Skip to content

Commit af2dd15

Browse files
[MLIR][LLVMIR] Add support for empty global ctor/dtor lists (#128969)
LLVM IR emitted in from C++ may contain `@llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] zeroinitializer`. Before this PR, if we try to roundtrip code like this from the importer, we'll end up with nothing in place. Note that `llvm::appendToGlobalCtors` ignores empty lists and this PR uses the same approach as `llvm-as`, which doesn't use the utilities from `llvm/lib/Transforms/Utils/ModuleUtils.cpp` in order to build this - it calls into creating a global variable from scratch.
1 parent f5749e7 commit af2dd15

File tree

5 files changed

+66
-13
lines changed

5 files changed

+66
-13
lines changed

mlir/lib/Target/LLVMIR/ModuleImport.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,11 +1071,21 @@ LogicalResult
10711071
ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
10721072
if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
10731073
return failure();
1074-
auto *initializer =
1075-
dyn_cast<llvm::ConstantArray>(globalVar->getInitializer());
1076-
if (!initializer)
1074+
llvm::Constant *initializer = globalVar->getInitializer();
1075+
1076+
bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1077+
isa<llvm::ConstantAggregateZero>(initializer);
1078+
if (!knownInit)
10771079
return failure();
10781080

1081+
// ConstantAggregateZero does not engage with the operand initialization
1082+
// in the loop that follows - there should be no operands. This implies
1083+
// empty ctor/dtor lists.
1084+
if (auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1085+
if (caz->getElementCount().getFixedValue() != 0)
1086+
return failure();
1087+
}
1088+
10791089
SmallVector<Attribute> funcs;
10801090
SmallVector<int32_t> priorities;
10811091
for (llvm::Value *operand : initializer->operands()) {

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,16 +1258,35 @@ LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
12581258
auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
12591259
if (!ctorOp && !dtorOp)
12601260
continue;
1261-
auto range = ctorOp ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1262-
: llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1263-
auto appendGlobalFn =
1264-
ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1265-
for (auto symbolAndPriority : range) {
1266-
llvm::Function *f = lookupFunction(
1267-
cast<FlatSymbolRefAttr>(std::get<0>(symbolAndPriority)).getValue());
1268-
appendGlobalFn(*llvmModule, f,
1269-
cast<IntegerAttr>(std::get<1>(symbolAndPriority)).getInt(),
1270-
/*Data=*/nullptr);
1261+
1262+
// The empty / zero initialized version of llvm.global_(c|d)tors cannot be
1263+
// handled by appendGlobalFn logic below, which just ignores empty (c|d)tor
1264+
// lists. Make sure it gets emitted.
1265+
if ((ctorOp && ctorOp.getCtors().empty()) ||
1266+
(dtorOp && dtorOp.getDtors().empty())) {
1267+
llvm::IRBuilder<llvm::TargetFolder> builder(
1268+
llvmModule->getContext(),
1269+
llvm::TargetFolder(llvmModule->getDataLayout()));
1270+
llvm::Type *eltTy = llvm::StructType::get(
1271+
builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1272+
llvm::ArrayType *at = llvm::ArrayType::get(eltTy, 0);
1273+
llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1274+
(void)new llvm::GlobalVariable(
1275+
*llvmModule, zeroInit->getType(), false,
1276+
llvm::GlobalValue::AppendingLinkage, zeroInit,
1277+
ctorOp ? "llvm.global_ctors" : "llvm.global_dtors");
1278+
} else {
1279+
auto range = ctorOp
1280+
? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1281+
: llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1282+
auto appendGlobalFn =
1283+
ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1284+
for (const auto &[sym, prio] : range) {
1285+
llvm::Function *f =
1286+
lookupFunction(cast<FlatSymbolRefAttr>(sym).getValue());
1287+
appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1288+
/*Data=*/nullptr);
1289+
}
12711290
}
12721291
}
12731292

mlir/test/Dialect/LLVMIR/global.mlir

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,14 @@ llvm.mlir.global_ctors { ctors = [@ctor], priorities = [0 : i32]}
233233

234234
// -----
235235

236+
// CHECK: llvm.mlir.global_ctors {ctors = [], priorities = []}
237+
llvm.mlir.global_ctors {ctors = [], priorities = []}
238+
239+
// CHECK: llvm.mlir.global_dtors {dtors = [], priorities = []}
240+
llvm.mlir.global_dtors {dtors = [], priorities = []}
241+
242+
// -----
243+
236244
llvm.func @dtor() {
237245
llvm.return
238246
}

mlir/test/Target/LLVMIR/Import/global-variables.ll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,14 @@ define void @bar() {
256256

257257
; // -----
258258

259+
; CHECK: llvm.mlir.global_ctors {ctors = [], priorities = []}
260+
@llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] zeroinitializer
261+
262+
; CHECK: llvm.mlir.global_dtors {dtors = [], priorities = []}
263+
@llvm.global_dtors = appending global [0 x { i32, ptr, ptr }] zeroinitializer
264+
265+
; // -----
266+
259267
; Visibility attribute.
260268

261269
; CHECK: llvm.mlir.global external hidden constant @hidden("string")

mlir/test/Target/LLVMIR/llvmir.mlir

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,14 @@ llvm.func @foo() {
18591859

18601860
// -----
18611861

1862+
// CHECK: @llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] zeroinitializer
1863+
llvm.mlir.global_ctors {ctors = [], priorities = []}
1864+
1865+
// CHECK: @llvm.global_dtors = appending global [0 x { i32, ptr, ptr }] zeroinitializer
1866+
llvm.mlir.global_dtors {dtors = [], priorities = []}
1867+
1868+
// -----
1869+
18621870
// CHECK: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @foo, ptr null }]
18631871
llvm.mlir.global_dtors { dtors = [@foo], priorities = [0 : i32]}
18641872

0 commit comments

Comments
 (0)