Skip to content

Commit 0ae536e

Browse files
abidhaaryanshukla
authored andcommitted
[mlir][debug] Allow global with local scope. (llvm#98358)
Currently, only those global variables in debug info are allowed which have a compile unit or module scope. But global variable with function scope are used in debug info to represent certain type of variables. One example will be static local variables in C. Here the variable is represented as global variable with parent function as its scope. See the code and debug metadata as generated by clang below. You can see that scope of `DIGlobalVariable` is `DISubprogram`. ``` int test() { static int a = 0; return a++; } !0 = !DIGlobalVariableExpression(var: !1...) !1 = !DIGlobalVariable(name: "a", scope: !2 ...) !2 = !DISubprogram(name: "test" ...) !7 = !DICompileUnit(... globals: !8...) !8 = !{!0} ``` Similar issue exist in fortran where global variable with function scope are used to represent local variable with save attribute. This PR will allows such variables during module translation.
1 parent 4a0600a commit 0ae536e

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,9 +1073,15 @@ LogicalResult ModuleTranslation::convertGlobals() {
10731073
// variable -> module -> compile unit
10741074
// If a variable scope points to the module then we use the scope of the
10751075
// module to get the compile unit.
1076+
// Global variables are also used for things like static local variables
1077+
// in C and local variables with the save attribute in Fortran. The scope
1078+
// of the variable is the parent function. We use the compile unit of the
1079+
// parent function in this case.
10761080
llvm::DIScope *scope = diGlobalVar->getScope();
1077-
if (llvm::DIModule *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1081+
if (auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
10781082
scope = mod->getScope();
1083+
else if (auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1084+
scope = sp->getUnit();
10791085

10801086
// Get the compile unit (scope) of the the global variable.
10811087
if (llvm::DICompileUnit *compileUnit =

mlir/test/Target/LLVMIR/llvmir-debug.mlir

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,25 @@ llvm.mlir.global external @module_global() {dbg_expr = #llvm.di_global_variable_
347347

348348
// -----
349349

350+
// CHECK: @func_global = external global i64, !dbg {{.*}}
351+
// CHECK-DAG: ![[CU:.*]] = distinct !DICompileUnit({{.*}}globals: ![[GVALS:.*]])
352+
// CHECK-DAG: ![[SP:.*]] = distinct !DISubprogram(name: "fn_with_gl"{{.*}}unit: ![[CU]])
353+
// CHECK-DAG: ![[GVAR:.*]] = distinct !DIGlobalVariable(name: "func_global"{{.*}}, scope: ![[SP]]{{.*}})
354+
// CHECK-DAG: ![[GEXPR:.*]] = !DIGlobalVariableExpression(var: ![[GVAR]], expr: !DIExpression())
355+
// CHECK-DAG: ![[GVALS]] = !{![[GEXPR]]}
356+
357+
#file = #llvm.di_file<"test.f90" in "existence">
358+
#cu = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_Fortran95, file = #file, producer = "MLIR", isOptimized = true, emissionKind = Full>
359+
#ty1 = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 64, encoding = DW_ATE_signed>
360+
#sp = #llvm.di_subprogram<compileUnit = #cu, scope = #file, name = "fn_with_gl", file = #file, subprogramFlags = "Definition|Optimized">
361+
llvm.mlir.global @func_global() {dbg_expr = #llvm.di_global_variable_expression<var = <scope = #sp, name = "func_global", linkageName = "func_global", file = #file, line = 121, type = #ty1, isLocalToUnit = true, isDefined = true>, expr = <>>} : i64
362+
363+
llvm.func @fn_with_gl() {
364+
llvm.return
365+
} loc(fused<#sp>["foo1.mlir":0:0])
366+
367+
// -----
368+
350369
// Nameless and scopeless global constant.
351370

352371
// CHECK-LABEL: @.str.1 = external constant [10 x i8]

0 commit comments

Comments
 (0)