diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -75,8 +75,8 @@ /// Stores a mapping between an LLVM instruction and the imported MLIR /// operation if the operation returns no result. Asserts if the operation /// returns a result and should be added to valueMapping instead. - void mapNoResultOp(llvm::Instruction *inst, Operation *mlir) { - mapNoResultOp(inst) = mlir; + void mapNoResultOp(llvm::Instruction *llvm, Operation *mlir) { + mapNoResultOp(llvm) = mlir; } /// Provides write-once access to store the MLIR operation corresponding to @@ -113,6 +113,19 @@ return blockMapping.lookup(block); } + /// Stores the mapping between an LLVM global and its MLIR counterpart. + void mapGlobal(llvm::GlobalVariable *llvm, GlobalOp mlir) { + auto result = globalMapping.try_emplace(llvm, mlir); + (void)result; + assert(result.second && + "attempting to map a global that is already mapped"); + } + + /// Returns the MLIR global mapped to the given LLVM global variable. + GlobalOp lookupGlobal(llvm::GlobalVariable *globalVar) { + return globalMapping.lookup(globalVar); + } + /// Converts an LLVM value to an MLIR value, or returns failure if the /// conversion fails. Uses the `convertConstant` method to translate constant /// LLVM values. @@ -140,13 +153,10 @@ /// Imports `func` into the current module. LogicalResult processFunction(llvm::Function *func); - /// Converts function attributes of LLVM Function \p func - /// into LLVM dialect attributes of LLVMFuncOp \p funcOp. + /// Converts function attributes of LLVM Function `func` into LLVM dialect + /// attributes of LLVMFuncOp `funcOp`. void processFunctionAttributes(llvm::Function *func, LLVMFuncOp funcOp); - /// Imports `globalVar` as a GlobalOp, creating it if it doesn't exist. - GlobalOp processGlobal(llvm::GlobalVariable *globalVar); - /// Sets the fastmath flags attribute for the imported operation `op` given /// the original instruction `inst`. Asserts if the operation does not /// implement the fastmath interface. @@ -165,6 +175,11 @@ constantInsertionOp = nullptr; } + /// Converts an LLVM global variable into an MLIR LLVM dialect global + /// operation if a conversion exists. Otherwise, returns failure. + LogicalResult convertGlobal(llvm::GlobalVariable *globalVar); + /// Imports the magic globals "global_ctors" and "global_dtors". + LogicalResult convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar); /// Returns personality of `func` as a FlatSymbolRefAttr. FlatSymbolRefAttr getPersonalityAsAttr(llvm::Function *func); /// Imports `bb` into `block`, which must be initially empty. @@ -218,9 +233,6 @@ /// function entry block. FailureOr convertConstantExpr(llvm::Constant *constant); - /// Imports the magic globals "global_ctors" and "global_dtors". - LogicalResult convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar); - /// Builder pointing at where the next instruction should be generated. OpBuilder builder; /// Block to insert the next constant into. @@ -248,8 +260,8 @@ /// operations for all operations that return no result. All operations that /// return a result have a valueMapping entry instead. DenseMap noResultOpMapping; - /// Uniquing map of GlobalVariables. - DenseMap globals; + /// Module-level mapping between original and imported global variables. + DenseMap globalMapping; /// The stateful type translator (contains named structs). LLVM::TypeFromLLVMIRTranslator typeTranslator; /// Stateful debug information importer. diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -338,9 +338,10 @@ } continue; } - - if (!processGlobal(&globalVar)) - return failure(); + if (failed(convertGlobal(&globalVar))) { + return emitError(mlirModule.getLoc()) + << "unhandled global variable " << diag(globalVar); + } } return success(); } @@ -531,10 +532,7 @@ return nullptr; } -GlobalOp ModuleImport::processGlobal(llvm::GlobalVariable *globalVar) { - if (globals.count(globalVar)) - return globals[globalVar]; - +LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) { // Insert the global after the last one or at the start of the module. OpBuilder::InsertionGuard guard(builder); if (!globalInsertionOp) { @@ -556,11 +554,12 @@ } GlobalOp globalOp = builder.create( - UnknownLoc::get(context), type, globalVar->isConstant(), + mlirModule.getLoc(), type, globalVar->isConstant(), convertLinkageFromLLVM(globalVar->getLinkage()), globalVar->getName(), valueAttr, alignment, /*addr_space=*/globalVar->getAddressSpace(), /*dso_local=*/globalVar->isDSOLocal(), /*thread_local=*/globalVar->isThreadLocal()); + mapGlobal(globalVar, globalOp); globalInsertionOp = globalOp; if (globalVar->hasInitializer() && !valueAttr) { @@ -570,7 +569,7 @@ FailureOr initializer = convertConstantExpr(globalVar->getInitializer()); if (failed(initializer)) - return {}; + return failure(); builder.create(globalOp.getLoc(), *initializer); } if (globalVar->hasAtLeastLocalUnnamedAddr()) { @@ -580,7 +579,7 @@ if (globalVar->hasSection()) globalOp.setSection(globalVar->getSection()); - return globals[globalVar] = globalOp; + return success(); } LogicalResult @@ -695,8 +694,9 @@ // Convert global variable accesses. if (auto *globalVar = dyn_cast(constant)) { - return builder.create(loc, processGlobal(globalVar)) - .getResult(); + Type type = convertType(globalVar->getType()); + auto symbolRef = FlatSymbolRefAttr::get(context, globalVar->getName()); + return builder.create(loc, type, symbolRef).getResult(); } // Convert constant expressions. diff --git a/mlir/test/Target/LLVMIR/Import/global-variables.ll b/mlir/test/Target/LLVMIR/Import/global-variables.ll --- a/mlir/test/Target/LLVMIR/Import/global-variables.ll +++ b/mlir/test/Target/LLVMIR/Import/global-variables.ll @@ -12,10 +12,18 @@ ; CHECK-SAME: {addr_space = 0 : i32, alignment = 8 : i64} : f64 @global_float = external global double, align 8 +; CHECK: llvm.mlir.global internal constant @address_before +; CHECK: = llvm.mlir.addressof @global_int : !llvm.ptr +@address_before = internal constant i32* @global_int + ; CHECK: llvm.mlir.global external @global_int ; CHECK-SAME: {addr_space = 0 : i32, alignment = 8 : i64} : i32 @global_int = external global i32, align 8 +; CHECK: llvm.mlir.global internal constant @address_after +; CHECK: = llvm.mlir.addressof @global_int : !llvm.ptr +@address_after = internal constant i32* @global_int + ; CHECK: llvm.mlir.global internal @global_string("hello world") @global_string = internal global [11 x i8] c"hello world" diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll --- a/mlir/test/Target/LLVMIR/Import/import-failure.ll +++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll @@ -27,6 +27,17 @@ ; // ----- +; CHECK: error: unhandled constant i8* blockaddress(@unhandled_global, %bb1) +; CHECK: error: unhandled global variable @private = private global i8* blockaddress(@unhandled_global, %bb1) +@private = private global i8* blockaddress(@unhandled_global, %bb1) + +define void @unhandled_global() { +bb1: + ret void +} + +; // ----- + declare void @llvm.gcroot(ptr %arg0, ptr %arg1) ; CHECK: error: unhandled intrinsic call void @llvm.gcroot(ptr %arg0, ptr %arg1) @@ -63,7 +74,7 @@ !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} !1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2) -!2 = !DIFile(filename: "debug-info.ll", directory: "/") +!2 = !DIFile(filename: "import-failure.ll", directory: "/") !3 = !DILocalVariable(scope: !4, name: "arg", file: !2, line: 1, arg: 1, align: 32); !4 = distinct !DISubprogram(name: "intrinsic", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1) !5 = !DILocation(line: 1, column: 2, scope: !4)