[llvm] r335005 - [WebAssembly] Add WasmEHFuncInfo for unwind destination information
Heejin Ahn via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 18 17:26:39 PDT 2018
Author: aheejin
Date: Mon Jun 18 17:26:39 2018
New Revision: 335005
URL: http://llvm.org/viewvc/llvm-project?rev=335005&view=rev
Log:
[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
Added:
llvm/trunk/include/llvm/CodeGen/WasmEHFuncInfo.h
Modified:
llvm/trunk/include/llvm/CodeGen/MachineFunction.h
llvm/trunk/lib/CodeGen/MachineFunction.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
llvm/trunk/lib/CodeGen/WasmEHPrepare.cpp
Modified: llvm/trunk/include/llvm/CodeGen/MachineFunction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFunction.h?rev=335005&r1=335004&r2=335005&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineFunction.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineFunction.h Mon Jun 18 17:26:39 2018
@@ -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.
Added: llvm/trunk/include/llvm/CodeGen/WasmEHFuncInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/WasmEHFuncInfo.h?rev=335005&view=auto
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/WasmEHFuncInfo.h (added)
+++ llvm/trunk/include/llvm/CodeGen/WasmEHFuncInfo.h Mon Jun 18 17:26:39 2018
@@ -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
Modified: llvm/trunk/lib/CodeGen/MachineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineFunction.cpp?rev=335005&r1=335004&r2=335005&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineFunction.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineFunction.cpp Mon Jun 18 17:26:39 2018
@@ -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");
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=335005&r1=335004&r2=335005&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp Mon Jun 18 17:26:39 2018
@@ -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 Fun
}
}
}
+ 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 Fun
}
}
- if (!isFuncletEHPersonality(Personality))
- return;
-
- WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo();
+ if (isFuncletEHPersonality(Personality)) {
+ 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);
}
}
Modified: llvm/trunk/lib/CodeGen/WasmEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WasmEHPrepare.cpp?rev=335005&r1=335004&r2=335005&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WasmEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WasmEHPrepare.cpp Mon Jun 18 17:26:39 2018
@@ -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(BasicBl
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);
+ }
+}
More information about the llvm-commits
mailing list