Skip to content

Commit 54d3cf1

Browse files
authored
[MLIR][LLVM] Fix nameless global import to support use before def case (#111797)
This commit fixes a bug in the import of nameless globals. Before this change, the fake symbol names were only generated during the transformation of the definition. This caused issues when the symbol was used before it was defined.
1 parent 06eb10d commit 54d3cf1

File tree

3 files changed

+42
-15
lines changed

3 files changed

+42
-15
lines changed

mlir/include/mlir/Target/LLVMIR/ModuleImport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,10 @@ class ModuleImport {
355355
/// and stores a mapping from the struct to the symbol pointing to the
356356
/// translated operation.
357357
void processComdat(const llvm::Comdat *comdat);
358+
/// Returns a symbol name for a nameless global. MLIR, in contrast to LLVM,
359+
/// always requires a symbol name.
360+
FlatSymbolRefAttr
361+
getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar);
358362

359363
/// Builder pointing at where the next instruction should be generated.
360364
OpBuilder builder;

mlir/lib/Target/LLVMIR/ModuleImport.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,24 @@ Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
874874
return {};
875875
}
876876

877+
FlatSymbolRefAttr
878+
ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
879+
assert(globalVar->getName().empty() &&
880+
"expected to work with a nameless global");
881+
auto [it, success] = namelessGlobals.try_emplace(globalVar);
882+
if (!success)
883+
return it->second;
884+
885+
// Make sure the symbol name does not clash with an existing symbol.
886+
SmallString<128> globalName = SymbolTable::generateSymbolName<128>(
887+
getNamelessGlobalPrefix(),
888+
[this](StringRef newName) { return llvmModule->getNamedValue(newName); },
889+
namelessGlobalId);
890+
auto symbolRef = FlatSymbolRefAttr::get(context, globalName);
891+
it->getSecond() = symbolRef;
892+
return symbolRef;
893+
}
894+
877895
LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
878896
// Insert the global after the last one or at the start of the module.
879897
OpBuilder::InsertionGuard guard(builder);
@@ -907,17 +925,10 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
907925

908926
// Workaround to support LLVM's nameless globals. MLIR, in contrast to LLVM,
909927
// always requires a symbol name.
910-
SmallString<128> globalName(globalVar->getName());
911-
if (globalName.empty()) {
912-
// Make sure the symbol name does not clash with an existing symbol.
913-
globalName = SymbolTable::generateSymbolName<128>(
914-
getNamelessGlobalPrefix(),
915-
[this](StringRef newName) {
916-
return llvmModule->getNamedValue(newName);
917-
},
918-
namelessGlobalId);
919-
namelessGlobals[globalVar] = FlatSymbolRefAttr::get(context, globalName);
920-
}
928+
StringRef globalName = globalVar->getName();
929+
if (globalName.empty())
930+
globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
931+
921932
GlobalOp globalOp = builder.create<GlobalOp>(
922933
mlirModule.getLoc(), type, globalVar->isConstant(),
923934
convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
@@ -1100,13 +1111,14 @@ FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
11001111
}
11011112

11021113
// Convert global variable accesses.
1103-
if (auto *globalVar = dyn_cast<llvm::GlobalObject>(constant)) {
1104-
Type type = convertType(globalVar->getType());
1105-
StringRef globalName = globalVar->getName();
1114+
if (auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1115+
Type type = convertType(globalObj->getType());
1116+
StringRef globalName = globalObj->getName();
11061117
FlatSymbolRefAttr symbolRef;
11071118
// Empty names are only allowed for global variables.
11081119
if (globalName.empty())
1109-
symbolRef = namelessGlobals[cast<llvm::GlobalVariable>(globalVar)];
1120+
symbolRef =
1121+
getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
11101122
else
11111123
symbolRef = FlatSymbolRefAttr::get(context, globalName);
11121124
return builder.create<AddressOfOp>(loc, type, symbolRef).getResult();

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,14 @@ declare void @"mlir.llvm.nameless_global_2"()
330330
!5 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
331331
!6 = !{}
332332
!7 = !{i32 2, !"Debug Info Version", i32 3}
333+
334+
; // -----
335+
336+
; Verify that unnamed globals can also be referenced before they are defined.
337+
338+
; CHECK: llvm.mlir.global internal constant @reference()
339+
; CHECK: llvm.mlir.addressof @mlir.llvm.nameless_global_0 : !llvm.ptr
340+
@reference = internal constant ptr @0
341+
342+
; CHECK: llvm.mlir.global private unnamed_addr constant @mlir.llvm.nameless_global_0("0\00")
343+
@0 = private unnamed_addr constant [2 x i8] c"0\00"

0 commit comments

Comments
 (0)