Skip to content

Commit b2f3614

Browse files
authored
[CIR] Implement function personality attribute and its lowering (#171001)
1 parent d8d87b5 commit b2f3614

File tree

8 files changed

+77
-26
lines changed

8 files changed

+77
-26
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2746,6 +2746,10 @@ def CIR_FuncOp : CIR_Op<"func", [
27462746
The `always_inline` attribute marks a function that should always be inlined.
27472747
The `inline_hint` attribute suggests that the function should be inlined.
27482748

2749+
The `personality` attribute specifies the personality function to use for
2750+
exception handling. This is a symbol reference to the personality function
2751+
(e.g., `@__gxx_personality_v0` for C++ exceptions).
2752+
27492753
Example:
27502754

27512755
```mlir
@@ -2792,6 +2796,7 @@ def CIR_FuncOp : CIR_Op<"func", [
27922796
OptionalAttr<DictArrayAttr>:$arg_attrs,
27932797
OptionalAttr<DictArrayAttr>:$res_attrs,
27942798
OptionalAttr<FlatSymbolRefAttr>:$aliasee,
2799+
OptionalAttr<FlatSymbolRefAttr>:$personality,
27952800
CIR_OptionalPriorityAttr:$global_ctor_priority,
27962801
CIR_OptionalPriorityAttr:$global_dtor_priority,
27972802
OptionalAttr<CIR_CXXSpecialMemberAttr>:$cxx_special_member

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ struct MissingFeatures {
9393
static bool opFuncNoReturn() { return false; }
9494
static bool setFunctionAttributes() { return false; }
9595
static bool setLLVMFunctionFEnvAttributes() { return false; }
96-
static bool setFunctionPersonality() { return false; }
9796

9897
// CallOp handling
9998
static bool opCallAggregateArgs() { return false; }
@@ -279,6 +278,7 @@ struct MissingFeatures {
279278

280279
static bool fpConstraints() { return false; }
281280
static bool generateDebugInfo() { return false; }
281+
static bool getRuntimeFunctionDecl() { return false; }
282282
static bool globalViewIndices() { return false; }
283283
static bool globalViewIntLowering() { return false; }
284284
static bool handleBuiltinICEArguments() { return false; }

clang/lib/CIR/CodeGen/CIRGenException.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,18 @@ const EHPersonality &EHPersonality::get(CIRGenFunction &cgf) {
185185
return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));
186186
}
187187

188+
static llvm::StringRef getPersonalityFn(CIRGenModule &cgm,
189+
const EHPersonality &personality) {
190+
// Create the personality function type: i32 (...)
191+
mlir::Type i32Ty = cgm.getBuilder().getI32Type();
192+
auto funcTy = cir::FuncType::get({}, i32Ty, /*isVarArg=*/true);
193+
194+
cir::FuncOp personalityFn = cgm.createRuntimeFunction(
195+
funcTy, personality.personalityFn, mlir::ArrayAttr(), /*isLocal=*/true);
196+
197+
return personalityFn.getSymName();
198+
}
199+
188200
void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) {
189201
const llvm::Triple &triple = getTarget().getTriple();
190202
if (cgm.getLangOpts().OpenMPIsTargetDevice &&
@@ -641,10 +653,14 @@ void CIRGenFunction::populateCatchHandlersIfRequired(cir::TryOp tryOp) {
641653
assert(ehStack.requiresCatchOrCleanup());
642654
assert(!ehStack.empty());
643655

644-
assert(!cir::MissingFeatures::setFunctionPersonality());
656+
const EHPersonality &personality = EHPersonality::get(*this);
657+
658+
// Set personality function if not already set
659+
auto funcOp = mlir::cast<cir::FuncOp>(curFn);
660+
if (!funcOp.getPersonality())
661+
funcOp.setPersonality(getPersonalityFn(cgm, personality));
645662

646663
// CIR does not cache landing pads.
647-
const EHPersonality &personality = EHPersonality::get(*this);
648664
if (personality.usesFuncletPads()) {
649665
cgm.errorNYI("getInvokeDestImpl: usesFuncletPads");
650666
} else {

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2354,14 +2354,27 @@ void CIRGenModule::setCXXSpecialMemberAttr(
23542354
}
23552355
}
23562356

2357+
static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
2358+
cir::FuncOp funcOp, StringRef name) {
2359+
// In Windows Itanium environments, try to mark runtime functions
2360+
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
2361+
// will link their standard library statically or dynamically. Marking
2362+
// functions imported when they are not imported can cause linker errors
2363+
// and warnings.
2364+
if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
2365+
!cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
2366+
assert(!cir::MissingFeatures::getRuntimeFunctionDecl());
2367+
assert(!cir::MissingFeatures::setDLLStorageClass());
2368+
assert(!cir::MissingFeatures::opGlobalDLLImportExport());
2369+
}
2370+
}
2371+
23572372
cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
23582373
StringRef name, mlir::ArrayAttr,
2359-
[[maybe_unused]] bool isLocal,
2374+
bool isLocal,
23602375
bool assumeConvergent) {
23612376
if (assumeConvergent)
23622377
errorNYI("createRuntimeFunction: assumeConvergent");
2363-
if (isLocal)
2364-
errorNYI("createRuntimeFunction: local");
23652378

23662379
cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
23672380
/*forVtable=*/false);
@@ -2370,7 +2383,7 @@ cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
23702383
// TODO(cir): set the attributes of the function.
23712384
assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());
23722385
assert(!cir::MissingFeatures::opFuncCallingConv());
2373-
assert(!cir::MissingFeatures::opGlobalDLLImportExport());
2386+
setWindowsItaniumDLLImport(*this, isLocal, entry, name);
23742387
entry.setDSOLocal(true);
23752388
}
23762389

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,6 +1910,19 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
19101910
hasAlias = true;
19111911
}
19121912

1913+
mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
1914+
if (parser.parseOptionalKeyword("personality").succeeded()) {
1915+
if (parser.parseLParen().failed())
1916+
return failure();
1917+
mlir::StringAttr personalityAttr;
1918+
if (parser.parseOptionalSymbolName(personalityAttr).failed())
1919+
return failure();
1920+
state.addAttribute(personalityNameAttr,
1921+
FlatSymbolRefAttr::get(personalityAttr));
1922+
if (parser.parseRParen().failed())
1923+
return failure();
1924+
}
1925+
19131926
auto parseGlobalDtorCtor =
19141927
[&](StringRef keyword,
19151928
llvm::function_ref<void(std::optional<int> prio)> createAttr)
@@ -2111,6 +2124,12 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
21112124
p << ")";
21122125
}
21132126

2127+
if (std::optional<StringRef> personalityName = getPersonality()) {
2128+
p << " personality(";
2129+
p.printSymbolName(*personalityName);
2130+
p << ")";
2131+
}
2132+
21142133
if (auto specialMemberAttr = getCxxSpecialMember()) {
21152134
p << " special_member<";
21162135
p.printAttribute(*specialMemberAttr);

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,6 +2053,9 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
20532053
fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
20542054
}
20552055

2056+
if (std::optional<llvm::StringRef> personality = op.getPersonality())
2057+
fn.setPersonality(*personality);
2058+
20562059
fn.setVisibility_(
20572060
lowerCIRVisibilityToLLVMVisibility(op.getGlobalVisibility()));
20582061

@@ -3412,22 +3415,6 @@ mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
34123415
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
34133416
rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
34143417

3415-
// Landing pads are required to be in LLVM functions with personality
3416-
// attribute.
3417-
// TODO(cir): for now hardcode personality creation in order to start
3418-
// adding exception tests, once we annotate CIR with such information,
3419-
// change it to be in FuncOp lowering instead.
3420-
mlir::OpBuilder::InsertionGuard guard(rewriter);
3421-
// Insert personality decl before the current function.
3422-
rewriter.setInsertionPoint(llvmFn);
3423-
auto personalityFnTy =
3424-
mlir::LLVM::LLVMFunctionType::get(rewriter.getI32Type(), {},
3425-
/*isVarArg=*/true);
3426-
3427-
const StringRef fnName = "__gxx_personality_v0";
3428-
createLLVMFuncOpIfNotExist(rewriter, op, fnName, personalityFnTy);
3429-
llvmFn.setPersonality(fnName);
3430-
34313418
return mlir::success();
34323419
}
34333420

clang/test/CIR/IR/func.cir

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ cir.func @intfunc() -> !s32i {
4444
cir.func @a_empty() alias(@empty)
4545
// CHECK: cir.func @a_empty() alias(@empty)
4646

47+
// Should print/parse function personality.
48+
cir.func @personality_func() personality(@__gxx_personality_v0) {
49+
cir.return
50+
}
51+
// CHECK: cir.func @personality_func() personality(@__gxx_personality_v0) {
52+
// CHECK: cir.return
53+
// CHECK: }
54+
4755
// int scopes() {
4856
// {
4957
// {

clang/test/CIR/Lowering/eh-inflight.cir

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
// RUN: cir-opt %s -cir-to-llvm -o %t.cir
22

3+
!s32i = !cir.int<s, 32>
34
!u8i = !cir.int<u, 8>
45

56
module {
67

8+
cir.func private @__gxx_personality_v0(...) -> !s32i
9+
710
// CHECK: llvm.func @__gxx_personality_v0(...) -> i32
811

9-
cir.func @inflight_exception() {
12+
cir.func @inflight_exception() personality(@__gxx_personality_v0) {
1013
%exception_ptr, %type_id = cir.eh.inflight_exception
1114
cir.return
1215
}
@@ -19,7 +22,7 @@ cir.func @inflight_exception() {
1922
// CHECK: llvm.return
2023
// CHECK: }
2124

22-
cir.func @inflight_exception_with_cleanup() {
25+
cir.func @inflight_exception_with_cleanup() personality(@__gxx_personality_v0) {
2326
%exception_ptr, %type_id = cir.eh.inflight_exception cleanup
2427
cir.return
2528
}
@@ -35,7 +38,7 @@ cir.func @inflight_exception_with_cleanup() {
3538
cir.global "private" constant external @_ZTIi : !cir.ptr<!u8i>
3639
cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i>
3740

38-
cir.func @inflight_exception_with_catch_type_list() {
41+
cir.func @inflight_exception_with_catch_type_list() personality(@__gxx_personality_v0) {
3942
%exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc]
4043
cir.return
4144
}

0 commit comments

Comments
 (0)