Skip to content

Commit 2a986c5

Browse files
abidhtru
authored andcommitted
[flang][debug] Set scope of internal functions correctly. (#99531)
Summary: The functions internal to subroutine should have the scope set to the parent function. This allows a user to evaluate local variables of parent function when control is stopped in the child. Fixes #96314 Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250527 (cherry picked from commit 626022b)
1 parent 58f851d commit 2a986c5

File tree

2 files changed

+132
-75
lines changed

2 files changed

+132
-75
lines changed

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 106 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {
6666
void handleGlobalOp(fir::GlobalOp glocalOp, mlir::LLVM::DIFileAttr fileAttr,
6767
mlir::LLVM::DIScopeAttr scope,
6868
mlir::SymbolTable *symbolTable);
69+
void handleFuncOp(mlir::func::FuncOp funcOp, mlir::LLVM::DIFileAttr fileAttr,
70+
mlir::LLVM::DICompileUnitAttr cuAttr,
71+
mlir::SymbolTable *symbolTable);
6972
};
7073

7174
static uint32_t getLineFromLoc(mlir::Location loc) {
@@ -204,11 +207,112 @@ void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp,
204207
globalOp->setLoc(builder.getFusedLoc({globalOp->getLoc()}, gvAttr));
205208
}
206209

210+
void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
211+
mlir::LLVM::DIFileAttr fileAttr,
212+
mlir::LLVM::DICompileUnitAttr cuAttr,
213+
mlir::SymbolTable *symbolTable) {
214+
mlir::Location l = funcOp->getLoc();
215+
// If fused location has already been created then nothing to do
216+
// Otherwise, create a fused location.
217+
if (debugInfoIsAlreadySet(l))
218+
return;
219+
220+
mlir::ModuleOp module = getOperation();
221+
mlir::MLIRContext *context = &getContext();
222+
mlir::OpBuilder builder(context);
223+
llvm::StringRef fileName(fileAttr.getName());
224+
llvm::StringRef filePath(fileAttr.getDirectory());
225+
unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry())
226+
? llvm::dwarf::getCallingConvention("DW_CC_program")
227+
: llvm::dwarf::getCallingConvention("DW_CC_normal");
228+
229+
if (auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l)) {
230+
fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue());
231+
filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue());
232+
}
233+
234+
mlir::StringAttr fullName = mlir::StringAttr::get(context, funcOp.getName());
235+
mlir::Attribute attr = funcOp->getAttr(fir::getInternalFuncNameAttrName());
236+
mlir::StringAttr funcName =
237+
(attr) ? mlir::cast<mlir::StringAttr>(attr)
238+
: mlir::StringAttr::get(context, funcOp.getName());
239+
240+
auto result = fir::NameUniquer::deconstruct(funcName);
241+
funcName = mlir::StringAttr::get(context, result.second.name);
242+
243+
llvm::SmallVector<mlir::LLVM::DITypeAttr> types;
244+
fir::DebugTypeGenerator typeGen(module);
245+
for (auto resTy : funcOp.getResultTypes()) {
246+
auto tyAttr = typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc());
247+
types.push_back(tyAttr);
248+
}
249+
for (auto inTy : funcOp.getArgumentTypes()) {
250+
auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr,
251+
cuAttr, funcOp.getLoc());
252+
types.push_back(tyAttr);
253+
}
254+
255+
mlir::LLVM::DISubroutineTypeAttr subTypeAttr =
256+
mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types);
257+
mlir::LLVM::DIFileAttr funcFileAttr =
258+
mlir::LLVM::DIFileAttr::get(context, fileName, filePath);
259+
260+
// Only definitions need a distinct identifier and a compilation unit.
261+
mlir::DistinctAttr id;
262+
mlir::LLVM::DIScopeAttr Scope = fileAttr;
263+
mlir::LLVM::DICompileUnitAttr compilationUnit;
264+
mlir::LLVM::DISubprogramFlags subprogramFlags =
265+
mlir::LLVM::DISubprogramFlags{};
266+
if (isOptimized)
267+
subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized;
268+
if (!funcOp.isExternal()) {
269+
id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context));
270+
compilationUnit = cuAttr;
271+
subprogramFlags =
272+
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
273+
}
274+
unsigned line = getLineFromLoc(l);
275+
if (fir::isInternalProcedure(funcOp)) {
276+
// For contained functions, the scope is the parent subroutine.
277+
mlir::SymbolRefAttr sym = mlir::cast<mlir::SymbolRefAttr>(
278+
funcOp->getAttr(fir::getHostSymbolAttrName()));
279+
if (sym) {
280+
if (auto func =
281+
symbolTable->lookup<mlir::func::FuncOp>(sym.getLeafReference())) {
282+
// Make sure that parent is processed.
283+
handleFuncOp(func, fileAttr, cuAttr, symbolTable);
284+
if (auto fusedLoc =
285+
mlir::dyn_cast_if_present<mlir::FusedLoc>(func.getLoc())) {
286+
if (auto spAttr =
287+
mlir::dyn_cast_if_present<mlir::LLVM::DISubprogramAttr>(
288+
fusedLoc.getMetadata()))
289+
Scope = spAttr;
290+
}
291+
}
292+
}
293+
} else if (!result.second.modules.empty()) {
294+
Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr,
295+
line - 1, false);
296+
}
297+
298+
auto spAttr = mlir::LLVM::DISubprogramAttr::get(
299+
context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr,
300+
line, line, subprogramFlags, subTypeAttr);
301+
funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));
302+
303+
// Don't process variables if user asked for line tables only.
304+
if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly)
305+
return;
306+
307+
funcOp.walk([&](fir::cg::XDeclareOp declOp) {
308+
handleDeclareOp(declOp, fileAttr, spAttr, typeGen, symbolTable);
309+
});
310+
}
311+
207312
void AddDebugInfoPass::runOnOperation() {
208313
mlir::ModuleOp module = getOperation();
209314
mlir::MLIRContext *context = &getContext();
210315
mlir::SymbolTable symbolTable(module);
211-
mlir::OpBuilder builder(context);
212316
llvm::StringRef fileName;
213317
std::string filePath;
214318
// We need 2 type of file paths here.
@@ -245,80 +349,7 @@ void AddDebugInfoPass::runOnOperation() {
245349
isOptimized, debugLevel);
246350

247351
module.walk([&](mlir::func::FuncOp funcOp) {
248-
mlir::Location l = funcOp->getLoc();
249-
// If fused location has already been created then nothing to do
250-
// Otherwise, create a fused location.
251-
if (debugInfoIsAlreadySet(l))
252-
return;
253-
254-
unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry())
255-
? llvm::dwarf::getCallingConvention("DW_CC_program")
256-
: llvm::dwarf::getCallingConvention("DW_CC_normal");
257-
258-
if (auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l)) {
259-
fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue());
260-
filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue());
261-
}
262-
263-
mlir::StringAttr fullName =
264-
mlir::StringAttr::get(context, funcOp.getName());
265-
mlir::Attribute attr = funcOp->getAttr(fir::getInternalFuncNameAttrName());
266-
mlir::StringAttr funcName =
267-
(attr) ? mlir::cast<mlir::StringAttr>(attr)
268-
: mlir::StringAttr::get(context, funcOp.getName());
269-
270-
auto result = fir::NameUniquer::deconstruct(funcName);
271-
funcName = mlir::StringAttr::get(context, result.second.name);
272-
273-
llvm::SmallVector<mlir::LLVM::DITypeAttr> types;
274-
fir::DebugTypeGenerator typeGen(module);
275-
for (auto resTy : funcOp.getResultTypes()) {
276-
auto tyAttr =
277-
typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc());
278-
types.push_back(tyAttr);
279-
}
280-
for (auto inTy : funcOp.getArgumentTypes()) {
281-
auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr,
282-
cuAttr, funcOp.getLoc());
283-
types.push_back(tyAttr);
284-
}
285-
286-
mlir::LLVM::DISubroutineTypeAttr subTypeAttr =
287-
mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types);
288-
mlir::LLVM::DIFileAttr funcFileAttr =
289-
mlir::LLVM::DIFileAttr::get(context, fileName, filePath);
290-
291-
// Only definitions need a distinct identifier and a compilation unit.
292-
mlir::DistinctAttr id;
293-
mlir::LLVM::DIScopeAttr Scope = fileAttr;
294-
mlir::LLVM::DICompileUnitAttr compilationUnit;
295-
mlir::LLVM::DISubprogramFlags subprogramFlags =
296-
mlir::LLVM::DISubprogramFlags{};
297-
if (isOptimized)
298-
subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized;
299-
if (!funcOp.isExternal()) {
300-
id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context));
301-
compilationUnit = cuAttr;
302-
subprogramFlags =
303-
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
304-
}
305-
unsigned line = getLineFromLoc(l);
306-
if (!result.second.modules.empty())
307-
Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr,
308-
line - 1, false);
309-
310-
auto spAttr = mlir::LLVM::DISubprogramAttr::get(
311-
context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr,
312-
line, line, subprogramFlags, subTypeAttr);
313-
funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));
314-
315-
// Don't process variables if user asked for line tables only.
316-
if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly)
317-
return;
318-
319-
funcOp.walk([&](fir::cg::XDeclareOp declOp) {
320-
handleDeclareOp(declOp, fileAttr, spAttr, typeGen, &symbolTable);
321-
});
352+
handleFuncOp(funcOp, fileAttr, cuAttr, &symbolTable);
322353
});
323354
// Process any global which was not processed through DeclareOp.
324355
if (debugLevel == mlir::LLVM::DIEmissionKind::Full) {

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)