diff options
| author | 2019-01-27 16:42:12 +0000 | |
|---|---|---|
| committer | 2019-01-27 16:42:12 +0000 | |
| commit | b773203fb58f3ef282fb69c832d8710cab5bc82d (patch) | |
| tree | e75913f147570fbd75169647b144df85b88a038c /gnu/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp | |
| parent | tweak errno in previous (diff) | |
| download | wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip | |
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp')
| -rw-r--r-- | gnu/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp | 159 |
1 files changed, 152 insertions, 7 deletions
diff --git a/gnu/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp b/gnu/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp index e32772d491c..5944cea5abd 100644 --- a/gnu/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp +++ b/gnu/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file implements several utility functions for WebAssembly. +/// This file implements several utility functions for WebAssembly. /// //===----------------------------------------------------------------------===// @@ -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; } |
