diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 15fcc09c6219a..9b624efa05381 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -2808,14 +2808,14 @@ struct GlobalOpConversion : public fir::FIROpConversion { matchAndRewrite(fir::GlobalOp global, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - mlir::LLVM::DIGlobalVariableExpressionAttr dbgExpr; + llvm::SmallVector dbgExprs; if (auto fusedLoc = mlir::dyn_cast(global.getLoc())) { if (auto gvAttr = mlir::dyn_cast_or_null( fusedLoc.getMetadata())) { - dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get( - global.getContext(), gvAttr, mlir::LLVM::DIExpressionAttr()); + dbgExprs.push_back(mlir::LLVM::DIGlobalVariableExpressionAttr::get( + global.getContext(), gvAttr, mlir::LLVM::DIExpressionAttr())); } } @@ -2831,7 +2831,7 @@ struct GlobalOpConversion : public fir::FIROpConversion { llvm::ArrayRef attrs; auto g = rewriter.create( loc, tyAttr, isConst, linkage, global.getSymName(), initAttr, 0, 0, - false, false, comdat, attrs, dbgExpr); + false, false, comdat, attrs, dbgExprs); if (global.getAlignment() && *global.getAlignment() > 0) g.setAlignment(*global.getAlignment()); diff --git a/flang/test/Transforms/debug-module-2.fir b/flang/test/Transforms/debug-module-2.fir index 6acdc1df23d27..c8d618ce34b26 100644 --- a/flang/test/Transforms/debug-module-2.fir +++ b/flang/test/Transforms/debug-module-2.fir @@ -31,5 +31,5 @@ module { // CHECK-DAG: #[[GLR:.*]] = #llvm.di_global_variable<{{.*}}name = "glr", linkageName = "_QMhelperEglr"{{.*}}> // CHECK-DAG: #[[GLIE:.*]] = #llvm.di_global_variable_expression // CHECK-DAG: #[[GLRE:.*]] = #llvm.di_global_variable_expression -// CHECK-DAG: llvm.mlir.global{{.*}}@_QMhelperEgli() {{{.*}}dbg_expr = #[[GLIE]]} -// CHECK-DAG: llvm.mlir.global{{.*}}@_QMhelperEglr() {{{.*}}dbg_expr = #[[GLRE]]} +// CHECK-DAG: llvm.mlir.global{{.*}}@_QMhelperEgli() {{{.*}}dbg_exprs = [#[[GLIE]]]} +// CHECK-DAG: llvm.mlir.global{{.*}}@_QMhelperEglr() {{{.*}}dbg_exprs = [#[[GLRE]]]} diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td index 0d904f13037c6..855fa5702f5b9 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -471,6 +471,10 @@ def LLVM_DIGlobalVariableExpressionAttr let constBuilderCall = "$0"; } +def DIGlobalVariableExpressionArrayAttr : + TypedArrayAttrBase; + //===----------------------------------------------------------------------===// // DIGlobalVariableAttr //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index 000d92f9ea3bc..bbca7bc7286ac 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -1168,7 +1168,7 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global", OptionalAttr:$unnamed_addr, OptionalAttr:$section, OptionalAttr:$comdat, - DefaultValuedAttr:$dbg_expr, + OptionalAttr:$dbg_exprs, DefaultValuedAttr:$visibility_ ); let summary = "LLVM dialect global."; @@ -1279,7 +1279,7 @@ def LLVM_GlobalOp : LLVM_Op<"mlir.global", CArg<"bool", "false">:$thread_local_, CArg<"SymbolRefAttr", "{}">:$comdat, CArg<"ArrayRef", "{}">:$attrs, - CArg<"DIGlobalVariableExpressionAttr", "{}">:$dbgExpr)> + CArg<"ArrayRef", "{}">:$dbgExprs)> ]; let extraClassDeclaration = [{ diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp index 006d412936a33..55c4e03aaefe7 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -2089,7 +2089,7 @@ void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type, Attribute value, uint64_t alignment, unsigned addrSpace, bool dsoLocal, bool threadLocal, SymbolRefAttr comdat, ArrayRef attrs, - DIGlobalVariableExpressionAttr dbgExpr) { + ArrayRef dbgExprs) { result.addAttribute(getSymNameAttrName(result.name), builder.getStringAttr(name)); result.addAttribute(getGlobalTypeAttrName(result.name), TypeAttr::get(type)); @@ -2121,8 +2121,9 @@ void GlobalOp::build(OpBuilder &builder, OperationState &result, Type type, builder.getI32IntegerAttr(addrSpace)); result.attributes.append(attrs.begin(), attrs.end()); - if (dbgExpr) - result.addAttribute(getDbgExprAttrName(result.name), dbgExpr); + if (!dbgExprs.empty()) + result.addAttribute(getDbgExprsAttrName(result.name), + ArrayAttr::get(builder.getContext(), dbgExprs)); result.addRegion(); } diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index 4ff1f1135b0a8..da340f6c9b26d 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -914,14 +914,15 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) { // Get the global expression associated with this global variable and convert // it. - DIGlobalVariableExpressionAttr globalExpressionAttr; + SmallVector globalExpressionAttrs; SmallVector globalExpressions; globalVar->getDebugInfo(globalExpressions); - // There should only be a single global expression. - if (!globalExpressions.empty()) - globalExpressionAttr = - debugImporter->translateGlobalVariableExpression(globalExpressions[0]); + for (llvm::DIGlobalVariableExpression *expr : globalExpressions) { + DIGlobalVariableExpressionAttr globalExpressionAttr = + debugImporter->translateGlobalVariableExpression(expr); + globalExpressionAttrs.push_back(globalExpressionAttr); + } // Workaround to support LLVM's nameless globals. MLIR, in contrast to LLVM, // always requires a symbol name. @@ -935,7 +936,7 @@ LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) { valueAttr, alignment, /*addr_space=*/globalVar->getAddressSpace(), /*dso_local=*/globalVar->isDSOLocal(), /*thread_local=*/globalVar->isThreadLocal(), /*comdat=*/SymbolRefAttr(), - /*attrs=*/ArrayRef(), /*dbgExpr=*/globalExpressionAttr); + /*attrs=*/ArrayRef(), /*dbgExprs=*/globalExpressionAttrs); globalInsertionOp = globalOp; if (globalVar->hasInitializer() && !valueAttr) { diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index a5de90160c414..d52b20758e7b9 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -1055,44 +1055,48 @@ LogicalResult ModuleTranslation::convertGlobals() { globalsMapping.try_emplace(op, var); // Add debug information if present. - if (op.getDbgExpr()) { - llvm::DIGlobalVariableExpression *diGlobalExpr = - debugTranslation->translateGlobalVariableExpression(op.getDbgExpr()); - llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable(); - var->addDebugInfo(diGlobalExpr); - - // There is no `globals` field in DICompileUnitAttr which can be directly - // assigned to DICompileUnit. We have to build the list by looking at the - // dbgExpr of all the GlobalOps. The scope of the variable is used to get - // the DICompileUnit in which to add it. - // But there are cases where the scope of a global does not - // directly point to the DICompileUnit and we have to do a bit more work - // to get to it. Some of those cases are: - // - // 1. For the languages that support modules, the scope hierarchy can be - // variable -> DIModule -> DICompileUnit - // - // 2. For the Fortran common block variable, the scope hierarchy can be - // variable -> DICommonBlock -> DISubprogram -> DICompileUnit - // - // 3. For entities like static local variables in C or variable with - // SAVE attribute in Fortran, the scope hierarchy can be - // variable -> DISubprogram -> DICompileUnit - llvm::DIScope *scope = diGlobalVar->getScope(); - if (auto *mod = dyn_cast_if_present(scope)) - scope = mod->getScope(); - else if (auto *cb = dyn_cast_if_present(scope)) { - if (auto *sp = dyn_cast_if_present(cb->getScope())) + if (op.getDbgExprs()) { + for (auto exprAttr : + op.getDbgExprs()->getAsRange()) { + llvm::DIGlobalVariableExpression *diGlobalExpr = + debugTranslation->translateGlobalVariableExpression(exprAttr); + llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable(); + var->addDebugInfo(diGlobalExpr); + + // There is no `globals` field in DICompileUnitAttr which can be + // directly assigned to DICompileUnit. We have to build the list by + // looking at the dbgExpr of all the GlobalOps. The scope of the + // variable is used to get the DICompileUnit in which to add it. But + // there are cases where the scope of a global does not directly point + // to the DICompileUnit and we have to do a bit more work to get to + // it. Some of those cases are: + // + // 1. For the languages that support modules, the scope hierarchy can + // be variable -> DIModule -> DICompileUnit + // + // 2. For the Fortran common block variable, the scope hierarchy can + // be variable -> DICommonBlock -> DISubprogram -> DICompileUnit + // + // 3. For entities like static local variables in C or variable with + // SAVE attribute in Fortran, the scope hierarchy can be + // variable -> DISubprogram -> DICompileUnit + llvm::DIScope *scope = diGlobalVar->getScope(); + if (auto *mod = dyn_cast_if_present(scope)) + scope = mod->getScope(); + else if (auto *cb = dyn_cast_if_present(scope)) { + if (auto *sp = + dyn_cast_if_present(cb->getScope())) + scope = sp->getUnit(); + } else if (auto *sp = dyn_cast_if_present(scope)) scope = sp->getUnit(); - } else if (auto *sp = dyn_cast_if_present(scope)) - scope = sp->getUnit(); - - // Get the compile unit (scope) of the the global variable. - if (llvm::DICompileUnit *compileUnit = - dyn_cast_if_present(scope)) { - // Update the compile unit with this incoming global variable expression - // during the finalizing step later. - allGVars[compileUnit].push_back(diGlobalExpr); + + // Get the compile unit (scope) of the the global variable. + if (llvm::DICompileUnit *compileUnit = + dyn_cast_if_present(scope)) { + // Update the compile unit with this incoming global variable + // expression during the finalizing step later. + allGVars[compileUnit].push_back(diGlobalExpr); + } } } } diff --git a/mlir/test/Dialect/LLVMIR/debuginfo.mlir b/mlir/test/Dialect/LLVMIR/debuginfo.mlir index 8475ec6c3510d..dafb3bcef740f 100644 --- a/mlir/test/Dialect/LLVMIR/debuginfo.mlir +++ b/mlir/test/Dialect/LLVMIR/debuginfo.mlir @@ -162,7 +162,18 @@ file = #file, line = 2, type = #int0> #var_expression = #llvm.di_global_variable_expression> -llvm.mlir.global common @block_() {dbg_expr = #var_expression} : i64 +#global_var1 = #llvm.di_global_variable +#var_expression1 = #llvm.di_global_variable_expression> +llvm.mlir.global @data() {dbg_exprs = [#var_expression, #var_expression1]} : i64 + +// CHECK-DAG: llvm.mlir.global external @data() {{{.*}}dbg_exprs = [#[[EXP1:.*]], #[[EXP2:.*]]]} : i64 +// CHECK-DAG: #[[EXP1]] = #llvm.di_global_variable_expression> +// CHECK-DAG: #[[EXP2]] = #llvm.di_global_variable_expression> +// CHECK-DAG: #[[GV1]] = #llvm.di_global_variable<{{.*}}name = "a"{{.*}}> +// CHECK-DAG: #[[GV2]] = #llvm.di_global_variable<{{.*}}name = "b"{{.*}}> + // CHECK: llvm.func @addr(%[[ARG:.*]]: i64) llvm.func @addr(%arg: i64) { diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir index 3fa7636d4dd68..79d1cafabfbed 100644 --- a/mlir/test/Dialect/LLVMIR/global.mlir +++ b/mlir/test/Dialect/LLVMIR/global.mlir @@ -272,15 +272,15 @@ llvm.mlir.global @target_fail(0 : i64) : !llvm.target<"spirv.Image", i32, 0> // CHECK-DAG: #[[EXPR1:.*]] = #llvm.di_global_variable_expression> // CHECK-DAG: #[[EXPR2:.*]] = #llvm.di_global_variable_expression> // CHECK-DAG: #[[EXPR3:.*]] = #llvm.di_global_variable_expression> -// CHECK-DAG: llvm.mlir.global external @global_with_expr1() {addr_space = 0 : i32, dbg_expr = #[[EXPR0]]} : i64 -// CHECK-DAG: llvm.mlir.global external @global_with_expr2() {addr_space = 0 : i32, dbg_expr = #[[EXPR1]]} : i64 -// CHECK-DAG: llvm.mlir.global external @global_with_expr3() {addr_space = 0 : i32, dbg_expr = #[[EXPR2]]} : i64 -// CHECK-DAG: llvm.mlir.global external @global_with_expr4() {addr_space = 0 : i32, dbg_expr = #[[EXPR3]]} : i64 +// CHECK-DAG: llvm.mlir.global external @global_with_expr1() {addr_space = 0 : i32, dbg_expr = [#[[EXPR0]]]} : i64 +// CHECK-DAG: llvm.mlir.global external @global_with_expr2() {addr_space = 0 : i32, dbg_expr = [#[[EXPR1]]]} : i64 +// CHECK-DAG: llvm.mlir.global external @global_with_expr3() {addr_space = 0 : i32, dbg_expr = [#[[EXPR2]]]} : i64 +// CHECK-DAG: llvm.mlir.global external @global_with_expr4() {addr_space = 0 : i32, dbg_expr = [#[[EXPR3]]]} : i64 #di_file = #llvm.di_file<"not" in "existence"> #di_compile_unit = #llvm.di_compile_unit, sourceLanguage = DW_LANG_C, file = #di_file, producer = "MLIR", isOptimized = true, emissionKind = Full> #di_basic_type = #llvm.di_basic_type -llvm.mlir.global external @global_with_expr1() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression, expr = <>>} : i64 -llvm.mlir.global external @global_with_expr2() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression, expr = <[DW_OP_push_object_address, DW_OP_deref]>>} : i64 -llvm.mlir.global external @global_with_expr3() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression, expr = <[DW_OP_LLVM_arg(0), DW_OP_LLVM_arg(1), DW_OP_plus]>>} : i64 -llvm.mlir.global external @global_with_expr4() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression, expr = <[DW_OP_LLVM_convert(16, DW_ATE_signed)]>>} : i64 +llvm.mlir.global external @global_with_expr1() {addr_space = 0 : i32, dbg_expr = [#llvm.di_global_variable_expression, expr = <>>]} : i64 +llvm.mlir.global external @global_with_expr2() {addr_space = 0 : i32, dbg_expr = [#llvm.di_global_variable_expression, expr = <[DW_OP_push_object_address, DW_OP_deref]>>]} : i64 +llvm.mlir.global external @global_with_expr3() {addr_space = 0 : i32, dbg_expr = [#llvm.di_global_variable_expression, expr = <[DW_OP_LLVM_arg(0), DW_OP_LLVM_arg(1), DW_OP_plus]>>]} : i64 +llvm.mlir.global external @global_with_expr4() {addr_space = 0 : i32, dbg_expr = [#llvm.di_global_variable_expression, expr = <[DW_OP_LLVM_convert(16, DW_ATE_signed)]>>]} : i64 diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll index 09909d7d63b2a..9ef1942e0787c 100644 --- a/mlir/test/Target/LLVMIR/Import/debug-info.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll @@ -867,3 +867,27 @@ define void @test() !dbg !3 { ; CHECK: #[[FILE:.+]] = #llvm.di_file<"test.f90" in ""> ; CHECK: #[[SP:.+]] = #llvm.di_subprogram<{{.*}}name = "test"{{.*}}> ; CHECK: #llvm.di_common_block + +; // ----- + +@data = external global i64, !dbg !0, !dbg !5 + +!llvm.module.flags = !{!8} +!llvm.dbg.cu = !{!2} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !7) +!2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, globals: !4) +!3 = !DIFile(filename: "test.c", directory: "") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !7) +!7 = !DIBasicType(name: "int", size: 32) +!8 = !{i32 2, !"Debug Info Version", i32 3} + + +; CHECK: #[[VAR1:.+]] = #llvm.di_global_variable<{{.*}}name = "a"{{.*}}> +; CHECK: #[[VAR2:.+]] = #llvm.di_global_variable<{{.*}}name = "b"{{.*}}> +; CHECK: #[[EXP1:.+]] = #llvm.di_global_variable_expression> +; CHECK: #[[EXP2:.+]] = #llvm.di_global_variable_expression> +; CHECK: llvm.mlir.global external @data() {{{.*}}dbg_exprs = [#[[EXP1]], #[[EXP2]]]} : i64 diff --git a/mlir/test/Target/LLVMIR/Import/global-variables.ll b/mlir/test/Target/LLVMIR/Import/global-variables.ll index 879e9135fe4ec..fbeda4cd42af8 100644 --- a/mlir/test/Target/LLVMIR/Import/global-variables.ll +++ b/mlir/test/Target/LLVMIR/Import/global-variables.ll @@ -274,8 +274,8 @@ define void @bar() { ; CHECK-DAG: #[[GVAR1:.*]] = #llvm.di_global_variable ; CHECK-DAG: #[[EXPR0:.*]] = #llvm.di_global_variable_expression> ; CHECK-DAG: #[[EXPR1:.*]] = #llvm.di_global_variable_expression> -; CHECK-DAG: llvm.mlir.global external @foo() {addr_space = 0 : i32, alignment = 8 : i64, dbg_expr = #[[EXPR0]]} : i32 -; CHECK-DAG: llvm.mlir.global external @bar() {addr_space = 0 : i32, alignment = 8 : i64, dbg_expr = #[[EXPR1]]} : i32 +; CHECK-DAG: llvm.mlir.global external @foo() {addr_space = 0 : i32, alignment = 8 : i64, dbg_exprs = [#[[EXPR0]]]} : i32 +; CHECK-DAG: llvm.mlir.global external @bar() {addr_space = 0 : i32, alignment = 8 : i64, dbg_exprs = [#[[EXPR1]]]} : i32 @foo = external global i32, align 8, !dbg !5 @bar = external global i32, align 8, !dbg !7 @@ -308,7 +308,7 @@ define void @bar() { ; CHECK: llvm.mlir.global internal constant @one() {addr_space = 0 : i32, dso_local} : !llvm.ptr { ; CHECK: llvm.mlir.addressof @mlir.llvm.nameless_global_3 : !llvm.ptr -; CHECK: llvm.mlir.global external constant @".str.1"() {addr_space = 0 : i32, dbg_expr = #[[GLOBAL_VAR_EXPR]]} +; CHECK: llvm.mlir.global external constant @".str.1"() {addr_space = 0 : i32, dbg_exprs = [#[[GLOBAL_VAR_EXPR]]]} @0 = private unnamed_addr constant [2 x i8] c"0\00" @1 = private unnamed_addr constant [2 x i8] c"1\00" diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir index 826fda60c5efe..b97bdcbc772d8 100644 --- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir @@ -327,8 +327,8 @@ llvm.func @dbg_intrinsics_with_no_location(%arg0: i32) -> (i32) { #di_file_2 = #llvm.di_file<"not" in "existence"> #di_compile_unit_2 = #llvm.di_compile_unit, sourceLanguage = DW_LANG_C, file = #di_file_2, producer = "MLIR", isOptimized = true, emissionKind = Full> #di_basic_type_2 = #llvm.di_basic_type -llvm.mlir.global external @global_with_expr_1() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression, expr = <>>} : i64 -llvm.mlir.global external @global_with_expr_2() {addr_space = 0 : i32, dbg_expr = #llvm.di_global_variable_expression, expr = <>>} : i64 +llvm.mlir.global external @global_with_expr_1() {addr_space = 0 : i32, dbg_exprs = [#llvm.di_global_variable_expression, expr = <>>]} : i64 +llvm.mlir.global external @global_with_expr_2() {addr_space = 0 : i32, dbg_exprs = [#llvm.di_global_variable_expression, expr = <>>]} : i64 // ----- @@ -347,7 +347,7 @@ llvm.mlir.global external @global_with_expr_2() {addr_space = 0 : i32, dbg_expr #di_compile_unit = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "MLIR", isOptimized = true, emissionKind = Full> #di_basic_type = #llvm.di_basic_type #di_module = #llvm.di_module -llvm.mlir.global external @module_global() {dbg_expr = #llvm.di_global_variable_expression, expr = <>>} : i64 +llvm.mlir.global external @module_global() {dbg_exprs = [#llvm.di_global_variable_expression, expr = <>>]} : i64 // ----- @@ -362,7 +362,7 @@ llvm.mlir.global external @module_global() {dbg_expr = #llvm.di_global_variable_ #cu = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #file, producer = "MLIR", isOptimized = true, emissionKind = Full> #ty1 = #llvm.di_basic_type #sp = #llvm.di_subprogram -llvm.mlir.global @func_global() {dbg_expr = #llvm.di_global_variable_expression, expr = <>>} : i64 +llvm.mlir.global @func_global() {dbg_exprs = [#llvm.di_global_variable_expression, expr = <>>]} : i64 llvm.func @fn_with_gl() { llvm.return @@ -419,7 +419,7 @@ llvm.func @imp_fn() { #di_global_variable = #llvm.di_global_variable #di_global_variable_expression = #llvm.di_global_variable_expression> -llvm.mlir.global external constant @".str.1"() {addr_space = 0 : i32, dbg_expr = #di_global_variable_expression} : !llvm.array<10 x i8> +llvm.mlir.global external constant @".str.1"() {addr_space = 0 : i32, dbg_exprs = [#di_global_variable_expression]} : !llvm.array<10 x i8> // ----- @@ -514,7 +514,7 @@ llvm.func @class_method() { #di_global_variable = #llvm.di_global_variable #di_global_variable_expression = #llvm.di_global_variable_expression -llvm.mlir.global @global_variable() {dbg_expr = #di_global_variable_expression} : !llvm.struct<()> +llvm.mlir.global @global_variable() {dbg_exprs = [#di_global_variable_expression]} : !llvm.struct<()> // CHECK: distinct !DIGlobalVariable({{.*}}type: ![[COMP:[0-9]+]], // CHECK: ![[COMP]] = distinct !DICompositeType({{.*}}scope: ![[SCOPE:[0-9]+]] @@ -544,7 +544,7 @@ llvm.mlir.global @global_variable() {dbg_expr = #di_global_variable_expression} #di_global_variable = #llvm.di_global_variable #di_global_variable_expression = #llvm.di_global_variable_expression -llvm.mlir.global @global_variable() {dbg_expr = #di_global_variable_expression} : !llvm.struct<()> +llvm.mlir.global @global_variable() {dbg_exprs = [#di_global_variable_expression]} : !llvm.struct<()> // CHECK: distinct !DIGlobalVariable({{.*}}type: ![[VAR:[0-9]+]], // CHECK: ![[VAR]] = !DISubroutineType(types: ![[COMPS:[0-9]+]]) @@ -616,7 +616,7 @@ llvm.func @fn_with_composite() { #loc1 = loc("test.f90": 1:1) #loc2 = loc(fused<#sp>[#loc1]) -llvm.mlir.global external @gv() {dbg_expr = #gve} : i64 +llvm.mlir.global external @gv() {dbg_exprs = [#gve]} : i64 llvm.func @subranges(%arg: !llvm.ptr) { llvm.intr.dbg.declare #lvar2 = %arg : !llvm.ptr @@ -678,7 +678,7 @@ llvm.func @string_ty(%arg0: !llvm.ptr) { expr = <>> llvm.mlir.global common @block_(dense<0> : tensor<8xi8>) - {dbg_expr = #var_expression} : !llvm.array<8 x i8> + {dbg_exprs = [#var_expression]} : !llvm.array<8 x i8> llvm.func @test() { llvm.return @@ -690,3 +690,27 @@ llvm.func @test() { // CHECK: !DICommonBlock(scope: ![[SCOPE:[0-9]+]], declaration: null, name: "block", file: ![[FILE:[0-9]+]], line: 3) // CHECK: ![[SCOPE]] = {{.*}}!DISubprogram(name: "test"{{.*}}) // CHECK: ![[FILE]] = !DIFile(filename: "test.f90"{{.*}}) + +// ----- + +// Test multiple DIGlobalVariableExpression on a global. +#bt = #llvm.di_basic_type +#file = #llvm.di_file<"test.f90" in ""> +#cu = #llvm.di_compile_unit, sourceLanguage = DW_LANG_C, + file = #file, isOptimized = false, emissionKind = Full> +#global_var = #llvm.di_global_variable +#var_expression = #llvm.di_global_variable_expression> +#global_var1 = #llvm.di_global_variable +#var_expression1 = #llvm.di_global_variable_expression> + +llvm.mlir.global @data() {dbg_exprs = [#var_expression, #var_expression1]} : i64 + +// CHECK: @data = external global i64, !dbg ![[EXP1:[0-9]+]], !dbg ![[EXP2:[0-9]+]] +// CHECK: ![[EXP1]] = !DIGlobalVariableExpression(var: ![[VAR1:[0-9]+]], expr: !DIExpression()) +// CHECK: ![[VAR1]] = {{.*}}!DIGlobalVariable(name: "a"{{.*}}) +// CHECK: ![[EXP2]] = !DIGlobalVariableExpression(var: ![[VAR2:[0-9]+]], expr: !DIExpression()) +// CHECK: ![[VAR2]] = {{.*}}!DIGlobalVariable(name: "b"{{.*}})