Skip to content

Commit ee785a0

Browse files
authored
[CIR] Fix Global Ctor/Dtor priority attributes (#1743)
- This fixes default value to be expected 65535 - Introduces DefaultGlobalCtorDtorPriority constant - Makes function to use I32Attr for priority instead of unnecessary attribute with reference to function
1 parent 17aa78d commit ee785a0

File tree

11 files changed

+136
-80
lines changed

11 files changed

+136
-80
lines changed

clang/include/clang/CIR/Dialect/IR/CIRAttrs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#include "clang/CIR/Interfaces/ASTAttrInterfaces.h"
2222
#include "clang/CIR/Interfaces/CIRTypeInterfaces.h"
2323

24+
namespace cir {
25+
inline constexpr uint32_t DefaultGlobalCtorDtorPriority = 65535;
26+
} // namespace cir
27+
2428
//===----------------------------------------------------------------------===//
2529
// CIR Dialect Attrs
2630
//===----------------------------------------------------------------------===//

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

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,42 +1207,50 @@ def CIR_UWTableAttr : CIR_EnumAttr<CIR_UWTableKind, "uwtable"> {
12071207
let cppClassName = "UWTableAttr";
12081208
}
12091209

1210-
class CIR_GlobalCtorDtor<string name, string attrMnemonic,
1211-
string sum, string desc>
1210+
class CIR_GlobalCtorDtor<string name, string attrMnemonic>
12121211
: CIR_Attr<"Global" # name, "global_" # attrMnemonic> {
1213-
let summary = sum;
1214-
let description = desc;
1215-
12161212
let parameters = (ins "mlir::StringAttr":$name, "int":$priority);
1217-
let assemblyFormat = [{
1218-
`<`
1219-
$name `,` $priority
1220-
`>`
1221-
}];
1213+
1214+
let skipDefaultBuilders = 1;
12221215
let builders = [
1223-
AttrBuilder<(ins "llvm::StringRef":$name,
1224-
CArg<"int", "65536">:$priority), [{
1216+
AttrBuilder<(ins
1217+
"llvm::StringRef":$name,
1218+
CArg<"int", "cir::DefaultGlobalCtorDtorPriority">:$priority), [{
12251219
return $_get($_ctxt, mlir::StringAttr::get($_ctxt, name), priority);
12261220
}]>,
1227-
AttrBuilderWithInferredContext<(ins "mlir::StringAttr":$name,
1228-
CArg<"int", "65536">:$priority), [{
1221+
AttrBuilderWithInferredContext<(ins
1222+
"mlir::StringAttr":$name,
1223+
CArg<"int", "cir::DefaultGlobalCtorDtorPriority">:$priority), [{
12291224
return $_get(name.getContext(), name, priority);
12301225
}]>
12311226
];
1227+
1228+
let assemblyFormat = [{
1229+
`<` $name `,` $priority `>`
1230+
}];
1231+
12321232
let extraClassDeclaration = [{
1233-
bool isDefaultPriority() const { return getPriority() == 65536; };
1233+
bool isDefaultPriority() const {
1234+
return getPriority() == cir::DefaultGlobalCtorDtorPriority;
1235+
};
12341236
}];
1235-
let skipDefaultBuilders = 1;
12361237
}
12371238

1238-
def GlobalCtorAttr : CIR_GlobalCtorDtor<"Ctor", "ctor",
1239-
"Marks a function as a global constructor",
1240-
"A function with this attribute executes before main()"
1241-
>;
1242-
def GlobalDtorAttr : CIR_GlobalCtorDtor<"Dtor", "dtor",
1243-
"Marks a function as a global destructor",
1244-
"A function with this attribute excutes before module unloading"
1245-
>;
1239+
def GlobalCtorAttr : CIR_GlobalCtorDtor<"Ctor", "ctor"> {
1240+
let summary = "Marks a function as a global constructor";
1241+
let description = [{
1242+
Marks the function as a global constructor in the module's constructor list.
1243+
It will be executed before main() is called.
1244+
}];
1245+
}
1246+
1247+
def GlobalDtorAttr : CIR_GlobalCtorDtor<"Dtor", "dtor"> {
1248+
let summary = "Marks a function as a global destructor";
1249+
let description = [{
1250+
Marks a function as a global destructor in the module dtors list.
1251+
The function will be executed before the module unloading.
1252+
}];
1253+
}
12461254

12471255
def BitfieldInfoAttr : CIR_Attr<"BitfieldInfo", "bitfield_info"> {
12481256
let summary = "Represents a bit field info";

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ class LLVMLoweringInfo {
8484
class CIR_Op<string mnemonic, list<Trait> traits = []> :
8585
Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;
8686

87+
//===----------------------------------------------------------------------===//
88+
// CIR Operation Traits
89+
//===----------------------------------------------------------------------===//
90+
91+
class HasAtMostOneOfAttrsPred<list<string> names> :
92+
CPred<!foldl("0", names, acc, name, acc # " + (" # name # " ? 1 : 0)")
93+
# " <= 1">;
94+
95+
class HasAtMostOneOfAttrs<list<string> names> : PredOpTrait<
96+
"has only one of the optional attributes: " # !interleave(names, ", "),
97+
HasAtMostOneOfAttrsPred<!foreach(name, names, "$" # name)>
98+
>;
99+
100+
87101
//===----------------------------------------------------------------------===//
88102
// CastOp
89103
//===----------------------------------------------------------------------===//
@@ -3597,9 +3611,17 @@ def CIR_CallingConv : CIR_I32EnumAttr<"CallingConv", "calling convention", [
35973611
I32EnumAttrCase<"PTXKernel", 5, "ptx_kernel">
35983612
]>;
35993613

3600-
def CIR_FuncOp : CIR_Op<"func", [
3614+
def CIR_OptionalPriorityAttr : OptionalAttr<
3615+
DefaultValuedAttr<
3616+
ConfinedAttr<I32Attr, [IntMinValue<101>, IntMaxValue<65535>]>,
3617+
"cir::DefaultGlobalCtorDtorPriority"
3618+
>
3619+
>;
3620+
3621+
def FuncOp : CIR_Op<"func", [
36013622
AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface,
36023623
DeclareOpInterfaceMethods<CIRGlobalValueInterface>,
3624+
HasAtMostOneOfAttrs<["global_ctor_priority", "global_dtor_priority"]>,
36033625
IsolatedFromAbove
36043626
]> {
36053627
let summary = "Declare or define a function";
@@ -3699,8 +3721,8 @@ def CIR_FuncOp : CIR_Op<"func", [
36993721
OptionalAttr<DictArrayAttr>:$arg_attrs,
37003722
OptionalAttr<DictArrayAttr>:$res_attrs,
37013723
OptionalAttr<FlatSymbolRefAttr>:$aliasee,
3702-
OptionalAttr<GlobalCtorAttr>:$global_ctor,
3703-
OptionalAttr<GlobalDtorAttr>:$global_dtor,
3724+
CIR_OptionalPriorityAttr:$global_ctor_priority,
3725+
CIR_OptionalPriorityAttr:$global_dtor_priority,
37043726
OptionalAttr<ArrayAttr>:$annotations,
37053727
OptionalAttr<AnyASTFunctionDeclAttr>:$ast
37063728
);

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -781,21 +781,20 @@ void CIRGenModule::emitGlobalFunctionDefinition(GlobalDecl gd,
781781
}
782782

783783
/// Track functions to be called before main() runs.
784-
void CIRGenModule::AddGlobalCtor(cir::FuncOp ctor, int priority) {
784+
void CIRGenModule::AddGlobalCtor(cir::FuncOp ctor,
785+
std::optional<int> priority) {
785786
// FIXME(cir): handle LexOrder and Associated data upon testcases.
786787
//
787788
// Traditional LLVM codegen directly adds the function to the list of global
788789
// ctors. In CIR we just add a global_ctor attribute to the function. The
789790
// global list is created in LoweringPrepare.
790791
//
791792
// FIXME(from traditional LLVM): Type coercion of void()* types.
792-
ctor->setAttr(
793-
ctor.getGlobalCtorAttrName(),
794-
cir::GlobalCtorAttr::get(&getMLIRContext(), ctor.getName(), priority));
793+
ctor.setGlobalCtorPriority(priority);
795794
}
796795

797796
/// Add a function to the list that will be called when the module is unloaded.
798-
void CIRGenModule::AddGlobalDtor(cir::FuncOp dtor, int priority,
797+
void CIRGenModule::AddGlobalDtor(cir::FuncOp dtor, std::optional<int> priority,
799798
bool isDtorAttrFunc) {
800799
assert(isDtorAttrFunc && "NYI");
801800
if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
@@ -805,9 +804,7 @@ void CIRGenModule::AddGlobalDtor(cir::FuncOp dtor, int priority,
805804
}
806805

807806
// FIXME(from traditional LLVM): Type coercion of void()* types.
808-
dtor->setAttr(
809-
dtor.getGlobalDtorAttrName(),
810-
cir::GlobalDtorAttr::get(&getMLIRContext(), dtor.getName(), priority));
807+
dtor.setGlobalDtorPriority(priority);
811808
}
812809

813810
mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,13 @@ class CIRGenModule : public CIRGenTypeCache {
265265
mlir::Operation *insertPoint = nullptr,
266266
cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage);
267267

268-
// FIXME: Hardcoding priority here is gross.
269-
void AddGlobalCtor(cir::FuncOp Ctor, int Priority = 65535);
270-
void AddGlobalDtor(cir::FuncOp Dtor, int Priority = 65535,
271-
bool IsDtorAttrFunc = false);
268+
/// Add a global constructor or destructor to the module.
269+
/// The priority is optional, if not specified, the default priority is used.
270+
void AddGlobalCtor(cir::FuncOp ctor,
271+
std::optional<int> priority = std::nullopt);
272+
void AddGlobalDtor(cir::FuncOp dtor,
273+
std::optional<int> priority = std::nullopt,
274+
bool isDtorAttrFunc = false);
272275

273276
// Return whether structured convergence intrinsics should be generated for
274277
// this target.

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

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,35 +2652,35 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
26522652
llvm::function_ref<void(std::optional<int> prio)> createAttr)
26532653
-> mlir::LogicalResult {
26542654
if (::mlir::succeeded(parser.parseOptionalKeyword(keyword))) {
2655-
std::optional<int> prio;
2655+
std::optional<int> priority;
26562656
if (mlir::succeeded(parser.parseOptionalLParen())) {
26572657
auto parsedPrio = mlir::FieldParser<int>::parse(parser);
26582658
if (mlir::failed(parsedPrio))
26592659
return parser.emitError(parser.getCurrentLocation(),
26602660
"failed to parse 'priority', of type 'int'");
2661-
prio = parsedPrio.value_or(int());
2661+
priority = parsedPrio.value_or(int());
26622662
// Parse literal ')'
26632663
if (parser.parseRParen())
26642664
return failure();
26652665
}
2666-
createAttr(prio);
2666+
createAttr(priority);
26672667
}
26682668
return success();
26692669
};
26702670

2671-
if (parseGlobalDtorCtor("global_ctor", [&](std::optional<int> prio) {
2672-
cir::GlobalCtorAttr globalCtorAttr =
2673-
prio ? cir::GlobalCtorAttr::get(nameAttr, *prio)
2674-
: cir::GlobalCtorAttr::get(nameAttr);
2675-
state.addAttribute(getGlobalCtorAttrName(state.name), globalCtorAttr);
2671+
if (parseGlobalDtorCtor("global_ctor", [&](std::optional<int> priority) {
2672+
auto globalCtorPriorityAttr = builder.getI32IntegerAttr(
2673+
priority ? *priority : DefaultGlobalCtorDtorPriority);
2674+
state.addAttribute(getGlobalCtorPriorityAttrName(state.name),
2675+
globalCtorPriorityAttr);
26762676
}).failed())
26772677
return failure();
26782678

2679-
if (parseGlobalDtorCtor("global_dtor", [&](std::optional<int> prio) {
2680-
cir::GlobalDtorAttr globalDtorAttr =
2681-
prio ? cir::GlobalDtorAttr::get(nameAttr, *prio)
2682-
: cir::GlobalDtorAttr::get(nameAttr);
2683-
state.addAttribute(getGlobalDtorAttrName(state.name), globalDtorAttr);
2679+
if (parseGlobalDtorCtor("global_dtor", [&](std::optional<int> priority) {
2680+
auto globalDtorPriorityAttr = builder.getI32IntegerAttr(
2681+
priority ? *priority : DefaultGlobalCtorDtorPriority);
2682+
state.addAttribute(getGlobalDtorPriorityAttrName(state.name),
2683+
globalDtorPriorityAttr);
26842684
}).failed())
26852685
return failure();
26862686

@@ -2794,9 +2794,9 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
27942794
// These are all omitted since they are custom printed already.
27952795
{getAliaseeAttrName(), getBuiltinAttrName(), getCoroutineAttrName(),
27962796
getDsoLocalAttrName(), getExtraAttrsAttrName(),
2797-
getFunctionTypeAttrName(), getGlobalCtorAttrName(),
2798-
getGlobalDtorAttrName(), getLambdaAttrName(), getLinkageAttrName(),
2799-
getCallingConvAttrName(), getNoProtoAttrName(),
2797+
getFunctionTypeAttrName(), getGlobalCtorPriorityAttrName(),
2798+
getGlobalDtorPriorityAttrName(), getLambdaAttrName(),
2799+
getLinkageAttrName(), getCallingConvAttrName(), getNoProtoAttrName(),
28002800
getSymVisibilityAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
28012801
getComdatAttrName(), getGlobalVisibilityAttrName(),
28022802
getAnnotationsAttrName()});
@@ -2813,16 +2813,16 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
28132813
p << ")";
28142814
}
28152815

2816-
if (auto globalCtor = getGlobalCtorAttr()) {
2816+
if (auto globalCtorPriority = getGlobalCtorPriority()) {
28172817
p << " global_ctor";
2818-
if (!globalCtor.isDefaultPriority())
2819-
p << "(" << globalCtor.getPriority() << ")";
2818+
if (globalCtorPriority.value() != DefaultGlobalCtorDtorPriority)
2819+
p << "(" << globalCtorPriority.value() << ")";
28202820
}
28212821

2822-
if (auto globalDtor = getGlobalDtorAttr()) {
2822+
if (auto globalDtorPriority = getGlobalDtorPriority()) {
28232823
p << " global_dtor";
2824-
if (!globalDtor.isDefaultPriority())
2825-
p << "(" << globalDtor.getPriority() << ")";
2824+
if (globalDtorPriority.value() != DefaultGlobalCtorDtorPriority)
2825+
p << "(" << globalDtorPriority.value() << ")";
28262826
}
28272827

28282828
if (!getExtraAttrs().getElements().empty()) {

clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,10 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> {
183183
llvm::StringMap<uint32_t> dynamicInitializerNames;
184184
llvm::SmallVector<FuncOp, 4> dynamicInitializers;
185185

186-
/// List of ctors to be called before main()
187-
llvm::SmallVector<mlir::Attribute, 4> globalCtorList;
188-
/// List of dtors to be called when unloading module.
189-
llvm::SmallVector<mlir::Attribute, 4> globalDtorList;
186+
/// List of ctors and their priorities to be called before main()
187+
llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalCtorList;
188+
/// List of dtors and their priorities to be called when unloading module.
189+
llvm::SmallVector<std::pair<std::string, uint32_t>, 4> globalDtorList;
190190
/// List of annotations in the module
191191
llvm::SmallVector<mlir::Attribute, 4> globalAnnotations;
192192
};
@@ -939,14 +939,33 @@ void LoweringPreparePass::lowerGlobalOp(GlobalOp op) {
939939
}
940940
}
941941

942+
template <typename AttributeTy>
943+
static llvm::SmallVector<mlir::Attribute>
944+
prepareCtorDtorAttrList(mlir::MLIRContext *context,
945+
llvm::ArrayRef<std::pair<std::string, uint32_t>> list) {
946+
llvm::SmallVector<mlir::Attribute> attrs;
947+
for (const auto &[name, priority] : list)
948+
attrs.push_back(AttributeTy::get(context, name, priority));
949+
return attrs;
950+
}
951+
942952
void LoweringPreparePass::buildGlobalCtorDtorList() {
953+
943954
if (!globalCtorList.empty()) {
955+
llvm::SmallVector<mlir::Attribute> globalCtors =
956+
prepareCtorDtorAttrList<cir::GlobalCtorAttr>(&getContext(),
957+
globalCtorList);
958+
944959
theModule->setAttr(cir::CIRDialect::getGlobalCtorsAttrName(),
945-
mlir::ArrayAttr::get(&getContext(), globalCtorList));
960+
mlir::ArrayAttr::get(&getContext(), globalCtors));
946961
}
962+
947963
if (!globalDtorList.empty()) {
964+
llvm::SmallVector<mlir::Attribute> globalDtors =
965+
prepareCtorDtorAttrList<cir::GlobalDtorAttr>(&getContext(),
966+
globalDtorList);
948967
theModule->setAttr(cir::CIRDialect::getGlobalDtorsAttrName(),
949-
mlir::ArrayAttr::get(&getContext(), globalDtorList));
968+
mlir::ArrayAttr::get(&getContext(), globalDtors));
950969
}
951970
}
952971

@@ -956,8 +975,9 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() {
956975

957976
for (auto &f : dynamicInitializers) {
958977
// TODO: handle globals with a user-specified initialzation priority.
959-
auto ctorAttr = cir::GlobalCtorAttr::get(&getContext(), f.getName());
960-
globalCtorList.push_back(ctorAttr);
978+
// TODO: handle defaule priority more nicely.
979+
globalCtorList.emplace_back(f.getName(),
980+
cir::DefaultGlobalCtorDtorPriority);
961981
}
962982

963983
SmallString<256> fnName;
@@ -1118,7 +1138,9 @@ void LoweringPreparePass::buildCUDAModuleCtor() {
11181138
auto moduleCtor = buildRuntimeFunction(builder, moduleCtorName, loc,
11191139
FuncType::get({}, voidTy),
11201140
GlobalLinkageKind::InternalLinkage);
1121-
globalCtorList.push_back(GlobalCtorAttr::get(&getContext(), moduleCtorName));
1141+
// TODO figure out default mode priority
1142+
globalCtorList.emplace_back(moduleCtorName,
1143+
cir::DefaultGlobalCtorDtorPriority);
11221144
builder.setInsertionPointToStart(moduleCtor.addEntryBlock());
11231145

11241146
// Register binary with CUDA runtime. This is substantially different in
@@ -1598,10 +1620,10 @@ void LoweringPreparePass::runOnOp(Operation *op) {
15981620
if (isa<cir::ArrayType>(valTy) || isa<cir::RecordType>(valTy))
15991621
lowerToMemCpy(storeOp);
16001622
} else if (auto fnOp = dyn_cast<cir::FuncOp>(op)) {
1601-
if (auto globalCtor = fnOp.getGlobalCtorAttr()) {
1602-
globalCtorList.push_back(globalCtor);
1603-
} else if (auto globalDtor = fnOp.getGlobalDtorAttr()) {
1604-
globalDtorList.push_back(globalDtor);
1623+
if (auto globalCtor = fnOp.getGlobalCtorPriority()) {
1624+
globalCtorList.emplace_back(fnOp.getName(), globalCtor.value());
1625+
} else if (auto globalDtor = fnOp.getGlobalDtorPriority()) {
1626+
globalDtorList.emplace_back(fnOp.getName(), globalDtor.value());
16051627
}
16061628
if (auto attr = fnOp.getExtraAttrs().getElements().get(
16071629
CUDAKernelNameAttr::getMnemonic())) {

clang/test/CIR/CodeGen/global-ctor-dtor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ void foo(void) {
1111
bar();
1212
}
1313

14-
// BEFORE: cir.func dso_local @_Z3foov() global_ctor(65535)
14+
// BEFORE: cir.func dso_local @_Z3foov() global_ctor
1515

1616
void foo2(void) __attribute__((constructor(777)));
1717
void foo2(void) {
@@ -25,7 +25,7 @@ void foo3(void) {
2525
bar();
2626
}
2727

28-
// BEFORE: cir.func dso_local @_Z4foo3v() global_dtor(65535)
28+
// BEFORE: cir.func dso_local @_Z4foo3v() global_dtor
2929

3030
void foo4(void) __attribute__((destructor(789)));
3131
void foo4(void) {

clang/test/CIR/CodeGen/global-new.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ e *g = new e(0);
6868
// LLVM_EH: ret void
6969
// LLVM_EH: }
7070

71-
// LLVM-DAG: @llvm.global_ctors = appending constant [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65536, ptr @__cxx_global_var_init, ptr null }, { i32, ptr, ptr } { i32 65536, ptr @__cxx_global_var_init.1, ptr null }]
71+
// LLVM-DAG: @llvm.global_ctors = appending constant [2 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.1, ptr null }]
7272
// LLVM: define internal void @__cxx_global_var_init()
7373
// LLVM: call ptr @_Znwm(i64 1)
7474

0 commit comments

Comments
 (0)