[llvm] r335006 - [WebAssembly] Add more utility functions

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 18 17:32:03 PDT 2018


Author: aheejin
Date: Mon Jun 18 17:32:03 2018
New Revision: 335006

URL: http://llvm.org/viewvc/llvm-project?rev=335006&view=rev
Log:
[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

Modified:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.h

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp?rev=335006&r1=335005&r2=335006&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGSort.cpp Mon Jun 18 17:32:03 2018
@@ -253,7 +253,7 @@ static void SortBlocks(MachineFunction &
       assert(OnStack.count(MLI.getLoopFor(&MBB)) &&
              "Blocks must be nested in their loops");
     }
-    while (OnStack.size() > 1 && &MBB == LoopBottom(OnStack.back()))
+    while (OnStack.size() > 1 && &MBB == WebAssembly::getBottom(OnStack.back()))
       OnStack.pop_back();
   }
   assert(OnStack.pop_back_val() == nullptr &&

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp?rev=335006&r1=335005&r2=335006&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp Mon Jun 18 17:32:03 2018
@@ -127,7 +127,8 @@ static void PlaceBlockMarker(
   // Decide where in Header to put the BLOCK.
   MachineBasicBlock::iterator InsertPos;
   MachineLoop *HeaderLoop = MLI.getLoopFor(Header);
-  if (HeaderLoop && MBB.getNumber() > LoopBottom(HeaderLoop)->getNumber()) {
+  if (HeaderLoop &&
+      MBB.getNumber() > WebAssembly::getBottom(HeaderLoop)->getNumber()) {
     // Header is the header of a loop that does not lexically contain MBB, so
     // the BLOCK needs to be above the LOOP, after any END constructs.
     InsertPos = Header->begin();
@@ -181,7 +182,7 @@ static void PlaceLoopMarker(
 
   // The operand of a LOOP is the first block after the loop. If the loop is the
   // bottom of the function, insert a dummy block at the end.
-  MachineBasicBlock *Bottom = LoopBottom(Loop);
+  MachineBasicBlock *Bottom = WebAssembly::getBottom(Loop);
   auto Iter = std::next(MachineFunction::iterator(Bottom));
   if (Iter == MF.end()) {
     MachineBasicBlock *Label = MF.CreateMachineBasicBlock();

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp?rev=335006&r1=335005&r2=335006&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp Mon Jun 18 17:32:03 2018
@@ -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 MachineI
          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 M
   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;
   }
 }
 
-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::isThrow(const MachineInstr &MI) {
+  switch (MI.getOpcode()) {
+  case WebAssembly::THROW_I32:
+  case WebAssembly::THROW_I64:
+    return true;
+  default:
+    return false;
+  }
+}
+
+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;
 }

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.h?rev=335006&r1=335005&r2=335006&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.h (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.h Mon Jun 18 17:32:03 2018
@@ -16,11 +16,10 @@
 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYUTILITIES_H
 #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYUTILITIES_H
 
+#include "llvm/CodeGen/MachineBasicBlock.h"
+
 namespace llvm {
 
-class MachineBasicBlock;
-class MachineInstr;
-class MachineLoop;
 class WebAssemblyFunctionInfo;
 
 namespace WebAssembly {
@@ -29,15 +28,45 @@ bool isArgument(const MachineInstr &MI);
 bool isCopy(const MachineInstr &MI);
 bool isTee(const MachineInstr &MI);
 bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI);
+bool isCallDirect(const MachineInstr &MI);
 bool isCallIndirect(const MachineInstr &MI);
+bool isMarker(const MachineInstr &MI);
+bool isThrow(const MachineInstr &MI);
+bool isRethrow(const MachineInstr &MI);
+bool isCatch(const MachineInstr &MI);
+bool mayThrow(const MachineInstr &MI);
+
+/// Returns the operand number of a callee, assuming the argument is a call
+/// instruction.
+unsigned getCalleeOpNo(const MachineInstr &MI);
+
+/// Returns if the given BB is a single BB terminate pad which starts with a
+/// 'catch' instruction.
+bool isCatchTerminatePad(const MachineBasicBlock &MBB);
+/// Returns if the given BB is a single BB terminate pad which starts with a
+/// 'catch_all' insrtruction.
+bool isCatchAllTerminatePad(const MachineBasicBlock &MBB);
+
+// Exception-related function names
+extern const char *const ClangCallTerminateFn;
+extern const char *const CxaBeginCatchFn;
+extern const char *const CxaRethrowFn;
+extern const char *const StdTerminateFn;
+extern const char *const PersonalityWrapperFn;
+
+/// Return the "bottom" block of an entity, which can be either a MachineLoop or
+/// WebAssemblyException. This differs from MachineLoop::getBottomBlock in that
+/// it works even if the entity is discontiguous.
+template <typename T> MachineBasicBlock *getBottom(const T *Unit) {
+  MachineBasicBlock *Bottom = Unit->getHeader();
+  for (MachineBasicBlock *MBB : Unit->blocks())
+    if (MBB->getNumber() > Bottom->getNumber())
+      Bottom = MBB;
+  return Bottom;
+}
 
 } // end namespace WebAssembly
 
-/// Return the "bottom" block of a loop. This differs from
-/// MachineLoop::getBottomBlock in that it works even if the loop is
-/// discontiguous.
-MachineBasicBlock *LoopBottom(const MachineLoop *Loop);
-
 } // end namespace llvm
 
 #endif




More information about the llvm-commits mailing list