-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
release/19.x: [flang][debug] Set scope of internal functions correctly. (#99531) #100727
Conversation
@apolloww What do you think about merging this PR to the release branch? |
@llvm/pr-subscribers-flang-fir-hlfir Author: None (llvmbot) ChangesBackport 626022b Requested by: @pawosm-arm Full diff: https://github.com/llvm/llvm-project/pull/100727.diff 2 Files Affected:
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"{{.*}}>
|
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 llvm#96314 Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250527 (cherry picked from commit 626022b)
@pawosm-arm (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. |
Backport 626022b
Requested by: @pawosm-arm