Line data Source code
1 : //===- EHPersonalities.cpp - Compute EH-related information ---------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/Analysis/EHPersonalities.h"
11 : #include "llvm/ADT/StringSwitch.h"
12 : #include "llvm/IR/CFG.h"
13 : #include "llvm/IR/Constants.h"
14 : #include "llvm/IR/Function.h"
15 : #include "llvm/IR/Instructions.h"
16 : #include "llvm/Support/Debug.h"
17 : #include "llvm/Support/raw_ostream.h"
18 : using namespace llvm;
19 :
20 : /// See if the given exception handling personality function is one that we
21 : /// understand. If so, return a description of it; otherwise return Unknown.
22 4282439 : EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
23 : const Function *F =
24 4282439 : Pers ? dyn_cast<Function>(Pers->stripPointerCasts()) : nullptr;
25 : if (!F)
26 1048399 : return EHPersonality::Unknown;
27 6468080 : return StringSwitch<EHPersonality>(F->getName())
28 : .Case("__gnat_eh_personality", EHPersonality::GNU_Ada)
29 : .Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
30 : .Case("__gxx_personality_seh0", EHPersonality::GNU_CXX)
31 : .Case("__gxx_personality_sj0", EHPersonality::GNU_CXX_SjLj)
32 : .Case("__gcc_personality_v0", EHPersonality::GNU_C)
33 : .Case("__gcc_personality_seh0", EHPersonality::GNU_C)
34 : .Case("__gcc_personality_sj0", EHPersonality::GNU_C_SjLj)
35 : .Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
36 : .Case("_except_handler3", EHPersonality::MSVC_X86SEH)
37 : .Case("_except_handler4", EHPersonality::MSVC_X86SEH)
38 : .Case("__C_specific_handler", EHPersonality::MSVC_Win64SEH)
39 : .Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX)
40 : .Case("ProcessCLRException", EHPersonality::CoreCLR)
41 : .Case("rust_eh_personality", EHPersonality::Rust)
42 : .Case("__gxx_wasm_personality_v0", EHPersonality::Wasm_CXX)
43 : .Default(EHPersonality::Unknown);
44 : }
45 :
46 4 : StringRef llvm::getEHPersonalityName(EHPersonality Pers) {
47 4 : switch (Pers) {
48 0 : case EHPersonality::GNU_Ada: return "__gnat_eh_personality";
49 0 : case EHPersonality::GNU_CXX: return "__gxx_personality_v0";
50 0 : case EHPersonality::GNU_CXX_SjLj: return "__gxx_personality_sj0";
51 4 : case EHPersonality::GNU_C: return "__gcc_personality_v0";
52 0 : case EHPersonality::GNU_C_SjLj: return "__gcc_personality_sj0";
53 0 : case EHPersonality::GNU_ObjC: return "__objc_personality_v0";
54 0 : case EHPersonality::MSVC_X86SEH: return "_except_handler3";
55 0 : case EHPersonality::MSVC_Win64SEH: return "__C_specific_handler";
56 0 : case EHPersonality::MSVC_CXX: return "__CxxFrameHandler3";
57 0 : case EHPersonality::CoreCLR: return "ProcessCLRException";
58 0 : case EHPersonality::Rust: return "rust_eh_personality";
59 0 : case EHPersonality::Wasm_CXX: return "__gxx_wasm_personality_v0";
60 : case EHPersonality::Unknown: llvm_unreachable("Unknown EHPersonality!");
61 : }
62 :
63 0 : llvm_unreachable("Invalid EHPersonality!");
64 : }
65 :
66 4 : EHPersonality llvm::getDefaultEHPersonality(const Triple &T) {
67 4 : return EHPersonality::GNU_C;
68 : }
69 :
70 8195 : bool llvm::canSimplifyInvokeNoUnwind(const Function *F) {
71 8195 : EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn());
72 : // We can't simplify any invokes to nounwind functions if the personality
73 : // function wants to catch asynch exceptions. The nounwind attribute only
74 : // implies that the function does not throw synchronous exceptions.
75 8195 : return !isAsynchronousEHPersonality(Personality);
76 : }
77 :
78 325 : DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {
79 : SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;
80 : BasicBlock *EntryBlock = &F.getEntryBlock();
81 : DenseMap<BasicBlock *, ColorVector> BlockColors;
82 :
83 : // Build up the color map, which maps each block to its set of 'colors'.
84 : // For any block B the "colors" of B are the set of funclets F (possibly
85 : // including a root "funclet" representing the main function) such that
86 : // F will need to directly contain B or a copy of B (where the term "directly
87 : // contain" is used to distinguish from being "transitively contained" in
88 : // a nested funclet).
89 : //
90 : // Note: Despite not being a funclet in the truest sense, a catchswitch is
91 : // considered to belong to its own funclet for the purposes of coloring.
92 :
93 : DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
94 : << F.getName() << "\n");
95 :
96 325 : Worklist.push_back({EntryBlock, EntryBlock});
97 :
98 2752 : while (!Worklist.empty()) {
99 : BasicBlock *Visiting;
100 : BasicBlock *Color;
101 : std::tie(Visiting, Color) = Worklist.pop_back_val();
102 : DEBUG_WITH_TYPE("winehprepare-coloring",
103 : dbgs() << "Visiting " << Visiting->getName() << ", "
104 : << Color->getName() << "\n");
105 : Instruction *VisitingHead = Visiting->getFirstNonPHI();
106 : if (VisitingHead->isEHPad()) {
107 : // Mark this funclet head as a member of itself.
108 994 : Color = Visiting;
109 : }
110 : // Note that this is a member of the given color.
111 : ColorVector &Colors = BlockColors[Visiting];
112 2427 : if (!is_contained(Colors, Color))
113 1946 : Colors.push_back(Color);
114 : else
115 481 : continue;
116 :
117 : DEBUG_WITH_TYPE("winehprepare-coloring",
118 : dbgs() << " Assigned color \'" << Color->getName()
119 : << "\' to block \'" << Visiting->getName()
120 : << "\'.\n");
121 :
122 1946 : BasicBlock *SuccColor = Color;
123 1946 : Instruction *Terminator = Visiting->getTerminator();
124 : if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) {
125 : Value *ParentPad = CatchRet->getCatchSwitchParentPad();
126 308 : if (isa<ConstantTokenNone>(ParentPad))
127 : SuccColor = EntryBlock;
128 : else
129 22 : SuccColor = cast<Instruction>(ParentPad)->getParent();
130 : }
131 :
132 5994 : for (BasicBlock *Succ : successors(Visiting))
133 2102 : Worklist.push_back({Succ, SuccColor});
134 : }
135 325 : return BlockColors;
136 : }
|