diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index 8445e609c2244..7ea82f61fadbb 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -1071,11 +1071,21 @@ LogicalResult ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) { if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage()) return failure(); - auto *initializer = - dyn_cast(globalVar->getInitializer()); - if (!initializer) + llvm::Constant *initializer = globalVar->getInitializer(); + + bool knownInit = isa(initializer) || + isa(initializer); + if (!knownInit) return failure(); + // ConstantAggregateZero does not engage with the operand initialization + // in the loop that follows - there should be no operands. This implies + // empty ctor/dtor lists. + if (auto *caz = dyn_cast(initializer)) { + if (caz->getElementCount().getFixedValue() != 0) + return failure(); + } + SmallVector funcs; SmallVector priorities; for (llvm::Value *operand : initializer->operands()) { diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index 5cd841ee2df91..eda6b51ff45ea 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -1258,16 +1258,35 @@ LogicalResult ModuleTranslation::convertGlobalsAndAliases() { auto dtorOp = dyn_cast(op); if (!ctorOp && !dtorOp) continue; - auto range = ctorOp ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities()) - : llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities()); - auto appendGlobalFn = - ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors; - for (auto symbolAndPriority : range) { - llvm::Function *f = lookupFunction( - cast(std::get<0>(symbolAndPriority)).getValue()); - appendGlobalFn(*llvmModule, f, - cast(std::get<1>(symbolAndPriority)).getInt(), - /*Data=*/nullptr); + + // The empty / zero initialized version of llvm.global_(c|d)tors cannot be + // handled by appendGlobalFn logic below, which just ignores empty (c|d)tor + // lists. Make sure it gets emitted. + if ((ctorOp && ctorOp.getCtors().empty()) || + (dtorOp && dtorOp.getDtors().empty())) { + llvm::IRBuilder builder( + llvmModule->getContext(), + llvm::TargetFolder(llvmModule->getDataLayout())); + llvm::Type *eltTy = llvm::StructType::get( + builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy()); + llvm::ArrayType *at = llvm::ArrayType::get(eltTy, 0); + llvm::Constant *zeroInit = llvm::Constant::getNullValue(at); + (void)new llvm::GlobalVariable( + *llvmModule, zeroInit->getType(), false, + llvm::GlobalValue::AppendingLinkage, zeroInit, + ctorOp ? "llvm.global_ctors" : "llvm.global_dtors"); + } else { + auto range = ctorOp + ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities()) + : llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities()); + auto appendGlobalFn = + ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors; + for (const auto &[sym, prio] : range) { + llvm::Function *f = + lookupFunction(cast(sym).getValue()); + appendGlobalFn(*llvmModule, f, cast(prio).getInt(), + /*Data=*/nullptr); + } } } diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir index 79d1cafabfbed..bd3584de9a405 100644 --- a/mlir/test/Dialect/LLVMIR/global.mlir +++ b/mlir/test/Dialect/LLVMIR/global.mlir @@ -233,6 +233,14 @@ llvm.mlir.global_ctors { ctors = [@ctor], priorities = [0 : i32]} // ----- +// CHECK: llvm.mlir.global_ctors {ctors = [], priorities = []} +llvm.mlir.global_ctors {ctors = [], priorities = []} + +// CHECK: llvm.mlir.global_dtors {dtors = [], priorities = []} +llvm.mlir.global_dtors {dtors = [], priorities = []} + +// ----- + llvm.func @dtor() { llvm.return } diff --git a/mlir/test/Target/LLVMIR/Import/global-variables.ll b/mlir/test/Target/LLVMIR/Import/global-variables.ll index fbeda4cd42af8..b809c93d772f5 100644 --- a/mlir/test/Target/LLVMIR/Import/global-variables.ll +++ b/mlir/test/Target/LLVMIR/Import/global-variables.ll @@ -256,6 +256,14 @@ define void @bar() { ; // ----- +; CHECK: llvm.mlir.global_ctors {ctors = [], priorities = []} +@llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] zeroinitializer + +; CHECK: llvm.mlir.global_dtors {dtors = [], priorities = []} +@llvm.global_dtors = appending global [0 x { i32, ptr, ptr }] zeroinitializer + +; // ----- + ; Visibility attribute. ; CHECK: llvm.mlir.global external hidden constant @hidden("string") diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index 7f9a3ba79d724..db2e08742dbca 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -1859,6 +1859,14 @@ llvm.func @foo() { // ----- +// CHECK: @llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] zeroinitializer +llvm.mlir.global_ctors {ctors = [], priorities = []} + +// CHECK: @llvm.global_dtors = appending global [0 x { i32, ptr, ptr }] zeroinitializer +llvm.mlir.global_dtors {dtors = [], priorities = []} + +// ----- + // CHECK: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @foo, ptr null }] llvm.mlir.global_dtors { dtors = [@foo], priorities = [0 : i32]}