diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 00633b4104b6c..b21cb85e1256b 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -53,7 +53,7 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase { mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scopeAttr, fir::DebugTypeGenerator &typeGen, - mlir::SymbolTable *symbolTable); + mlir::SymbolTable *symbolTable, mlir::Value dummyScope); public: AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {} @@ -206,7 +206,8 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp, mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scopeAttr, fir::DebugTypeGenerator &typeGen, - mlir::SymbolTable *symbolTable) { + mlir::SymbolTable *symbolTable, + mlir::Value dummyScope) { mlir::MLIRContext *context = &getContext(); mlir::OpBuilder builder(context); auto result = fir::NameUniquer::deconstruct(declOp.getUniqName()); @@ -230,7 +231,7 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp, // Get the dummy argument position from the explicit attribute. unsigned argNo = 0; - if (declOp.getDummyScope()) { + if (dummyScope && declOp.getDummyScope() == dummyScope) { if (auto argNoOpt = declOp.getDummyArgNo()) argNo = *argNoOpt; } @@ -610,6 +611,21 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, funcOp->setLoc(builder.getFusedLoc({l}, spAttr)); addTargetOpDISP(/*lineTableOnly=*/false, entities); + // Find the first dummy_scope definition. This is the one of the current + // function. The other ones may come from inlined calls. The variables inside + // those inlined calls should not be identified as arguments of the current + // function. + mlir::Value dummyScope; + funcOp.walk([&](fir::UndefOp undef) -> mlir::WalkResult { + // TODO: delay fir.dummy_scope translation to undefined until + // codegeneration. This is nicer and safer to match. + if (llvm::isa(undef.getType())) { + dummyScope = undef; + return mlir::WalkResult::interrupt(); + } + return mlir::WalkResult::advance(); + }); + funcOp.walk([&](fir::cg::XDeclareOp declOp) { mlir::LLVM::DISubprogramAttr spTy = spAttr; if (auto tOp = declOp->getParentOfType()) { @@ -619,7 +635,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, spTy = sp; } } - handleDeclareOp(declOp, fileAttr, spTy, typeGen, symbolTable); + handleDeclareOp(declOp, fileAttr, spTy, typeGen, symbolTable, dummyScope); }); // commonBlockMap ensures that we don't create multiple DICommonBlockAttr of // the same name in one function. But it is ok (rather required) to create diff --git a/flang/test/Transforms/debug-dummy-argument-inline.fir b/flang/test/Transforms/debug-dummy-argument-inline.fir new file mode 100644 index 0000000000000..02f0d5c6539b4 --- /dev/null +++ b/flang/test/Transforms/debug-dummy-argument-inline.fir @@ -0,0 +1,36 @@ +// Tests that inlined calls arguments are not mistaken for the arguments of the +// procedure where the calls were inlined. +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s -o - | FileCheck %s + +// CHECK: #di_local_variable = #llvm.di_local_variable +// CHECK: #di_local_variable1 = #llvm.di_local_variable + +func.func @foo_(%arg0: !fir.ref {fir.bindc_name = "i"} loc("debug-dummy-argument-inline.f90":5:1)) attributes {fir.internal_name = "_QPfoo"} { + %0 = fir.undefined !fir.dscope loc(#loc5) + %1 = fircg.ext_declare %arg0 dummy_scope %0 arg 1 {uniq_name = "_QFfooEi"} : (!fir.ref, !fir.dscope) -> !fir.ref loc(#loc6) + %2 = fir.undefined !fir.dscope loc(#loc11) + %3 = fircg.ext_declare %1 dummy_scope %2 arg 1 {uniq_name = "_QFbarEi"} : (!fir.ref, !fir.dscope) -> !fir.ref loc(#loc12) + fir.call @buzz_(%3) fastmath : (!fir.ref) -> () loc(#loc13) + %4 = fir.undefined !fir.dscope loc(#loc14) + %5 = fircg.ext_declare %1 dummy_scope %4 arg 1 {uniq_name = "_QFbarEi"} : (!fir.ref, !fir.dscope) -> !fir.ref loc(#loc15) + fir.call @buzz_(%5) fastmath : (!fir.ref) -> () loc(#loc16) + return loc(#loc9) +} loc(#loc5) +func.func private @buzz_(!fir.ref) attributes {fir.internal_name = "_QPbuzz"} loc(#loc10) +#loc = loc("debug-dummy-argument-inline.f90":0:0) +#loc1 = loc("debug-dummy-argument-inline.f90":1:1) +#loc2 = loc("debug-dummy-argument-inline.f90":2:14) +#loc3 = loc("debug-dummy-argument-inline.f90":3:3) +#loc4 = loc("debug-dummy-argument-inline.f90":4:1) +#loc5 = loc("debug-dummy-argument-inline.f90":5:1) +#loc6 = loc("debug-dummy-argument-inline.f90":6:14) +#loc7 = loc("debug-dummy-argument-inline.f90":7:3) +#loc8 = loc("debug-dummy-argument-inline.f90":8:3) +#loc9 = loc("debug-dummy-argument-inline.f90":9:1) +#loc10 = loc("debug-dummy-argument-inline.f90":3:8) +#loc11 = loc(callsite(#loc1 at #loc7)) +#loc12 = loc(callsite(#loc2 at #loc7)) +#loc13 = loc(callsite(#loc3 at #loc7)) +#loc14 = loc(callsite(#loc1 at #loc8)) +#loc15 = loc(callsite(#loc2 at #loc8)) +#loc16 = loc(callsite(#loc3 at #loc8))