https://github.com/tru updated https://github.com/llvm/llvm-project/pull/100727
>From 2a986c55d135d1da7268c73ede08789497b7f992 Mon Sep 17 00:00:00 2001 From: Abid Qadeer <haqad...@amd.com> Date: Thu, 25 Jul 2024 13:52:50 +0100 Subject: [PATCH] [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 626022bfd18f335ef62a461992a05dfed4e6d715) --- .../lib/Optimizer/Transforms/AddDebugInfo.cpp | 181 ++++++++++-------- flang/test/Transforms/debug-96314.fir | 26 +++ 2 files changed, 132 insertions(+), 75 deletions(-) create mode 100644 flang/test/Transforms/debug-96314.fir diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 685a8645fa2fc..8751a3b2c322f 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -66,6 +66,9 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> { void handleGlobalOp(fir::GlobalOp glocalOp, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope, mlir::SymbolTable *symbolTable); + void handleFuncOp(mlir::func::FuncOp funcOp, mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DICompileUnitAttr cuAttr, + mlir::SymbolTable *symbolTable); }; static uint32_t getLineFromLoc(mlir::Location loc) { @@ -204,11 +207,112 @@ void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp, globalOp->setLoc(builder.getFusedLoc({globalOp->getLoc()}, gvAttr)); } +void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, + mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DICompileUnitAttr cuAttr, + mlir::SymbolTable *symbolTable) { + mlir::Location l = funcOp->getLoc(); + // If fused location has already been created then nothing to do + // Otherwise, create a fused location. + if (debugInfoIsAlreadySet(l)) + return; + + mlir::ModuleOp module = getOperation(); + mlir::MLIRContext *context = &getContext(); + mlir::OpBuilder builder(context); + llvm::StringRef fileName(fileAttr.getName()); + llvm::StringRef filePath(fileAttr.getDirectory()); + unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry()) + ? llvm::dwarf::getCallingConvention("DW_CC_program") + : llvm::dwarf::getCallingConvention("DW_CC_normal"); + + if (auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l)) { + fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue()); + filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue()); + } + + mlir::StringAttr fullName = mlir::StringAttr::get(context, funcOp.getName()); + mlir::Attribute attr = funcOp->getAttr(fir::getInternalFuncNameAttrName()); + mlir::StringAttr funcName = + (attr) ? mlir::cast<mlir::StringAttr>(attr) + : mlir::StringAttr::get(context, funcOp.getName()); + + auto result = fir::NameUniquer::deconstruct(funcName); + funcName = mlir::StringAttr::get(context, result.second.name); + + llvm::SmallVector<mlir::LLVM::DITypeAttr> types; + fir::DebugTypeGenerator typeGen(module); + for (auto resTy : funcOp.getResultTypes()) { + auto tyAttr = typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc()); + types.push_back(tyAttr); + } + for (auto inTy : funcOp.getArgumentTypes()) { + auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr, + cuAttr, funcOp.getLoc()); + types.push_back(tyAttr); + } + + mlir::LLVM::DISubroutineTypeAttr subTypeAttr = + mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types); + mlir::LLVM::DIFileAttr funcFileAttr = + mlir::LLVM::DIFileAttr::get(context, fileName, filePath); + + // Only definitions need a distinct identifier and a compilation unit. + mlir::DistinctAttr id; + mlir::LLVM::DIScopeAttr Scope = fileAttr; + mlir::LLVM::DICompileUnitAttr compilationUnit; + mlir::LLVM::DISubprogramFlags subprogramFlags = + mlir::LLVM::DISubprogramFlags{}; + if (isOptimized) + subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized; + if (!funcOp.isExternal()) { + id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); + compilationUnit = cuAttr; + subprogramFlags = + subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; + } + unsigned line = getLineFromLoc(l); + if (fir::isInternalProcedure(funcOp)) { + // For contained functions, the scope is the parent subroutine. + mlir::SymbolRefAttr sym = mlir::cast<mlir::SymbolRefAttr>( + funcOp->getAttr(fir::getHostSymbolAttrName())); + if (sym) { + if (auto func = + symbolTable->lookup<mlir::func::FuncOp>(sym.getLeafReference())) { + // Make sure that parent is processed. + handleFuncOp(func, fileAttr, cuAttr, symbolTable); + if (auto fusedLoc = + mlir::dyn_cast_if_present<mlir::FusedLoc>(func.getLoc())) { + if (auto spAttr = + mlir::dyn_cast_if_present<mlir::LLVM::DISubprogramAttr>( + fusedLoc.getMetadata())) + Scope = spAttr; + } + } + } + } else if (!result.second.modules.empty()) { + Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr, + line - 1, false); + } + + auto spAttr = mlir::LLVM::DISubprogramAttr::get( + context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr, + line, line, subprogramFlags, subTypeAttr); + funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); + + // Don't process variables if user asked for line tables only. + if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly) + return; + + funcOp.walk([&](fir::cg::XDeclareOp declOp) { + handleDeclareOp(declOp, fileAttr, spAttr, typeGen, symbolTable); + }); +} + void AddDebugInfoPass::runOnOperation() { mlir::ModuleOp module = getOperation(); mlir::MLIRContext *context = &getContext(); mlir::SymbolTable symbolTable(module); - mlir::OpBuilder builder(context); llvm::StringRef fileName; std::string filePath; // We need 2 type of file paths here. @@ -245,80 +349,7 @@ void AddDebugInfoPass::runOnOperation() { isOptimized, debugLevel); module.walk([&](mlir::func::FuncOp funcOp) { - mlir::Location l = funcOp->getLoc(); - // If fused location has already been created then nothing to do - // Otherwise, create a fused location. - if (debugInfoIsAlreadySet(l)) - return; - - unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry()) - ? llvm::dwarf::getCallingConvention("DW_CC_program") - : llvm::dwarf::getCallingConvention("DW_CC_normal"); - - if (auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l)) { - fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue()); - filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue()); - } - - mlir::StringAttr fullName = - mlir::StringAttr::get(context, funcOp.getName()); - mlir::Attribute attr = funcOp->getAttr(fir::getInternalFuncNameAttrName()); - mlir::StringAttr funcName = - (attr) ? mlir::cast<mlir::StringAttr>(attr) - : mlir::StringAttr::get(context, funcOp.getName()); - - auto result = fir::NameUniquer::deconstruct(funcName); - funcName = mlir::StringAttr::get(context, result.second.name); - - llvm::SmallVector<mlir::LLVM::DITypeAttr> types; - fir::DebugTypeGenerator typeGen(module); - for (auto resTy : funcOp.getResultTypes()) { - auto tyAttr = - typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc()); - types.push_back(tyAttr); - } - for (auto inTy : funcOp.getArgumentTypes()) { - auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr, - cuAttr, funcOp.getLoc()); - types.push_back(tyAttr); - } - - mlir::LLVM::DISubroutineTypeAttr subTypeAttr = - mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types); - mlir::LLVM::DIFileAttr funcFileAttr = - mlir::LLVM::DIFileAttr::get(context, fileName, filePath); - - // Only definitions need a distinct identifier and a compilation unit. - mlir::DistinctAttr id; - mlir::LLVM::DIScopeAttr Scope = fileAttr; - mlir::LLVM::DICompileUnitAttr compilationUnit; - mlir::LLVM::DISubprogramFlags subprogramFlags = - mlir::LLVM::DISubprogramFlags{}; - if (isOptimized) - subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized; - if (!funcOp.isExternal()) { - id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); - compilationUnit = cuAttr; - subprogramFlags = - subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; - } - unsigned line = getLineFromLoc(l); - if (!result.second.modules.empty()) - Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr, - line - 1, false); - - auto spAttr = mlir::LLVM::DISubprogramAttr::get( - context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr, - line, line, subprogramFlags, subTypeAttr); - funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); - - // Don't process variables if user asked for line tables only. - if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly) - return; - - funcOp.walk([&](fir::cg::XDeclareOp declOp) { - handleDeclareOp(declOp, fileAttr, spAttr, typeGen, &symbolTable); - }); + handleFuncOp(funcOp, fileAttr, cuAttr, &symbolTable); }); // Process any global which was not processed through DeclareOp. if (debugLevel == mlir::LLVM::DIEmissionKind::Full) { diff --git a/flang/test/Transforms/debug-96314.fir b/flang/test/Transforms/debug-96314.fir new file mode 100644 index 0000000000000..e2d0f24a1105c --- /dev/null +++ b/flang/test/Transforms/debug-96314.fir @@ -0,0 +1,26 @@ +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s -o - | FileCheck %s + +module attributes {dlti.dl_spec = #dlti.dl_spec<>} { + func.func @_QMhelperPmod_sub(%arg0: !fir.ref<i32> {fir.bindc_name = "a"} ) { + return + } loc(#loc1) + func.func private @_QMhelperFmod_subPchild1(%arg0: !fir.ref<i32> {fir.bindc_name = "b"} ) attributes {fir.host_symbol = @_QMhelperPmod_sub, llvm.linkage = #llvm.linkage<internal>} { + return + } loc(#loc2) + func.func @global_sub_(%arg0: !fir.ref<i32> {fir.bindc_name = "n"} ) attributes {fir.internal_name = "_QPglobal_sub"} { + return + } loc(#loc3) + func.func private @_QFglobal_subPchild2(%arg0: !fir.ref<i32> {fir.bindc_name = "c"}) attributes {fir.host_symbol = @global_sub_, llvm.linkage = #llvm.linkage<internal>} { + return + } loc(#loc4) +} + +#loc1 = loc("test.f90":5:1) +#loc2 = loc("test.f90":15:1) +#loc3 = loc("test.f90":25:1) +#loc4 = loc("test.f90":35:1) + +// CHECK-DAG: #[[SP1:.*]] = #llvm.di_subprogram<{{.*}}name = "mod_sub"{{.*}}> +// CHECK-DAG: #llvm.di_subprogram<{{.*}}scope = #[[SP1]], name = "child1"{{.*}}> +// CHECK-DAG: #[[SP2:.*]] = #llvm.di_subprogram<{{.*}}linkageName = "global_sub_"{{.*}}> +// CHECK-DAG: #llvm.di_subprogram<{{.*}}scope = #[[SP2]], name = "child2"{{.*}}> _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits