diff options
author | Heejin Ahn <aheejin@gmail.com> | 2018-06-19 00:32:03 +0000 |
---|---|---|
committer | Heejin Ahn <aheejin@gmail.com> | 2018-06-19 00:32:03 +0000 |
commit | 817811caae9175e088243450ce3b6e006ff337fe (patch) | |
tree | a14914d5ee05bacf574179695124b49fac1b0584 /llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp | |
parent | 33c3fce592cda760250f65fe5713fe3b01935f59 (diff) | |
download | llvm-817811caae9175e088243450ce3b6e006ff337fe.zip llvm-817811caae9175e088243450ce3b6e006ff337fe.tar.gz llvm-817811caae9175e088243450ce3b6e006ff337fe.tar.bz2 |
[WebAssembly] Add more utility functions
Summary:
Added more utility functions that will be used in EH-related passes Also
changed `LoopBottom` function to `getBottom` and uses templates to be
able to handle other classes as well, which will be used in CFGSort
later.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D48262
llvm-svn: 335006
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp | 157 |
1 files changed, 151 insertions, 6 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp index 0a81154..5944cea 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp @@ -18,6 +18,13 @@ #include "llvm/CodeGen/MachineLoopInfo.h" using namespace llvm; +const char *const WebAssembly::ClangCallTerminateFn = "__clang_call_terminate"; +const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch"; +const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow"; +const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev"; +const char *const WebAssembly::PersonalityWrapperFn = + "_Unwind_Wasm_CallPersonality"; + bool WebAssembly::isArgument(const MachineInstr &MI) { switch (MI.getOpcode()) { case WebAssembly::ARGUMENT_I32: @@ -71,6 +78,24 @@ bool WebAssembly::isChild(const MachineInstr &MI, MFI.isVRegStackified(Reg); } +bool WebAssembly::isCallDirect(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case WebAssembly::CALL_VOID: + case WebAssembly::CALL_I32: + case WebAssembly::CALL_I64: + case WebAssembly::CALL_F32: + case WebAssembly::CALL_F64: + case WebAssembly::CALL_v16i8: + case WebAssembly::CALL_v8i16: + case WebAssembly::CALL_v4i32: + case WebAssembly::CALL_v4f32: + case WebAssembly::CALL_EXCEPT_REF: + return true; + default: + return false; + } +} + bool WebAssembly::isCallIndirect(const MachineInstr &MI) { switch (MI.getOpcode()) { case WebAssembly::CALL_INDIRECT_VOID: @@ -82,16 +107,136 @@ bool WebAssembly::isCallIndirect(const MachineInstr &MI) { case WebAssembly::CALL_INDIRECT_v8i16: case WebAssembly::CALL_INDIRECT_v4i32: case WebAssembly::CALL_INDIRECT_v4f32: + case WebAssembly::CALL_INDIRECT_EXCEPT_REF: + return true; + default: + return false; + } +} + +unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case WebAssembly::CALL_VOID: + case WebAssembly::CALL_INDIRECT_VOID: + return 0; + case WebAssembly::CALL_I32: + case WebAssembly::CALL_I64: + case WebAssembly::CALL_F32: + case WebAssembly::CALL_F64: + case WebAssembly::CALL_EXCEPT_REF: + case WebAssembly::CALL_INDIRECT_I32: + case WebAssembly::CALL_INDIRECT_I64: + case WebAssembly::CALL_INDIRECT_F32: + case WebAssembly::CALL_INDIRECT_F64: + case WebAssembly::CALL_INDIRECT_EXCEPT_REF: + return 1; + default: + llvm_unreachable("Not a call instruction"); + } +} + +bool WebAssembly::isMarker(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case WebAssembly::BLOCK: + case WebAssembly::END_BLOCK: + case WebAssembly::LOOP: + case WebAssembly::END_LOOP: + case WebAssembly::TRY: + case WebAssembly::END_TRY: + return true; + default: + return false; + } +} + +bool WebAssembly::isThrow(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case WebAssembly::THROW_I32: + case WebAssembly::THROW_I64: return true; default: return false; } } -MachineBasicBlock *llvm::LoopBottom(const MachineLoop *Loop) { - MachineBasicBlock *Bottom = Loop->getHeader(); - for (MachineBasicBlock *MBB : Loop->blocks()) - if (MBB->getNumber() > Bottom->getNumber()) - Bottom = MBB; - return Bottom; +bool WebAssembly::isRethrow(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case WebAssembly::RETHROW: + case WebAssembly::RETHROW_TO_CALLER: + return true; + default: + return false; + } +} + +bool WebAssembly::isCatch(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case WebAssembly::CATCH_I32: + case WebAssembly::CATCH_I64: + case WebAssembly::CATCH_ALL: + return true; + default: + return false; + } +} + +bool WebAssembly::mayThrow(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case WebAssembly::THROW_I32: + case WebAssembly::THROW_I64: + case WebAssembly::RETHROW: + return true; + } + if (isCallIndirect(MI)) + return true; + if (!MI.isCall()) + return false; + + const MachineOperand &MO = MI.getOperand(getCalleeOpNo(MI)); + assert(MO.isGlobal()); + const auto *F = dyn_cast<Function>(MO.getGlobal()); + if (!F) + return true; + if (F->doesNotThrow()) + return false; + // These functions never throw + if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn || + F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn) + return false; + return true; +} + +bool WebAssembly::isCatchTerminatePad(const MachineBasicBlock &MBB) { + if (!MBB.isEHPad()) + return false; + bool SeenCatch = false; + for (auto &MI : MBB) { + if (MI.getOpcode() == WebAssembly::CATCH_I32 || + MI.getOpcode() == WebAssembly::CATCH_I64) + SeenCatch = true; + if (SeenCatch && MI.isCall()) { + const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI)); + if (CalleeOp.isGlobal() && + CalleeOp.getGlobal()->getName() == ClangCallTerminateFn) + return true; + } + } + return false; +} + +bool WebAssembly::isCatchAllTerminatePad(const MachineBasicBlock &MBB) { + if (!MBB.isEHPad()) + return false; + bool SeenCatchAll = false; + for (auto &MI : MBB) { + if (MI.getOpcode() == WebAssembly::CATCH_ALL) + SeenCatchAll = true; + if (SeenCatchAll && MI.isCall()) { + const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI)); + if (CalleeOp.isGlobal() && + CalleeOp.getGlobal()->getName() == StdTerminateFn) + return true; + } + } + return false; } |