Skip to content

Commit b0658b1

Browse files
authored
[CIR][NFC] Upstream EHPersonality for function (#164883)
Upstream the EHPersonality class for a function as a prerequisite for working with the handlers Issue #154992
1 parent 51fcb9d commit b0658b1

File tree

3 files changed

+216
-0
lines changed

3 files changed

+216
-0
lines changed

clang/lib/CIR/CodeGen/CIRGenCleanup.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H
1616

1717
#include "Address.h"
18+
#include "CIRGenModule.h"
1819
#include "EHScopeStack.h"
1920
#include "mlir/IR/Value.h"
2021

@@ -257,5 +258,53 @@ inline void EHScopeStack::popCatch() {
257258
deallocate(EHCatchScope::getSizeForNumHandlers(scope.getNumHandlers()));
258259
}
259260

261+
/// The exceptions personality for a function.
262+
struct EHPersonality {
263+
const char *personalityFn = nullptr;
264+
265+
// If this is non-null, this personality requires a non-standard
266+
// function for rethrowing an exception after a catchall cleanup.
267+
// This function must have prototype void(void*).
268+
const char *catchallRethrowFn = nullptr;
269+
270+
static const EHPersonality &get(CIRGenModule &cgm,
271+
const clang::FunctionDecl *fd);
272+
static const EHPersonality &get(CIRGenFunction &cgf);
273+
274+
static const EHPersonality GNU_C;
275+
static const EHPersonality GNU_C_SJLJ;
276+
static const EHPersonality GNU_C_SEH;
277+
static const EHPersonality GNU_ObjC;
278+
static const EHPersonality GNU_ObjC_SJLJ;
279+
static const EHPersonality GNU_ObjC_SEH;
280+
static const EHPersonality GNUstep_ObjC;
281+
static const EHPersonality GNU_ObjCXX;
282+
static const EHPersonality NeXT_ObjC;
283+
static const EHPersonality GNU_CPlusPlus;
284+
static const EHPersonality GNU_CPlusPlus_SJLJ;
285+
static const EHPersonality GNU_CPlusPlus_SEH;
286+
static const EHPersonality MSVC_except_handler;
287+
static const EHPersonality MSVC_C_specific_handler;
288+
static const EHPersonality MSVC_CxxFrameHandler3;
289+
static const EHPersonality GNU_Wasm_CPlusPlus;
290+
static const EHPersonality XL_CPlusPlus;
291+
static const EHPersonality ZOS_CPlusPlus;
292+
293+
/// Does this personality use landingpads or the family of pad instructions
294+
/// designed to form funclets?
295+
bool usesFuncletPads() const {
296+
return isMSVCPersonality() || isWasmPersonality();
297+
}
298+
299+
bool isMSVCPersonality() const {
300+
return this == &MSVC_except_handler || this == &MSVC_C_specific_handler ||
301+
this == &MSVC_CxxFrameHandler3;
302+
}
303+
304+
bool isWasmPersonality() const { return this == &GNU_Wasm_CPlusPlus; }
305+
306+
bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; }
307+
};
308+
260309
} // namespace clang::CIRGen
261310
#endif // CLANG_LIB_CIR_CODEGEN_CIRGENCLEANUP_H

clang/lib/CIR/CodeGen/CIRGenException.cpp

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,171 @@
1818
using namespace clang;
1919
using namespace clang::CIRGen;
2020

21+
const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr};
22+
const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0",
23+
nullptr};
24+
const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0",
25+
nullptr};
26+
const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0",
27+
nullptr};
28+
const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0",
29+
nullptr};
30+
const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ = {
31+
"__gxx_personality_sj0", nullptr};
32+
const EHPersonality EHPersonality::GNU_CPlusPlus_SEH = {
33+
"__gxx_personality_seh0", nullptr};
34+
const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0",
35+
"objc_exception_throw"};
36+
const EHPersonality EHPersonality::GNU_ObjC_SJLJ = {
37+
"__gnu_objc_personality_sj0", "objc_exception_throw"};
38+
const EHPersonality EHPersonality::GNU_ObjC_SEH = {
39+
"__gnu_objc_personality_seh0", "objc_exception_throw"};
40+
const EHPersonality EHPersonality::GNU_ObjCXX = {
41+
"__gnustep_objcxx_personality_v0", nullptr};
42+
const EHPersonality EHPersonality::GNUstep_ObjC = {
43+
"__gnustep_objc_personality_v0", nullptr};
44+
const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3",
45+
nullptr};
46+
const EHPersonality EHPersonality::MSVC_C_specific_handler = {
47+
"__C_specific_handler", nullptr};
48+
const EHPersonality EHPersonality::MSVC_CxxFrameHandler3 = {
49+
"__CxxFrameHandler3", nullptr};
50+
const EHPersonality EHPersonality::GNU_Wasm_CPlusPlus = {
51+
"__gxx_wasm_personality_v0", nullptr};
52+
const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",
53+
nullptr};
54+
const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",
55+
nullptr};
56+
57+
static const EHPersonality &getCPersonality(const TargetInfo &target,
58+
const CodeGenOptions &cgOpts) {
59+
const llvm::Triple &triple = target.getTriple();
60+
if (triple.isWindowsMSVCEnvironment())
61+
return EHPersonality::MSVC_CxxFrameHandler3;
62+
if (cgOpts.hasSjLjExceptions())
63+
return EHPersonality::GNU_C_SJLJ;
64+
if (cgOpts.hasDWARFExceptions())
65+
return EHPersonality::GNU_C;
66+
if (cgOpts.hasSEHExceptions())
67+
return EHPersonality::GNU_C_SEH;
68+
return EHPersonality::GNU_C;
69+
}
70+
71+
static const EHPersonality &getObjCPersonality(const TargetInfo &target,
72+
const LangOptions &langOpts,
73+
const CodeGenOptions &cgOpts) {
74+
const llvm::Triple &triple = target.getTriple();
75+
if (triple.isWindowsMSVCEnvironment())
76+
return EHPersonality::MSVC_CxxFrameHandler3;
77+
78+
switch (langOpts.ObjCRuntime.getKind()) {
79+
case ObjCRuntime::FragileMacOSX:
80+
return getCPersonality(target, cgOpts);
81+
case ObjCRuntime::MacOSX:
82+
case ObjCRuntime::iOS:
83+
case ObjCRuntime::WatchOS:
84+
return EHPersonality::NeXT_ObjC;
85+
case ObjCRuntime::GNUstep:
86+
if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
87+
return EHPersonality::GNUstep_ObjC;
88+
[[fallthrough]];
89+
case ObjCRuntime::GCC:
90+
case ObjCRuntime::ObjFW:
91+
if (cgOpts.hasSjLjExceptions())
92+
return EHPersonality::GNU_ObjC_SJLJ;
93+
if (cgOpts.hasSEHExceptions())
94+
return EHPersonality::GNU_ObjC_SEH;
95+
return EHPersonality::GNU_ObjC;
96+
}
97+
llvm_unreachable("bad runtime kind");
98+
}
99+
100+
static const EHPersonality &getCXXPersonality(const TargetInfo &target,
101+
const CodeGenOptions &cgOpts) {
102+
const llvm::Triple &triple = target.getTriple();
103+
if (triple.isWindowsMSVCEnvironment())
104+
return EHPersonality::MSVC_CxxFrameHandler3;
105+
if (triple.isOSAIX())
106+
return EHPersonality::XL_CPlusPlus;
107+
if (cgOpts.hasSjLjExceptions())
108+
return EHPersonality::GNU_CPlusPlus_SJLJ;
109+
if (cgOpts.hasDWARFExceptions())
110+
return EHPersonality::GNU_CPlusPlus;
111+
if (cgOpts.hasSEHExceptions())
112+
return EHPersonality::GNU_CPlusPlus_SEH;
113+
if (cgOpts.hasWasmExceptions())
114+
return EHPersonality::GNU_Wasm_CPlusPlus;
115+
return EHPersonality::GNU_CPlusPlus;
116+
}
117+
118+
/// Determines the personality function to use when both C++
119+
/// and Objective-C exceptions are being caught.
120+
static const EHPersonality &getObjCXXPersonality(const TargetInfo &target,
121+
const LangOptions &langOpts,
122+
const CodeGenOptions &cgOpts) {
123+
if (target.getTriple().isWindowsMSVCEnvironment())
124+
return EHPersonality::MSVC_CxxFrameHandler3;
125+
126+
switch (langOpts.ObjCRuntime.getKind()) {
127+
// In the fragile ABI, just use C++ exception handling and hope
128+
// they're not doing crazy exception mixing.
129+
case ObjCRuntime::FragileMacOSX:
130+
return getCXXPersonality(target, cgOpts);
131+
132+
// The ObjC personality defers to the C++ personality for non-ObjC
133+
// handlers. Unlike the C++ case, we use the same personality
134+
// function on targets using (backend-driven) SJLJ EH.
135+
case ObjCRuntime::MacOSX:
136+
case ObjCRuntime::iOS:
137+
case ObjCRuntime::WatchOS:
138+
return getObjCPersonality(target, langOpts, cgOpts);
139+
140+
case ObjCRuntime::GNUstep:
141+
return EHPersonality::GNU_ObjCXX;
142+
143+
// The GCC runtime's personality function inherently doesn't support
144+
// mixed EH. Use the ObjC personality just to avoid returning null.
145+
case ObjCRuntime::GCC:
146+
case ObjCRuntime::ObjFW:
147+
return getObjCPersonality(target, langOpts, cgOpts);
148+
}
149+
llvm_unreachable("bad runtime kind");
150+
}
151+
152+
static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) {
153+
return triple.getArch() == llvm::Triple::x86
154+
? EHPersonality::MSVC_except_handler
155+
: EHPersonality::MSVC_C_specific_handler;
156+
}
157+
158+
const EHPersonality &EHPersonality::get(CIRGenModule &cgm,
159+
const FunctionDecl *fd) {
160+
const llvm::Triple &triple = cgm.getTarget().getTriple();
161+
const LangOptions &langOpts = cgm.getLangOpts();
162+
const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
163+
const TargetInfo &target = cgm.getTarget();
164+
165+
// Functions using SEH get an SEH personality.
166+
if (fd && fd->usesSEHTry())
167+
return getSEHPersonalityMSVC(triple);
168+
169+
if (langOpts.ObjC) {
170+
return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts)
171+
: getObjCPersonality(target, langOpts, cgOpts);
172+
}
173+
return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts)
174+
: getCPersonality(target, cgOpts);
175+
}
176+
177+
const EHPersonality &EHPersonality::get(CIRGenFunction &cgf) {
178+
const auto *fg = cgf.curCodeDecl;
179+
// For outlined finallys and filters, use the SEH personality in case they
180+
// contain more SEH. This mostly only affects finallys. Filters could
181+
// hypothetically use gnu statement expressions to sneak in nested SEH.
182+
fg = fg ? fg : cgf.curSEHParent.getDecl();
183+
return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));
184+
}
185+
21186
void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) {
22187
const llvm::Triple &triple = getTarget().getTriple();
23188
if (cgm.getLangOpts().OpenMPIsTargetDevice &&

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ class CIRGenFunction : public CIRGenTypeCache {
120120
/// Tracks function scope overall cleanup handling.
121121
EHScopeStack ehStack;
122122

123+
GlobalDecl curSEHParent;
124+
123125
llvm::DenseMap<const clang::ValueDecl *, clang::FieldDecl *>
124126
lambdaCaptureFields;
125127
clang::FieldDecl *lambdaThisCaptureField = nullptr;

0 commit comments

Comments
 (0)