[Mlir-commits] [mlir] [mlir][debug] Allow global with local scope. (PR #98358)

Abid Qadeer llvmlistbot at llvm.org
Wed Jul 10 10:54:42 PDT 2024


https://github.com/abidh created https://github.com/llvm/llvm-project/pull/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.

>From 6f49dae02142e1278555f1eb7a4875d7cd98ba2c Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Wed, 10 Jul 2024 14:41:21 +0100
Subject: [PATCH] [mlir][debug] Allow global with local scope.

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. 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 variable during module translation.
---
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp |  7 +++++++
 mlir/test/Target/LLVMIR/llvmir-debug.mlir    | 19 +++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 1d2e4725d5d63..9bfdb5b582212 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1073,9 +1073,16 @@ LogicalResult ModuleTranslation::convertGlobals() {
       // variable -> module -> compile unit
       // If a variable scope points to the module then we use the scope of the
       // module to get the compile unit.
+      // Global variables are also used for things like static local variables
+      // in C and local variables with the save attribute in Fortran. The scope
+      // of the variable is the parent function. We use the compile unit of the
+      // parent function in this case.
       llvm::DIScope *scope = diGlobalVar->getScope();
       if (llvm::DIModule *mod = dyn_cast_if_present<llvm::DIModule>(scope))
         scope = mod->getScope();
+      else if (llvm::DISubprogram *sp =
+                   dyn_cast_or_null<llvm::DISubprogram>(scope))
+        scope = sp->getUnit();
 
       // Get the compile unit (scope) of the the global variable.
       if (llvm::DICompileUnit *compileUnit =
diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir
index 019e3565c3577..f89ef5af87f4b 100644
--- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir
@@ -347,6 +347,25 @@ llvm.mlir.global external @module_global() {dbg_expr = #llvm.di_global_variable_
 
 // -----
 
+// CHECK: @func_global = external global i64, !dbg {{.*}}
+// CHECK-DAG: ![[CU:.*]] = distinct !DICompileUnit({{.*}}globals: ![[GVALS:.*]])
+// CHECK-DAG: ![[SP:.*]] = distinct !DISubprogram(name: "fn_with_gl"{{.*}}unit: ![[CU]])
+// CHECK-DAG: ![[GVAR:.*]] = distinct !DIGlobalVariable(name: "func_global"{{.*}}, scope: ![[SP]]{{.*}})
+// CHECK-DAG: ![[GEXPR:.*]] = !DIGlobalVariableExpression(var: ![[GVAR]], expr: !DIExpression())
+// CHECK-DAG: ![[GVALS]] = !{![[GEXPR]]}
+
+#file = #llvm.di_file<"test.f90" in "existence">
+#cu = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_Fortran95, file = #file, producer = "MLIR", isOptimized = true, emissionKind = Full>
+#ty1 = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 64, encoding = DW_ATE_signed>
+#sp = #llvm.di_subprogram<compileUnit = #cu, scope = #file, name = "fn_with_gl", file = #file, subprogramFlags = "Definition|Optimized">
+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
+
+llvm.func @fn_with_gl() {
+  llvm.return
+} loc(fused<#sp>["foo1.mlir":0:0])
+
+// -----
+
 // Nameless and scopeless global constant.
 
 // CHECK-LABEL: @.str.1 = external constant [10 x i8]



More information about the Mlir-commits mailing list