llvm.org GIT mirror llvm / c430c83
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335005 91177308-0d34-0410-b5e6-96231b3b80d8 Heejin Ahn 2 years ago
5 changed file(s) with 180 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
7272 class TargetMachine;
7373 class TargetRegisterClass;
7474 class TargetSubtargetInfo;
75 struct WasmEHFuncInfo;
7576 struct WinEHFuncInfo;
7677
7778 template <> struct ilist_alloc_traits {
244245 // Keep track of jump tables for switch instructions
245246 MachineJumpTableInfo *JumpTableInfo;
246247
248 // Keeps track of Wasm exception handling related data. This will be null for
249 // functions that aren't using a wasm EH personality.
250 WasmEHFuncInfo *WasmEHInfo = nullptr;
251
247252 // Keeps track of Windows exception handling related data. This will be null
248253 // for functions that aren't using a funclet-based EH personality.
249254 WinEHFuncInfo *WinEHInfo = nullptr;
431436 MachineConstantPool *getConstantPool() { return ConstantPool; }
432437 const MachineConstantPool *getConstantPool() const { return ConstantPool; }
433438
439 /// getWasmEHFuncInfo - Return information about how the current function uses
440 /// Wasm exception handling. Returns null for functions that don't use wasm
441 /// exception handling.
442 const WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; }
443 WasmEHFuncInfo *getWasmEHFuncInfo() { return WasmEHInfo; }
444
434445 /// getWinEHFuncInfo - Return information about how the current function uses
435446 /// Windows exception handling. Returns null for functions that don't use
436447 /// funclets for exception handling.
0 //===--- llvm/CodeGen/WasmEHFuncInfo.h --------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Data structures for Wasm exception handling schemes.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H
14 #define LLVM_CODEGEN_WASMEHFUNCINFO_H
15
16 namespace llvm {
17
18 using BBOrMBB = PointerUnion;
19
20 struct WasmEHFuncInfo {
21 // When there is an entry , if an exception is not caught by A, it
22 // should next unwind to the EH pad B.
23 DenseMap EHPadUnwindMap;
24 // For entry , A is a BB with an instruction that may throw
25 // (invoke/cleanupret in LLVM IR, call/rethrow in the backend) and B is an EH
26 // pad that A unwinds to.
27 DenseMap ThrowUnwindMap;
28
29 // Helper functions
30 const BasicBlock *getEHPadUnwindDest(const BasicBlock *BB) const {
31 return EHPadUnwindMap.lookup(BB).get();
32 }
33 void setEHPadUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) {
34 EHPadUnwindMap[BB] = Dest;
35 }
36 const BasicBlock *getThrowUnwindDest(BasicBlock *BB) const {
37 return ThrowUnwindMap.lookup(BB).get();
38 }
39 void setThrowUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) {
40 ThrowUnwindMap[BB] = Dest;
41 }
42 bool hasEHPadUnwindDest(const BasicBlock *BB) const {
43 return EHPadUnwindMap.count(BB);
44 }
45 bool hasThrowUnwindDest(const BasicBlock *BB) const {
46 return ThrowUnwindMap.count(BB);
47 }
48
49 MachineBasicBlock *getEHPadUnwindDest(MachineBasicBlock *MBB) const {
50 return EHPadUnwindMap.lookup(MBB).get();
51 }
52 void setEHPadUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) {
53 EHPadUnwindMap[MBB] = Dest;
54 }
55 MachineBasicBlock *getThrowUnwindDest(MachineBasicBlock *MBB) const {
56 return ThrowUnwindMap.lookup(MBB).get();
57 }
58 void setThrowUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) {
59 ThrowUnwindMap[MBB] = Dest;
60 }
61 bool hasEHPadUnwindDest(MachineBasicBlock *MBB) const {
62 return EHPadUnwindMap.count(MBB);
63 }
64 bool hasThrowUnwindDest(MachineBasicBlock *MBB) const {
65 return ThrowUnwindMap.count(MBB);
66 }
67 };
68
69 // Analyze the IR in the given function to build WasmEHFuncInfo.
70 void calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &FuncInfo);
71
72 }; // namespace llvm
73
74 #endif // LLVM_CODEGEN_WASMEHFUNCINFO_H
3636 #include "llvm/CodeGen/TargetLowering.h"
3737 #include "llvm/CodeGen/TargetRegisterInfo.h"
3838 #include "llvm/CodeGen/TargetSubtargetInfo.h"
39 #include "llvm/CodeGen/WasmEHFuncInfo.h"
3940 #include "llvm/CodeGen/WinEHFuncInfo.h"
4041 #include "llvm/Config/llvm-config.h"
4142 #include "llvm/IR/Attributes.h"
174175 WinEHInfo = new (Allocator) WinEHFuncInfo();
175176 }
176177
178 if (isScopedEHPersonality(classifyEHPersonality(
179 F.hasPersonalityFn() ? F.getPersonalityFn() : nullptr))) {
180 WasmEHInfo = new (Allocator) WasmEHFuncInfo();
181 }
182
177183 assert(Target.isCompatibleDataLayout(getDataLayout()) &&
178184 "Can't create a MachineFunction using a Module with a "
179185 "Target-incompatible DataLayout attached\n");
2222 #include "llvm/CodeGen/TargetLowering.h"
2323 #include "llvm/CodeGen/TargetRegisterInfo.h"
2424 #include "llvm/CodeGen/TargetSubtargetInfo.h"
25 #include "llvm/CodeGen/WasmEHFuncInfo.h"
2526 #include "llvm/CodeGen/WinEHFuncInfo.h"
2627 #include "llvm/IR/DataLayout.h"
2728 #include "llvm/IR/DerivedTypes.h"
116117 H.CatchObj.FrameIndex = INT_MAX;
117118 }
118119 }
120 }
121 if (Personality == EHPersonality::Wasm_CXX) {
122 WasmEHFuncInfo &EHInfo = *MF->getWasmEHFuncInfo();
123 calculateWasmEHInfo(&fn, EHInfo);
119124 }
120125
121126 // Initialize the mapping of values to registers. This is only set up for
281286 }
282287 }
283288
284 if (!isFuncletEHPersonality(Personality))
285 return;
286
287 WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo();
288
289 // Map all BB references in the WinEH data to MBBs.
290 for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
291 for (WinEHHandlerType &H : TBME.HandlerArray) {
292 if (H.Handler)
293 H.Handler = MBBMap[H.Handler.get()];
294 }
295 }
296 for (CxxUnwindMapEntry &UME : EHInfo.CxxUnwindMap)
297 if (UME.Cleanup)
298 UME.Cleanup = MBBMap[UME.Cleanup.get()];
299 for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
300 const BasicBlock *BB = UME.Handler.get();
301 UME.Handler = MBBMap[BB];
302 }
303 for (ClrEHUnwindMapEntry &CME : EHInfo.ClrEHUnwindMap) {
304 const BasicBlock *BB = CME.Handler.get();
305 CME.Handler = MBBMap[BB];
289 if (isFuncletEHPersonality(Personality)) {
290 WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo();
291
292 // Map all BB references in the WinEH data to MBBs.
293 for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
294 for (WinEHHandlerType &H : TBME.HandlerArray) {
295 if (H.Handler)
296 H.Handler = MBBMap[H.Handler.get()];
297 }
298 }
299 for (CxxUnwindMapEntry &UME : EHInfo.CxxUnwindMap)
300 if (UME.Cleanup)
301 UME.Cleanup = MBBMap[UME.Cleanup.get()];
302 for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
303 const auto *BB = UME.Handler.get();
304 UME.Handler = MBBMap[BB];
305 }
306 for (ClrEHUnwindMapEntry &CME : EHInfo.ClrEHUnwindMap) {
307 const auto *BB = CME.Handler.get();
308 CME.Handler = MBBMap[BB];
309 }
310 }
311
312 else if (Personality == EHPersonality::Wasm_CXX) {
313 WasmEHFuncInfo &EHInfo = *MF->getWasmEHFuncInfo();
314 // Map all BB references in the WinEH data to MBBs.
315 DenseMap NewMap;
316 for (auto &KV : EHInfo.EHPadUnwindMap) {
317 const auto *Src = KV.first.get();
318 const auto *Dst = KV.second.get();
319 NewMap[MBBMap[Src]] = MBBMap[Dst];
320 }
321 EHInfo.EHPadUnwindMap = std::move(NewMap);
322 NewMap.clear();
323 for (auto &KV : EHInfo.ThrowUnwindMap) {
324 const auto *Src = KV.first.get();
325 const auto *Dst = KV.second.get();
326 NewMap[MBBMap[Src]] = MBBMap[Dst];
327 }
328 EHInfo.ThrowUnwindMap = std::move(NewMap);
306329 }
307330 }
308331
115115 #include "llvm/CodeGen/Passes.h"
116116 #include "llvm/CodeGen/TargetLowering.h"
117117 #include "llvm/CodeGen/TargetSubtargetInfo.h"
118 #include "llvm/CodeGen/WasmEHFuncInfo.h"
118119 #include "llvm/IR/Dominators.h"
119120 #include "llvm/IR/IRBuilder.h"
120121 #include "llvm/IR/Intrinsics.h"
328329 GetSelectorCI->replaceAllUsesWith(Selector);
329330 GetSelectorCI->eraseFromParent();
330331 }
332
333 void llvm::calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &EHInfo) {
334 for (const auto &BB : *F) {
335 if (!BB.isEHPad())
336 continue;
337 const Instruction *Pad = BB.getFirstNonPHI();
338
339 // If an exception is not caught by a catchpad (i.e., it is a foreign
340 // exception), it will unwind to its parent catchswitch's unwind
341 // destination. We don't record an unwind destination for cleanuppads
342 // because every exception should be caught by it.
343 if (const auto *CatchPad = dyn_cast(Pad)) {
344 const auto *UnwindBB = CatchPad->getCatchSwitch()->getUnwindDest();
345 if (!UnwindBB)
346 continue;
347 const Instruction *UnwindPad = UnwindBB->getFirstNonPHI();
348 if (const auto *CatchSwitch = dyn_cast(UnwindPad))
349 // Currently there should be only one handler per a catchswitch.
350 EHInfo.setEHPadUnwindDest(&BB, *CatchSwitch->handlers().begin());
351 else // cleanuppad
352 EHInfo.setEHPadUnwindDest(&BB, UnwindBB);
353 }
354 }
355
356 // Record the unwind destination for invoke and cleanupret instructions.
357 for (const auto &BB : *F) {
358 const Instruction *TI = BB.getTerminator();
359 BasicBlock *UnwindBB = nullptr;
360 if (const auto *Invoke = dyn_cast(TI))
361 UnwindBB = Invoke->getUnwindDest();
362 else if (const auto *CleanupRet = dyn_cast(TI))
363 UnwindBB = CleanupRet->getUnwindDest();
364 if (!UnwindBB)
365 continue;
366 const Instruction *UnwindPad = UnwindBB->getFirstNonPHI();
367 if (const auto *CatchSwitch = dyn_cast(UnwindPad))
368 // Currently there should be only one handler per a catchswitch.
369 EHInfo.setThrowUnwindDest(&BB, *CatchSwitch->handlers().begin());
370 else // cleanuppad
371 EHInfo.setThrowUnwindDest(&BB, UnwindBB);
372 }
373 }