-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang][debug] Use DICompileUnit as scope. #96345
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
This PR is required for llvm#96316. For assumed size arrays, we don't have the size of the array in the last dimension. This is represented in metadata by having a DISubrange with no entry for count or upper bound. LLVM verifier allows a DISubrange with no count or upper bound only for Fortran. This language is set when DICompileUnit is processed. If a type is processed before DICompileUnit then Verifier will not allow DISubrange with not count or upper bound entry. It will fail with error "Subrange must contain count or upperBound". Above scenario easily happens if a subroutine at global scope takes assumed size parameter. The metadata on DISubprogram is such that type is processed before unit so we hit Verifier::visitDISubrange before language has been set to Fortran. I have worked around this issue by setting the scope of such functions to be DICompileUnit instead of DIFile. As scope metadata in DISubprogram is processed before type so this problem does not happen. Some other observations about this change: 1. It does not make any difference to the generated DWARF. 2. It bring subroutine inline with module as modules already set their scope to DiCompileUnit. 3. I also looked at the classic flang compiler and it also uses DICompileUnit as scope for such subroutines probably for the same reasons.
@llvm/pr-subscribers-flang-fir-hlfir Author: Abid Qadeer (abidh) ChangesThis PR is required for #96316 . For assumed size arrays, we don't have the size of the array in the last dimension. This is represented in metadata by having a DISubrange with no entry for count or upper bound. LLVM verifier allows a Above scenario easily happens if a subroutine at global scope takes assumed size parameter. The order of operands in I have worked around this issue by setting the scope of such functions to be Some other observations about this change:
Full diff: https://github.com/llvm/llvm-project/pull/96345.diff 2 Files Affected:
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 10c71d3fc9551..2216157f3378d 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -266,7 +266,7 @@ void AddDebugInfoPass::runOnOperation() {
// Only definitions need a distinct identifier and a compilation unit.
mlir::DistinctAttr id;
- mlir::LLVM::DIScopeAttr Scope = fileAttr;
+ mlir::LLVM::DIScopeAttr Scope = cuAttr;
mlir::LLVM::DICompileUnitAttr compilationUnit;
mlir::LLVM::DISubprogramFlags subprogramFlags =
mlir::LLVM::DISubprogramFlags{};
diff --git a/flang/test/Transforms/debug-line-table-inc-file.fir b/flang/test/Transforms/debug-line-table-inc-file.fir
index 065039b59c5ae..dcd11f75a487a 100644
--- a/flang/test/Transforms/debug-line-table-inc-file.fir
+++ b/flang/test/Transforms/debug-line-table-inc-file.fir
@@ -31,7 +31,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
// CHECK: #[[LOC_INC_FILE:.*]] = loc("{{.*}}inc.f90":1:1)
// CHECK: #[[LOC_FILE:.*]] = loc("{{.*}}simple.f90":3:1)
// CHECK: #[[DI_CU:.*]] = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #[[DI_FILE]], producer = "{{.*}}flang{{.*}}", isOptimized = false, emissionKind = LineTablesOnly>
-// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "sinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}>
-// CHECK: #[[DI_SP:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QQmain", linkageName = "_QQmain", file = #[[DI_FILE]], {{.*}}>
+// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_CU]], name = "sinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}>
+// CHECK: #[[DI_SP:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_CU]], name = "_QQmain", linkageName = "_QQmain", file = #[[DI_FILE]], {{.*}}>
// CHECK: #[[FUSED_LOC_INC_FILE]] = loc(fused<#[[DI_SP_INC]]>[#[[LOC_INC_FILE]]])
// CHECK: #[[FUSED_LOC_FILE]] = loc(fused<#[[DI_SP]]>[#[[LOC_FILE]]])
|
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.
Your reasoning for this change sounds good to me, but I am no expert on DWARF.
+0.5 (hopefully someone with more DWARF experience can review)
Thanks for the review. I have now opened #96474 to fix it properly in llvm. In case that fix is accepted, we will not need this work around. So I will put this on hold for now. |
This PR is required for #96316 . For assumed size arrays, we don't have the size of the array in the last dimension. This is represented in metadata by having a DISubrange with no entry for count or upper bound.
LLVM verifier allows a
DISubrange
with no count or upper bound only for Fortran here. This language is set here when DICompileUnit is processed. If a type is processed beforeDICompileUnit
then Verifier will not allowDISubrange
without count or upper bound entry. It will fail with errorSubrange must contain count or upperBound
.Above scenario easily happens if a subroutine at global scope takes assumed size parameter. The order of operands in
DISubprogram
is such thatType
is processed beforeUnit
so we hitVerifier::visitDISubrange
before language has been set to Fortran.I have worked around this issue by setting the scope of such functions to be
DICompileUnit
instead ofDIFile
. AsScope
metadata inDISubprogram
is processed beforeType
so this problem goes away.Some other observations about this change:
DICompileUnit
.DICompileUnit
as scope for such subroutines probably for the same reasons.