Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2676,6 +2676,10 @@ def CIR_FuncOp : CIR_Op<"func", [
The `always_inline` attribute marks a function that should always be inlined.
The `inline_hint` attribute suggests that the function should be inlined.

The `personality` attribute specifies the personality function to use for
exception handling. This is a symbol reference to the personality function
(e.g., `@__gxx_personality_v0` for C++ exceptions).

Example:

```mlir
Expand Down Expand Up @@ -2722,6 +2726,7 @@ def CIR_FuncOp : CIR_Op<"func", [
OptionalAttr<DictArrayAttr>:$arg_attrs,
OptionalAttr<DictArrayAttr>:$res_attrs,
OptionalAttr<FlatSymbolRefAttr>:$aliasee,
OptionalAttr<FlatSymbolRefAttr>:$personality,
CIR_OptionalPriorityAttr:$global_ctor_priority,
CIR_OptionalPriorityAttr:$global_dtor_priority,
OptionalAttr<CIR_CXXSpecialMemberAttr>:$cxx_special_member
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ struct MissingFeatures {
static bool opFuncNoReturn() { return false; }
static bool setFunctionAttributes() { return false; }
static bool setLLVMFunctionFEnvAttributes() { return false; }
static bool setFunctionPersonality() { return false; }

// CallOp handling
static bool opCallAggregateArgs() { return false; }
Expand Down Expand Up @@ -274,6 +273,7 @@ struct MissingFeatures {

static bool fpConstraints() { return false; }
static bool generateDebugInfo() { return false; }
static bool getRuntimeFunctionDecl() { return false; }
static bool globalViewIndices() { return false; }
static bool globalViewIntLowering() { return false; }
static bool handleBuiltinICEArguments() { return false; }
Expand Down
20 changes: 18 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ const EHPersonality &EHPersonality::get(CIRGenFunction &cgf) {
return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));
}

static llvm::StringRef getPersonalityFn(CIRGenModule &cgm,
const EHPersonality &personality) {
// Create the personality function type: i32 (...)
mlir::Type i32Ty = cgm.getBuilder().getI32Type();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to test this or does it require additional implementation?

auto funcTy = cir::FuncType::get({}, i32Ty, /*isVarArg=*/true);

cir::FuncOp personalityFn = cgm.createRuntimeFunction(
funcTy, personality.personalityFn, mlir::ArrayAttr(), /*isLocal=*/true);

return personalityFn.getSymName();
}

void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) {
const llvm::Triple &triple = getTarget().getTriple();
if (cgm.getLangOpts().OpenMPIsTargetDevice &&
Expand Down Expand Up @@ -640,10 +652,14 @@ void CIRGenFunction::populateCatchHandlersIfRequired(cir::TryOp tryOp) {
assert(ehStack.requiresCatchOrCleanup());
assert(!ehStack.empty());

assert(!cir::MissingFeatures::setFunctionPersonality());
const EHPersonality &personality = EHPersonality::get(*this);

// Set personality function if not already set
auto funcOp = mlir::cast<cir::FuncOp>(curFn);
if (!funcOp.getPersonality())
funcOp.setPersonality(getPersonalityFn(cgm, personality));

// CIR does not cache landing pads.
const EHPersonality &personality = EHPersonality::get(*this);
if (personality.usesFuncletPads()) {
cgm.errorNYI("getInvokeDestImpl: usesFuncletPads");
} else {
Expand Down
21 changes: 17 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2301,14 +2301,27 @@ void CIRGenModule::setCXXSpecialMemberAttr(
}
}

static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
cir::FuncOp funcOp, StringRef name) {
// In Windows Itanium environments, try to mark runtime functions
// dllimport. For Mingw and MSVC, don't. We don't really know if the user
// will link their standard library statically or dynamically. Marking
// functions imported when they are not imported can cause linker errors
// and warnings.
if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
!cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
assert(!cir::MissingFeatures::getRuntimeFunctionDecl());
assert(!cir::MissingFeatures::setDLLStorageClass());
assert(!cir::MissingFeatures::opGlobalDLLImportExport());
}
}

cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
StringRef name, mlir::ArrayAttr,
[[maybe_unused]] bool isLocal,
bool isLocal,
bool assumeConvergent) {
if (assumeConvergent)
errorNYI("createRuntimeFunction: assumeConvergent");
if (isLocal)
errorNYI("createRuntimeFunction: local");

cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
/*forVtable=*/false);
Expand All @@ -2317,7 +2330,7 @@ cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
// TODO(cir): set the attributes of the function.
assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());
assert(!cir::MissingFeatures::opFuncCallingConv());
assert(!cir::MissingFeatures::opGlobalDLLImportExport());
setWindowsItaniumDLLImport(*this, isLocal, entry, name);
entry.setDSOLocal(true);
}

Expand Down
19 changes: 19 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,19 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
hasAlias = true;
}

mlir::StringAttr personalityNameAttr = getPersonalityAttrName(state.name);
if (parser.parseOptionalKeyword("personality").succeeded()) {
if (parser.parseLParen().failed())
return failure();
mlir::StringAttr personalityAttr;
if (parser.parseOptionalSymbolName(personalityAttr).failed())
return failure();
state.addAttribute(personalityNameAttr,
FlatSymbolRefAttr::get(personalityAttr));
if (parser.parseRParen().failed())
return failure();
}

auto parseGlobalDtorCtor =
[&](StringRef keyword,
llvm::function_ref<void(std::optional<int> prio)> createAttr)
Expand Down Expand Up @@ -2140,6 +2153,12 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
p << ")";
}

if (std::optional<StringRef> personalityName = getPersonality()) {
p << " personality(";
p.printSymbolName(*personalityName);
p << ")";
}

if (auto specialMemberAttr = getCxxSpecialMember()) {
p << " special_member<";
p.printAttribute(*specialMemberAttr);
Expand Down
31 changes: 8 additions & 23 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2015,9 +2015,11 @@ mlir::LogicalResult CIRToLLVMFuncOpLowering::matchAndRewrite(
fn.setAlwaysInline(*inlineKind == cir::InlineKind::AlwaysInline);
}

fn.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
getContext(), lowerCIRVisibilityToLLVMVisibility(
op.getGlobalVisibilityAttr().getValue())));
if (std::optional<llvm::StringRef> personality = op.getPersonality())
fn.setPersonality(*personality);

fn.setVisibility_(
lowerCIRVisibilityToLLVMVisibility(op.getGlobalVisibility()));

rewriter.inlineRegionBefore(op.getBody(), fn.getBody(), fn.end());
if (failed(rewriter.convertRegionTypes(&fn.getBody(), *typeConverter,
Expand Down Expand Up @@ -2161,14 +2163,13 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
}
}

// Rewrite op.
mlir::LLVM::Visibility visibility =
lowerCIRVisibilityToLLVMVisibility(op.getGlobalVisibility());
mlir::SymbolRefAttr comdatAttr = getComdatAttr(op, rewriter);
auto newOp = rewriter.replaceOpWithNewOp<mlir::LLVM::GlobalOp>(
op, llvmType, isConst, linkage, symbol, init.value_or(mlir::Attribute()),
alignment, addrSpace, isDsoLocal, isThreadLocal, comdatAttr, attributes);
newOp.setVisibility_Attr(mlir::LLVM::VisibilityAttr::get(
getContext(), lowerCIRVisibilityToLLVMVisibility(
op.getGlobalVisibilityAttr().getValue())));
newOp.setVisibility_(visibility);

return mlir::success();
}
Expand Down Expand Up @@ -3344,22 +3345,6 @@ mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
rewriter.replaceOp(op, mlir::ValueRange{slot, selector});

// Landing pads are required to be in LLVM functions with personality
// attribute.
// TODO(cir): for now hardcode personality creation in order to start
// adding exception tests, once we annotate CIR with such information,
// change it to be in FuncOp lowering instead.
mlir::OpBuilder::InsertionGuard guard(rewriter);
// Insert personality decl before the current function.
rewriter.setInsertionPoint(llvmFn);
auto personalityFnTy =
mlir::LLVM::LLVMFunctionType::get(rewriter.getI32Type(), {},
/*isVarArg=*/true);

const StringRef fnName = "__gxx_personality_v0";
createLLVMFuncOpIfNotExist(rewriter, op, fnName, personalityFnTy);
llvmFn.setPersonality(fnName);

return mlir::success();
}

Expand Down
8 changes: 8 additions & 0 deletions clang/test/CIR/IR/func.cir
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ cir.func @intfunc() -> !s32i {
cir.func @a_empty() alias(@empty)
// CHECK: cir.func @a_empty() alias(@empty)

// Should print/parse function personality.
cir.func @personality_func() personality(@__gxx_personality_v0) {
cir.return
}
// CHECK: cir.func @personality_func() personality(@__gxx_personality_v0) {
// CHECK: cir.return
// CHECK: }

// int scopes() {
// {
// {
Expand Down
9 changes: 6 additions & 3 deletions clang/test/CIR/Lowering/eh-inflight.cir
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
// RUN: cir-opt %s -cir-to-llvm -o %t.cir

!s32i = !cir.int<s, 32>
!u8i = !cir.int<u, 8>

module {

cir.func private @__gxx_personality_v0(...) -> !s32i

// CHECK: llvm.func @__gxx_personality_v0(...) -> i32

cir.func @inflight_exception() {
cir.func @inflight_exception() personality(@__gxx_personality_v0) {
%exception_ptr, %type_id = cir.eh.inflight_exception
cir.return
}
Expand All @@ -19,7 +22,7 @@ cir.func @inflight_exception() {
// CHECK: llvm.return
// CHECK: }

cir.func @inflight_exception_with_cleanup() {
cir.func @inflight_exception_with_cleanup() personality(@__gxx_personality_v0) {
%exception_ptr, %type_id = cir.eh.inflight_exception cleanup
cir.return
}
Expand All @@ -35,7 +38,7 @@ cir.func @inflight_exception_with_cleanup() {
cir.global "private" constant external @_ZTIi : !cir.ptr<!u8i>
cir.global "private" constant external @_ZTIPKc : !cir.ptr<!u8i>

cir.func @inflight_exception_with_catch_type_list() {
cir.func @inflight_exception_with_catch_type_list() personality(@__gxx_personality_v0) {
%exception_ptr, %type_id = cir.eh.inflight_exception [@_ZTIi, @_ZTIPKc]
cir.return
}
Expand Down
Loading