LLVM 24.0.0git
EHPersonalities.cpp
Go to the documentation of this file.
1//===- EHPersonalities.cpp - Compute EH-related information ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "llvm/IR/CFG.h"
12#include "llvm/IR/Constants.h"
13#include "llvm/IR/Function.h"
15#include "llvm/IR/Module.h"
16#include "llvm/Support/Debug.h"
19using namespace llvm;
20
21/// See if the given exception handling personality function is one that we
22/// understand. If so, return a description of it; otherwise return Unknown.
24 const GlobalValue *F =
25 Pers ? dyn_cast<GlobalValue>(Pers->stripPointerCasts()) : nullptr;
26 if (!F || !F->getValueType() || !F->getValueType()->isFunctionTy())
28
29 StringRef Name = F->getName();
30 if (F->getParent()->getTargetTriple().isWindowsArm64EC()) {
31 // ARM64EC function symbols are mangled by prefixing them with "#".
32 // Demangle them by skipping this prefix.
33 Name.consume_front("#");
34 }
35
37 .Case("__gnat_eh_personality", EHPersonality::GNU_Ada)
38 .Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
39 .Case("__gxx_personality_seh0", EHPersonality::GNU_CXX)
40 .Case("__gxx_personality_sj0", EHPersonality::GNU_CXX_SjLj)
41 .Case("__gcc_personality_v0", EHPersonality::GNU_C)
42 .Case("__gcc_personality_seh0", EHPersonality::GNU_C)
43 .Case("__gcc_personality_sj0", EHPersonality::GNU_C_SjLj)
44 .Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
45 .Case("_except_handler3", EHPersonality::MSVC_X86SEH)
46 .Case("_except_handler4", EHPersonality::MSVC_X86SEH)
47 .Case("__C_specific_handler", EHPersonality::MSVC_TableSEH)
48 .Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX)
49 .Case("ProcessCLRException", EHPersonality::CoreCLR)
50 // Rust mangles its personality function, so we can't test exact equality.
51 .EndsWith("rust_eh_personality", EHPersonality::Rust)
52 .Case("__gxx_wasm_personality_v0", EHPersonality::Wasm_CXX)
53 .Case("__xlcxx_personality_v1", EHPersonality::XL_CXX)
54 .Case("__zos_cxx_personality_v2", EHPersonality::ZOS_CXX)
55 .Case("_d_eh_personality_wasm", EHPersonality::Wasm_D)
57}
58
60 switch (Pers) {
62 return "__gnat_eh_personality";
64 return "__gxx_personality_v0";
66 return "__gxx_personality_sj0";
68 return "__gcc_personality_v0";
70 return "__gcc_personality_sj0";
72 return "__objc_personality_v0";
74 return "_except_handler3";
76 return "__C_specific_handler";
78 return "__CxxFrameHandler3";
80 return "ProcessCLRException";
83 "Cannot get personality name of Rust personality, since it is mangled");
85 return "__gxx_wasm_personality_v0";
87 return "__xlcxx_personality_v1";
89 return "__zos_cxx_personality_v2";
91 return "_d_eh_personality_wasm";
93 llvm_unreachable("Unknown EHPersonality!");
94 }
95
96 llvm_unreachable("Invalid EHPersonality!");
97}
98
100 if (T.isPS5())
102 else
104}
105
107 EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn());
108 // We can't simplify any invokes to nounwind functions if the personality
109 // function wants to catch asynch exceptions. The nounwind attribute only
110 // implies that the function does not throw synchronous exceptions.
111
112 // Cannot simplify CXX Personality under AsynchEH
113 const llvm::Module *M = (const llvm::Module *)F->getParent();
114 bool EHa = M->getModuleFlag("eh-asynch");
115 return !EHa && !isAsynchronousEHPersonality(Personality);
116}
117
120 BasicBlock *EntryBlock = &F.getEntryBlock();
122
123 // Build up the color map, which maps each block to its set of 'colors'.
124 // For any block B the "colors" of B are the set of funclets F (possibly
125 // including a root "funclet" representing the main function) such that
126 // F will need to directly contain B or a copy of B (where the term "directly
127 // contain" is used to distinguish from being "transitively contained" in
128 // a nested funclet).
129 //
130 // Note: Despite not being a funclet in the truest sense, a catchswitch is
131 // considered to belong to its own funclet for the purposes of coloring.
132
133 DEBUG_WITH_TYPE("win-eh-prepare-coloring",
134 dbgs() << "\nColoring funclets for " << F.getName() << "\n");
135
136 Worklist.push_back({EntryBlock, EntryBlock});
137
138 while (!Worklist.empty()) {
139 BasicBlock *Visiting;
140 BasicBlock *Color;
141 std::tie(Visiting, Color) = Worklist.pop_back_val();
142 DEBUG_WITH_TYPE("win-eh-prepare-coloring",
143 dbgs() << "Visiting " << Visiting->getName() << ", "
144 << Color->getName() << "\n");
145 BasicBlock::iterator VisitingHead = Visiting->getFirstNonPHIIt();
146 if (VisitingHead->isEHPad()) {
147 // Mark this funclet head as a member of itself.
148 Color = Visiting;
149 }
150 // Note that this is a member of the given color.
151 ColorVector &Colors = BlockColors[Visiting];
152 if (!is_contained(Colors, Color))
153 Colors.push_back(Color);
154 else
155 continue;
156
157 DEBUG_WITH_TYPE("win-eh-prepare-coloring",
158 dbgs() << " Assigned color \'" << Color->getName()
159 << "\' to block \'" << Visiting->getName()
160 << "\'.\n");
161
162 BasicBlock *SuccColor = Color;
163 Instruction *Terminator = Visiting->getTerminator();
164 if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) {
165 Value *ParentPad = CatchRet->getCatchSwitchParentPad();
166 if (isa<ConstantTokenNone>(ParentPad))
167 SuccColor = EntryBlock;
168 else
169 SuccColor = cast<Instruction>(ParentPad)->getParent();
170 }
171
172 for (BasicBlock *Succ : successors(Visiting))
173 Worklist.push_back({Succ, SuccColor});
174 }
175 return BlockColors;
176}
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define T
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition Debug.h:72
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & EndsWith(StringLiteral S, T Value)
void push_back(EltTy NewVal)
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:712
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI StringRef getEHPersonalityName(EHPersonality Pers)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto successors(const MachineBasicBlock *BB)
LLVM_ABI DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
LLVM_ABI bool canSimplifyInvokeNoUnwind(const Function *F)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
bool isAsynchronousEHPersonality(EHPersonality Pers)
Returns true if this personality function catches asynchronous exceptions.
TinyPtrVector< BasicBlock * > ColorVector
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
LLVM_ABI EHPersonality getDefaultEHPersonality(const Triple &T)