-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[mlir][debug] Allow global with local scope. #98358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
@llvm/pr-subscribers-mlir @llvm/pr-subscribers-mlir-llvm Author: Abid Qadeer (abidh) ChangesCurrently, 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
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. Full diff: https://github.com/llvm/llvm-project/pull/98358.diff 2 Files Affected:
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]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
LGTM modulo nit.
else if (llvm::DISubprogram *sp = | ||
dyn_cast_or_null<llvm::DISubprogram>(scope)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else if (llvm::DISubprogram *sp = | |
dyn_cast_or_null<llvm::DISubprogram>(scope)) | |
else if (auto *sp = | |
dyn_cast_if_present<llvm::DISubprogram>(scope)) |
nit: auto makes sense here and I believe dyn_cast_if_present is the more modern version.
PS feel free to change llvm::DIModule to auto in the if above as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for he review. I have made the suggested changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect!
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.
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
isDISubprogram
.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.