aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2018-06-19 00:32:03 +0000
committerHeejin Ahn <aheejin@gmail.com>2018-06-19 00:32:03 +0000
commit817811caae9175e088243450ce3b6e006ff337fe (patch)
treea14914d5ee05bacf574179695124b49fac1b0584 /llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
parent33c3fce592cda760250f65fe5713fe3b01935f59 (diff)
downloadllvm-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.cpp157
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;
}