diff options
Diffstat (limited to 'lib/Target/WebAssembly/WebAssemblyUtilities.cpp')
| -rw-r--r-- | lib/Target/WebAssembly/WebAssemblyUtilities.cpp | 159 | 
1 files changed, 152 insertions, 7 deletions
diff --git a/lib/Target/WebAssembly/WebAssemblyUtilities.cpp b/lib/Target/WebAssembly/WebAssemblyUtilities.cpp index e32772d491cf..5944cea5abd1 100644 --- a/lib/Target/WebAssembly/WebAssemblyUtilities.cpp +++ b/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;  }  | 
