forked from OSchip/llvm-project
[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
This commit is contained in:
parent
33c3fce592
commit
817811caae
|
@ -253,7 +253,7 @@ static void SortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI,
|
|||
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 &&
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
MachineBasicBlock *llvm::LoopBottom(const MachineLoop *Loop) {
|
||||
MachineBasicBlock *Bottom = Loop->getHeader();
|
||||
for (MachineBasicBlock *MBB : Loop->blocks())
|
||||
if (MBB->getNumber() > Bottom->getNumber())
|
||||
Bottom = MBB;
|
||||
return Bottom;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue