Skip to content

Commit 36b2004

Browse files
committed
[CIR] Implement function personality attribute and its lowering
1 parent 0d0280b commit 36b2004

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
@@ -2676,6 +2676,10 @@ def CIR_FuncOp : CIR_Op<"func", [
26762676
The `always_inline` attribute marks a function that should always be inlined.
26772677
The `inline_hint` attribute suggests that the function should be inlined.
26782678

2679+
The `personality` attribute specifies the personality function to use for
2680+
exception handling. This is a symbol reference to the personality function
2681+
(e.g., `@__gxx_personality_v0` for C++ exceptions).
2682+
26792683
Example:
26802684

26812685
```mlir
@@ -2722,6 +2726,7 @@ def CIR_FuncOp : CIR_Op<"func", [
27222726
OptionalAttr<DictArrayAttr>:$arg_attrs,
27232727
OptionalAttr<DictArrayAttr>:$res_attrs,
27242728
OptionalAttr<FlatSymbolRefAttr>:$aliasee,
2729+
OptionalAttr<FlatSymbolRefAttr>:$personality,
27252730
CIR_OptionalPriorityAttr:$global_ctor_priority,
27262731
CIR_OptionalPriorityAttr:$global_dtor_priority,
27272732
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; }
@@ -274,6 +273,7 @@ struct MissingFeatures {
274273

275274
static bool fpConstraints() { return false; }
276275
static bool generateDebugInfo() { return false; }
276+
static bool getRuntimeFunctionDecl() { return false; }
277277
static bool globalViewIndices() { return false; }
278278
static bool globalViewIntLowering() { return false; }
279279
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
189+
getPersonalityFn(CIRGenModule &cgm, 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 &&
@@ -640,10 +652,14 @@ void CIRGenFunction::populateCatchHandlersIfRequired(cir::TryOp tryOp) {
640652
assert(ehStack.requiresCatchOrCleanup());
641653
assert(!ehStack.empty());
642654

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

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

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,14 +2301,27 @@ void CIRGenModule::setCXXSpecialMemberAttr(
23012301
}
23022302
}
23032303

2304+
static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
2305+
cir::FuncOp funcOp, StringRef name) {
2306+
// In Windows Itanium environments, try to mark runtime functions
2307+
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
2308+
// will link their standard library statically or dynamically. Marking
2309+
// functions imported when they are not imported can cause linker errors
2310+
// and warnings.
2311+
if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
2312+
!cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
2313+
assert(!cir::MissingFeatures::getRuntimeFunctionDecl());
2314+
assert(!cir::MissingFeatures::setDLLStorageClass());
2315+
assert(!cir::MissingFeatures::opGlobalDLLImportExport());
2316+
}
2317+
}
2318+
23042319
cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
23052320
StringRef name, mlir::ArrayAttr,
2306-
[[maybe_unused]] bool isLocal,
2321+
bool isLocal,
23072322
bool assumeConvergent) {
23082323
if (assumeConvergent)
23092324
errorNYI("createRuntimeFunction: assumeConvergent");
2310-
if (isLocal)
2311-
errorNYI("createRuntimeFunction: local");
23122325

23132326
cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
23142327
/*forVtable=*/false);
@@ -2317,7 +2330,7 @@ cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
23172330
// TODO(cir): set the attributes of the function.
23182331
assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());
23192332
assert(!cir::MissingFeatures::opFuncCallingConv());
2320-
assert(!cir::MissingFeatures::opGlobalDLLImportExport());
2333+
setWindowsItaniumDLLImport(*this, isLocal, entry, name);
23212334
entry.setDSOLocal(true);
23222335
}
23232336

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,18 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
19391939
hasAlias = true;
19401940
}
19411941

1942+
mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
1943+
if (parser.parseOptionalKeyword("personality").succeeded()) {
1944+
if (parser.parseLParen().failed())
1945+
return failure();
1946+
mlir::StringAttr personalityAttr;
1947+
if (parser.parseOptionalSymbolName(personalityAttr).failed())
1948+
return failure();
1949+
state.addAttribute(personalityNameAttr, FlatSymbolRefAttr::get(personalityAttr));
1950+
if (parser.parseRParen().failed())
1951+
return failure();
1952+
}
1953+
19421954
auto parseGlobalDtorCtor =
19431955
[&](StringRef keyword,
19441956
llvm::function_ref<void(std::optional<int> prio)> createAttr)
@@ -2140,6 +2152,12 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
21402152
p << ")";
21412153
}
21422154

2155+
if (std::optional<StringRef> personalityName = getPersonality()) {
2156+
p << " personality(";
2157+
p.printSymbolName(*personalityName);
2158+
p << ")";
2159+
}
2160+
21432161
if (auto specialMemberAttr = getCxxSpecialMember()) {
21442162
p << " special_member<";
21452163
p.printAttribute(*specialMemberAttr);

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

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,10 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
20152015
fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
20162016
}
20172017

2018+
// Transfer personality attribute from CIR to LLVM if present
2019+
if (std::optional<llvm::StringRef> personality = op.getPersonality())
2020+
fn.setPersonality(*personality);
2021+
20182022
fn.setVisibility_(lowerCIRVisibilityToLLVMVisibility(
20192023
op.getGlobalVisibility()));
20202024

@@ -3342,22 +3346,6 @@ mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
33423346
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
33433347
rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
33443348

3345-
// Landing pads are required to be in LLVM functions with personality
3346-
// attribute.
3347-
// TODO(cir): for now hardcode personality creation in order to start
3348-
// adding exception tests, once we annotate CIR with such information,
3349-
// change it to be in FuncOp lowering instead.
3350-
mlir::OpBuilder::InsertionGuard guard(rewriter);
3351-
// Insert personality decl before the current function.
3352-
rewriter.setInsertionPoint(llvmFn);
3353-
auto personalityFnTy =
3354-
mlir::LLVM::LLVMFunctionType::get(rewriter.getI32Type(), {},
3355-
/*isVarArg=*/true);
3356-
3357-
const StringRef fnName = "__gxx_personality_v0";
3358-
createLLVMFuncOpIfNotExist(rewriter, op, fnName, personalityFnTy);
3359-
llvmFn.setPersonality(fnName);
3360-
33613349
return mlir::success();
33623350
}
33633351

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)