Skip to content

Commit 26f574b

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 f0bd705 commit 26f574b

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
@@ -306,9 +306,29 @@ void AddDebugInfoPass::runOnOperation() {
306306
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
307307
}
308308
unsigned line = getLineFromLoc(l);
309-
if (!result.second.modules.empty())
309+
if (fir::isInternalProcedure(funcOp)) {
310+
// For contained functions, the scope is the parent subroutine.
311+
mlir::SymbolRefAttr sym = mlir::cast<mlir::SymbolRefAttr>(
312+
funcOp->getAttr(fir::getHostSymbolAttrName()));
313+
if (sym) {
314+
if (auto func = symbolTable.lookup<mlir::func::FuncOp>(
315+
sym.getLeafReference())) {
316+
// FIXME: Can there be situation where we process contained function
317+
// before the parent?
318+
if (debugInfoIsAlreadySet(func.getLoc())) {
319+
if (auto fusedLoc = mlir::cast<mlir::FusedLoc>(func.getLoc())) {
320+
if (auto spAttr =
321+
mlir::dyn_cast_if_present<mlir::LLVM::DISubprogramAttr>(
322+
fusedLoc.getMetadata()))
323+
Scope = spAttr;
324+
}
325+
}
326+
}
327+
}
328+
} else if (!result.second.modules.empty()) {
310329
Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr,
311330
line - 1, false);
331+
}
312332

313333
auto spAttr = mlir::LLVM::DISubprogramAttr::get(
314334
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)