mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-12 05:56:28 +00:00
[WebAssembly] Add WasmEHFuncInfo for unwind destination information
Summary: Add WasmEHFuncInfo and routines to calculate and fill in this struct to keep track of unwind destination information. This will be used in other EH related passes. Reviewers: dschuff Subscribers: sbc100, jgravelle-google, sunfish, chrib, llvm-commits Differential Revision: https://reviews.llvm.org/D48263 llvm-svn: 335005
This commit is contained in:
parent
c7da456a48
commit
4a721fef71
@ -73,6 +73,7 @@ class SlotIndexes;
|
||||
class TargetMachine;
|
||||
class TargetRegisterClass;
|
||||
class TargetSubtargetInfo;
|
||||
struct WasmEHFuncInfo;
|
||||
struct WinEHFuncInfo;
|
||||
|
||||
template <> struct ilist_alloc_traits<MachineBasicBlock> {
|
||||
@ -245,6 +246,10 @@ class MachineFunction {
|
||||
// Keep track of jump tables for switch instructions
|
||||
MachineJumpTableInfo *JumpTableInfo;
|
||||
|
||||
// Keeps track of Wasm exception handling related data. This will be null for
|
||||
// functions that aren't using a wasm EH personality.
|
||||
WasmEHFuncInfo *WasmEHInfo = nullptr;
|
||||
|
||||
// Keeps track of Windows exception handling related data. This will be null
|
||||
// for functions that aren't using a funclet-based EH personality.
|
||||
WinEHFuncInfo *WinEHInfo = nullptr;
|
||||
@ -432,6 +437,12 @@ public:
|
||||
MachineConstantPool *getConstantPool() { return ConstantPool; }
|
||||
const MachineConstantPool *getConstantPool() const { return ConstantPool; }
|
||||
|
||||
/// getWasmEHFuncInfo - Return information about how the current function uses
|
||||
/// Wasm exception handling. Returns null for functions that don't use wasm
|
||||
/// exception handling.
|
||||
const WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; }
|
||||
WasmEHFuncInfo *getWasmEHFuncInfo() { return WasmEHInfo; }
|
||||
|
||||
/// getWinEHFuncInfo - Return information about how the current function uses
|
||||
/// Windows exception handling. Returns null for functions that don't use
|
||||
/// funclets for exception handling.
|
||||
|
75
include/llvm/CodeGen/WasmEHFuncInfo.h
Normal file
75
include/llvm/CodeGen/WasmEHFuncInfo.h
Normal file
@ -0,0 +1,75 @@
|
||||
//===--- llvm/CodeGen/WasmEHFuncInfo.h --------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Data structures for Wasm exception handling schemes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H
|
||||
#define LLVM_CODEGEN_WASMEHFUNCINFO_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
using BBOrMBB = PointerUnion<const BasicBlock *, MachineBasicBlock *>;
|
||||
|
||||
struct WasmEHFuncInfo {
|
||||
// When there is an entry <A, B>, if an exception is not caught by A, it
|
||||
// should next unwind to the EH pad B.
|
||||
DenseMap<BBOrMBB, BBOrMBB> EHPadUnwindMap;
|
||||
// For entry <A, B>, A is a BB with an instruction that may throw
|
||||
// (invoke/cleanupret in LLVM IR, call/rethrow in the backend) and B is an EH
|
||||
// pad that A unwinds to.
|
||||
DenseMap<BBOrMBB, BBOrMBB> ThrowUnwindMap;
|
||||
|
||||
// Helper functions
|
||||
const BasicBlock *getEHPadUnwindDest(const BasicBlock *BB) const {
|
||||
return EHPadUnwindMap.lookup(BB).get<const BasicBlock *>();
|
||||
}
|
||||
void setEHPadUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) {
|
||||
EHPadUnwindMap[BB] = Dest;
|
||||
}
|
||||
const BasicBlock *getThrowUnwindDest(BasicBlock *BB) const {
|
||||
return ThrowUnwindMap.lookup(BB).get<const BasicBlock *>();
|
||||
}
|
||||
void setThrowUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) {
|
||||
ThrowUnwindMap[BB] = Dest;
|
||||
}
|
||||
bool hasEHPadUnwindDest(const BasicBlock *BB) const {
|
||||
return EHPadUnwindMap.count(BB);
|
||||
}
|
||||
bool hasThrowUnwindDest(const BasicBlock *BB) const {
|
||||
return ThrowUnwindMap.count(BB);
|
||||
}
|
||||
|
||||
MachineBasicBlock *getEHPadUnwindDest(MachineBasicBlock *MBB) const {
|
||||
return EHPadUnwindMap.lookup(MBB).get<MachineBasicBlock *>();
|
||||
}
|
||||
void setEHPadUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) {
|
||||
EHPadUnwindMap[MBB] = Dest;
|
||||
}
|
||||
MachineBasicBlock *getThrowUnwindDest(MachineBasicBlock *MBB) const {
|
||||
return ThrowUnwindMap.lookup(MBB).get<MachineBasicBlock *>();
|
||||
}
|
||||
void setThrowUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) {
|
||||
ThrowUnwindMap[MBB] = Dest;
|
||||
}
|
||||
bool hasEHPadUnwindDest(MachineBasicBlock *MBB) const {
|
||||
return EHPadUnwindMap.count(MBB);
|
||||
}
|
||||
bool hasThrowUnwindDest(MachineBasicBlock *MBB) const {
|
||||
return ThrowUnwindMap.count(MBB);
|
||||
}
|
||||
};
|
||||
|
||||
// Analyze the IR in the given function to build WasmEHFuncInfo.
|
||||
void calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &FuncInfo);
|
||||
|
||||
}; // namespace llvm
|
||||
|
||||
#endif // LLVM_CODEGEN_WASMEHFUNCINFO_H
|
@ -37,6 +37,7 @@
|
||||
#include "llvm/CodeGen/TargetLowering.h"
|
||||
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
||||
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
||||
#include "llvm/CodeGen/WasmEHFuncInfo.h"
|
||||
#include "llvm/CodeGen/WinEHFuncInfo.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/IR/Attributes.h"
|
||||
@ -175,6 +176,11 @@ void MachineFunction::init() {
|
||||
WinEHInfo = new (Allocator) WinEHFuncInfo();
|
||||
}
|
||||
|
||||
if (isScopedEHPersonality(classifyEHPersonality(
|
||||
F.hasPersonalityFn() ? F.getPersonalityFn() : nullptr))) {
|
||||
WasmEHInfo = new (Allocator) WasmEHFuncInfo();
|
||||
}
|
||||
|
||||
assert(Target.isCompatibleDataLayout(getDataLayout()) &&
|
||||
"Can't create a MachineFunction using a Module with a "
|
||||
"Target-incompatible DataLayout attached\n");
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "llvm/CodeGen/TargetLowering.h"
|
||||
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
||||
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
||||
#include "llvm/CodeGen/WasmEHFuncInfo.h"
|
||||
#include "llvm/CodeGen/WinEHFuncInfo.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
@ -118,6 +119,10 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Personality == EHPersonality::Wasm_CXX) {
|
||||
WasmEHFuncInfo &EHInfo = *MF->getWasmEHFuncInfo();
|
||||
calculateWasmEHInfo(&fn, EHInfo);
|
||||
}
|
||||
|
||||
// Initialize the mapping of values to registers. This is only set up for
|
||||
// instruction values that are used outside of the block that defines
|
||||
@ -282,28 +287,46 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
|
||||
}
|
||||
}
|
||||
|
||||
if (!isFuncletEHPersonality(Personality))
|
||||
return;
|
||||
if (isFuncletEHPersonality(Personality)) {
|
||||
WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo();
|
||||
|
||||
WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo();
|
||||
|
||||
// Map all BB references in the WinEH data to MBBs.
|
||||
for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
|
||||
for (WinEHHandlerType &H : TBME.HandlerArray) {
|
||||
if (H.Handler)
|
||||
H.Handler = MBBMap[H.Handler.get<const BasicBlock *>()];
|
||||
// Map all BB references in the WinEH data to MBBs.
|
||||
for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
|
||||
for (WinEHHandlerType &H : TBME.HandlerArray) {
|
||||
if (H.Handler)
|
||||
H.Handler = MBBMap[H.Handler.get<const BasicBlock *>()];
|
||||
}
|
||||
}
|
||||
for (CxxUnwindMapEntry &UME : EHInfo.CxxUnwindMap)
|
||||
if (UME.Cleanup)
|
||||
UME.Cleanup = MBBMap[UME.Cleanup.get<const BasicBlock *>()];
|
||||
for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
|
||||
const auto *BB = UME.Handler.get<const BasicBlock *>();
|
||||
UME.Handler = MBBMap[BB];
|
||||
}
|
||||
for (ClrEHUnwindMapEntry &CME : EHInfo.ClrEHUnwindMap) {
|
||||
const auto *BB = CME.Handler.get<const BasicBlock *>();
|
||||
CME.Handler = MBBMap[BB];
|
||||
}
|
||||
}
|
||||
for (CxxUnwindMapEntry &UME : EHInfo.CxxUnwindMap)
|
||||
if (UME.Cleanup)
|
||||
UME.Cleanup = MBBMap[UME.Cleanup.get<const BasicBlock *>()];
|
||||
for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
|
||||
const BasicBlock *BB = UME.Handler.get<const BasicBlock *>();
|
||||
UME.Handler = MBBMap[BB];
|
||||
}
|
||||
for (ClrEHUnwindMapEntry &CME : EHInfo.ClrEHUnwindMap) {
|
||||
const BasicBlock *BB = CME.Handler.get<const BasicBlock *>();
|
||||
CME.Handler = MBBMap[BB];
|
||||
|
||||
else if (Personality == EHPersonality::Wasm_CXX) {
|
||||
WasmEHFuncInfo &EHInfo = *MF->getWasmEHFuncInfo();
|
||||
// Map all BB references in the WinEH data to MBBs.
|
||||
DenseMap<BBOrMBB, BBOrMBB> NewMap;
|
||||
for (auto &KV : EHInfo.EHPadUnwindMap) {
|
||||
const auto *Src = KV.first.get<const BasicBlock *>();
|
||||
const auto *Dst = KV.second.get<const BasicBlock *>();
|
||||
NewMap[MBBMap[Src]] = MBBMap[Dst];
|
||||
}
|
||||
EHInfo.EHPadUnwindMap = std::move(NewMap);
|
||||
NewMap.clear();
|
||||
for (auto &KV : EHInfo.ThrowUnwindMap) {
|
||||
const auto *Src = KV.first.get<const BasicBlock *>();
|
||||
const auto *Dst = KV.second.get<const BasicBlock *>();
|
||||
NewMap[MBBMap[Src]] = MBBMap[Dst];
|
||||
}
|
||||
EHInfo.ThrowUnwindMap = std::move(NewMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,7 @@
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/TargetLowering.h"
|
||||
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
||||
#include "llvm/CodeGen/WasmEHFuncInfo.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
@ -329,3 +330,45 @@ void WasmEHPrepare::prepareEHPad(BasicBlock *BB, unsigned Index) {
|
||||
GetSelectorCI->replaceAllUsesWith(Selector);
|
||||
GetSelectorCI->eraseFromParent();
|
||||
}
|
||||
|
||||
void llvm::calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &EHInfo) {
|
||||
for (const auto &BB : *F) {
|
||||
if (!BB.isEHPad())
|
||||
continue;
|
||||
const Instruction *Pad = BB.getFirstNonPHI();
|
||||
|
||||
// If an exception is not caught by a catchpad (i.e., it is a foreign
|
||||
// exception), it will unwind to its parent catchswitch's unwind
|
||||
// destination. We don't record an unwind destination for cleanuppads
|
||||
// because every exception should be caught by it.
|
||||
if (const auto *CatchPad = dyn_cast<CatchPadInst>(Pad)) {
|
||||
const auto *UnwindBB = CatchPad->getCatchSwitch()->getUnwindDest();
|
||||
if (!UnwindBB)
|
||||
continue;
|
||||
const Instruction *UnwindPad = UnwindBB->getFirstNonPHI();
|
||||
if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(UnwindPad))
|
||||
// Currently there should be only one handler per a catchswitch.
|
||||
EHInfo.setEHPadUnwindDest(&BB, *CatchSwitch->handlers().begin());
|
||||
else // cleanuppad
|
||||
EHInfo.setEHPadUnwindDest(&BB, UnwindBB);
|
||||
}
|
||||
}
|
||||
|
||||
// Record the unwind destination for invoke and cleanupret instructions.
|
||||
for (const auto &BB : *F) {
|
||||
const Instruction *TI = BB.getTerminator();
|
||||
BasicBlock *UnwindBB = nullptr;
|
||||
if (const auto *Invoke = dyn_cast<InvokeInst>(TI))
|
||||
UnwindBB = Invoke->getUnwindDest();
|
||||
else if (const auto *CleanupRet = dyn_cast<CleanupReturnInst>(TI))
|
||||
UnwindBB = CleanupRet->getUnwindDest();
|
||||
if (!UnwindBB)
|
||||
continue;
|
||||
const Instruction *UnwindPad = UnwindBB->getFirstNonPHI();
|
||||
if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(UnwindPad))
|
||||
// Currently there should be only one handler per a catchswitch.
|
||||
EHInfo.setThrowUnwindDest(&BB, *CatchSwitch->handlers().begin());
|
||||
else // cleanuppad
|
||||
EHInfo.setThrowUnwindDest(&BB, UnwindBB);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user