Skip to content

Commit f938ad6

Browse files
committed
[flang][debug] Set scope of internal functions correctly.
The functions internal to subroutine should have the scope set to the parent function. This allows to evaluate variable in parent when control is stopped in the child. Fixes #96314
1 parent c5329c8 commit f938ad6

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,29 @@ void AddDebugInfoPass::runOnOperation() {
299299
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
300300
}
301301
unsigned line = getLineFromLoc(l);
302-
if (!result.second.modules.empty())
302+
if (fir::isInternalProcedure(funcOp)) {
303+
// For contained functions, the scope is the parent subroutine.
304+
mlir::SymbolRefAttr sym = mlir::cast<mlir::SymbolRefAttr>(
305+
funcOp->getAttr(fir::getHostSymbolAttrName()));
306+
if (sym) {
307+
if (auto func = symbolTable.lookup<mlir::func::FuncOp>(
308+
sym.getLeafReference())) {
309+
// FIXME: Can there be situation where we process contained function
310+
// before the parent?
311+
if (debugInfoIsAlreadySet(func.getLoc())) {
312+
if (auto fusedLoc = mlir::cast<mlir::FusedLoc>(func.getLoc())) {
313+
if (auto spAttr =
314+
mlir::dyn_cast_if_present<mlir::LLVM::DISubprogramAttr>(
315+
fusedLoc.getMetadata()))
316+
Scope = spAttr;
317+
}
318+
}
319+
}
320+
}
321+
} else if (!result.second.modules.empty()) {
303322
Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr,
304323
line - 1, false);
324+
}
305325

306326
auto spAttr = mlir::LLVM::DISubprogramAttr::get(
307327
context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr,

flang/test/Transforms/debug-96314.fir

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s -o - | FileCheck %s
2+
3+
module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
4+
func.func @_QMhelperPmod_sub(%arg0: !fir.ref<i32> {fir.bindc_name = "a"} ) {
5+
return
6+
} loc(#loc1)
7+
func.func private @_QMhelperFmod_subPchild1(%arg0: !fir.ref<i32> {fir.bindc_name = "b"} ) attributes {fir.host_symbol = @_QMhelperPmod_sub, llvm.linkage = #llvm.linkage<internal>} {
8+
return
9+
} loc(#loc2)
10+
func.func @global_sub_(%arg0: !fir.ref<i32> {fir.bindc_name = "n"} ) attributes {fir.internal_name = "_QPglobal_sub"} {
11+
return
12+
} loc(#loc3)
13+
func.func private @_QFglobal_subPchild2(%arg0: !fir.ref<i32> {fir.bindc_name = "c"}) attributes {fir.host_symbol = @global_sub_, llvm.linkage = #llvm.linkage<internal>} {
14+
return
15+
} loc(#loc4)
16+
}
17+
18+
#loc1 = loc("test.f90":5:1)
19+
#loc2 = loc("test.f90":15:1)
20+
#loc3 = loc("test.f90":25:1)
21+
#loc4 = loc("test.f90":35:1)
22+
23+
// CHECK-DAG: #[[SP1:.*]] = #llvm.di_subprogram<{{.*}}name = "mod_sub"{{.*}}>
24+
// CHECK-DAG: #llvm.di_subprogram<{{.*}}scope = #[[SP1]], name = "child1"{{.*}}>
25+
// CHECK-DAG: #[[SP2:.*]] = #llvm.di_subprogram<{{.*}}linkageName = "global_sub_"{{.*}}>
26+
// CHECK-DAG: #llvm.di_subprogram<{{.*}}scope = #[[SP2]], name = "child2"{{.*}}>

0 commit comments

Comments
 (0)