From 576842c4d9554a315879d14108eac201ce20e756 Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Tue, 29 Apr 2025 12:30:42 +0100 Subject: [PATCH 1/5] [flang][debug] Generate DISubprogramAttr for omp::TargetOp. There are DeclareOp present for the variables mapped into target region. That allow us to generate debug information for them. Bu the TargetOp is still part of parent function and those variables get the parent function's DISubprogram as a scope. In OMPIRBuilder, a new function is created for the TargetOp. We also create a new DISubprogram for it. All the variables that were in the target region now have to be updated to have the correct scope. This after the fact updating of debug information becomes very difficult in certain cases. Take the example of variable arrays. The type of those arrays depend on the artificial DILocalVariable(s) which hold the size(s) of the array. This new function will now require that we generate the new variable and and new types. Similar issue exist for character type variables too. To avoid this after the fact updating, this PR generates a DISubprogramAttr for the TargetOp while generating the debug info in flang. This help us avoid updating later. This PR is flang side of the change. I will open another PR which will make the required changes in OMPIRBuilder. --- .../lib/Optimizer/Transforms/AddDebugInfo.cpp | 99 ++++++++++++++++++- .../test/Transforms/debug-omp-target-op-1.fir | 35 +++++++ .../test/Transforms/debug-omp-target-op-2.fir | 53 ++++++++++ 3 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 flang/test/Transforms/debug-omp-target-op-1.fir create mode 100644 flang/test/Transforms/debug-omp-target-op-2.fir diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 8fa2f38818c02..8eb538da3a6eb 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -35,6 +35,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -104,6 +105,37 @@ bool debugInfoIsAlreadySet(mlir::Location loc) { return false; } +// Generates the name for the artificial DISubprogram that we are going to +// generate for omp::TargetOp. Its logic is borrowed from +// getTargetEntryUniqueInfo and +// TargetRegionEntryInfo::getTargetRegionEntryFnName to generate the same name. +// But even if there was a slight mismatch, it is not a problem because this +// name is artifical and not important to debug experience. +mlir::StringAttr getTargetFunctionName(mlir::MLIRContext *context, + mlir::Location Loc, + llvm::StringRef parentName) { + auto fileLoc = Loc->findInstanceOf(); + + assert(fileLoc && "No file found from location"); + llvm::StringRef fileName = fileLoc.getFilename().getValue(); + + llvm::sys::fs::UniqueID id; + uint64_t line = fileLoc.getLine(); + size_t fileId; + size_t deviceId; + if (auto ec = llvm::sys::fs::getUniqueID(fileName, id)) { + fileId = llvm::hash_value(fileName.str()); + deviceId = 0xdeadf17e; + } else { + fileId = id.getFile(); + deviceId = id.getDevice(); + } + return mlir::StringAttr::get( + context, + std::string(llvm::formatv("__omp_offloading_{0:x-}_{1:x-}_{2}_l{3}", + deviceId, fileId, parentName, line))); +} + } // namespace bool AddDebugInfoPass::createCommonBlockGlobal( @@ -511,8 +543,73 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, subTypeAttr, entities, /*annotations=*/{}); funcOp->setLoc(builder.getFusedLoc({l}, spAttr)); + /* When we process the DeclareOp inside the OpenMP target region, all the + variables get the DISubprogram of the parent function of the target op as + the scope. In the codegen (to llvm ir), OpenMP target op results in the + creation of a separate function. As the variables in the debug info have + the DISubprogram of the parent function as the scope, the variables + need to be updated at codegen time to avoid verification failures. + + This updating after the fact becomes more and more difficult when types + are dependent on local variables like in the case of variable size arrays + or string. We not only have to generate new variables but also new types. + We can avoid this problem by generating a DISubprogramAttr here for the + target op and make sure that all the variables inside the target region + get the correct scope in the first place. */ + funcOp.walk([&](mlir::omp::TargetOp targetOp) { + unsigned line = getLineFromLoc(targetOp.getLoc()); + mlir::StringAttr Name = + getTargetFunctionName(context, targetOp.getLoc(), funcOp.getName()); + mlir::LLVM::DISubprogramFlags flags = + mlir::LLVM::DISubprogramFlags::Definition | + mlir::LLVM::DISubprogramFlags::LocalToUnit; + if (isOptimized) + flags = flags | mlir::LLVM::DISubprogramFlags::Optimized; + + mlir::DistinctAttr recId = + mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); + mlir::DistinctAttr Id = + mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); + llvm::SmallVector types; + types.push_back(mlir::LLVM::DINullTypeAttr::get(context)); + mlir::LLVM::DISubroutineTypeAttr spTy = + mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types); + auto spAttr = mlir::LLVM::DISubprogramAttr::get( + context, recId, /*isRecSelf=*/true, Id, compilationUnit, Scope, Name, + Name, funcFileAttr, line, line, flags, spTy, /*retainedNodes=*/{}, + /*annotations=*/{}); + + // Make sure that information about the imported modules in copied from the + // parent function. + llvm::SmallVector OpEntities; + for (mlir::LLVM::DINodeAttr N : entities) { + if (auto entity = mlir::dyn_cast(N)) { + auto importedEntity = mlir::LLVM::DIImportedEntityAttr::get( + context, llvm::dwarf::DW_TAG_imported_module, spAttr, + entity.getEntity(), fileAttr, /*line=*/1, /*name=*/nullptr, + /*elements*/ {}); + OpEntities.push_back(importedEntity); + } + } + + Id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); + spAttr = mlir::LLVM::DISubprogramAttr::get( + context, recId, /*isRecSelf=*/false, Id, compilationUnit, Scope, Name, + Name, funcFileAttr, line, line, flags, spTy, OpEntities, + /*annotations=*/{}); + targetOp->setLoc(builder.getFusedLoc({targetOp.getLoc()}, spAttr)); + }); + funcOp.walk([&](fir::cg::XDeclareOp declOp) { - handleDeclareOp(declOp, fileAttr, spAttr, typeGen, symbolTable); + mlir::LLVM::DISubprogramAttr spTy = spAttr; + if (auto tOp = declOp->getParentOfType()) { + if (auto fusedLoc = llvm::dyn_cast(tOp.getLoc())) { + if (auto sp = llvm::dyn_cast( + fusedLoc.getMetadata())) + spTy = sp; + } + } + handleDeclareOp(declOp, fileAttr, spTy, typeGen, symbolTable); }); // 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-omp-target-op-1.fir b/flang/test/Transforms/debug-omp-target-op-1.fir new file mode 100644 index 0000000000000..bb586cdf6e9ab --- /dev/null +++ b/flang/test/Transforms/debug-omp-target-op-1.fir @@ -0,0 +1,35 @@ +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s + +module attributes {dlti.dl_spec = #dlti.dl_spec<>} { + func.func @_QQmain() attributes {fir.bindc_name = "test"} { + %c13_i32 = arith.constant 13 : i32 + %c12_i32 = arith.constant 12 : i32 + %c6_i32 = arith.constant 6 : i32 + %c1_i32 = arith.constant 1 : i32 + %c5_i32 = arith.constant 5 : i32 + %0 = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} loc(#loc1) + %1 = fircg.ext_declare %0 {uniq_name = "_QFEx"} : (!fir.ref) -> !fir.ref loc(#loc1) + %2 = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} loc(#loc2) + %3 = fircg.ext_declare %2 {uniq_name = "_QFEy"} : (!fir.ref) -> !fir.ref loc(#loc2) + %4 = omp.map.info var_ptr(%1 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "x"} + %5 = omp.map.info var_ptr(%3 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "y"} + omp.target map_entries(%4 -> %arg0, %5 -> %arg1 : !fir.ref, !fir.ref) { + %16 = fircg.ext_declare %arg0 {uniq_name = "_QFEx"} : (!fir.ref) -> !fir.ref loc(#loc3) + %17 = fircg.ext_declare %arg1 {uniq_name = "_QFEy"} : (!fir.ref) -> !fir.ref loc(#loc4) + omp.terminator + } loc(#loc5) + return + } +} +#loc1 = loc("test.f90":1:1) +#loc2 = loc("test.f90":3:1) +#loc3 = loc("test.f90":7:1) +#loc4 = loc("test.f90":8:1) +#loc5 = loc("test.f90":6:1) + +// CHECK: #[[SP:.*]] = #llvm.di_subprogram<{{.*}}name = "test"{{.*}}> +// CHECK: #[[SP1:.*]] = #llvm.di_subprogram<{{.*}}name = "__omp_offloading_{{.*}}_QQmain_l6"{{.*}}line = 6{{.*}}subprogramFlags = "LocalToUnit|Definition"{{.*}}> +// CHECK: #llvm.di_local_variable +// CHECK: #llvm.di_local_variable +// CHECK: #llvm.di_local_variable +// CHECK: #llvm.di_local_variable diff --git a/flang/test/Transforms/debug-omp-target-op-2.fir b/flang/test/Transforms/debug-omp-target-op-2.fir new file mode 100644 index 0000000000000..15dcf2389b21d --- /dev/null +++ b/flang/test/Transforms/debug-omp-target-op-2.fir @@ -0,0 +1,53 @@ +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s + +module attributes {dlti.dl_spec = #dlti.dl_spec<>} { + func.func @fn_(%arg0: !fir.ref> {fir.bindc_name = "b"}, %arg1: !fir.ref {fir.bindc_name = "c"}, %arg2: !fir.ref {fir.bindc_name = "d"}) { + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %0 = fir.alloca i32 + %1 = fir.alloca i32 + %2 = fir.undefined !fir.dscope + %3 = fircg.ext_declare %arg1 dummy_scope %2 {uniq_name = "_QFfnEc"} : (!fir.ref, !fir.dscope) -> !fir.ref loc(#loc2) + %4 = fircg.ext_declare %arg2 dummy_scope %2 {uniq_name = "_QFfnEd"} : (!fir.ref, !fir.dscope) -> !fir.ref loc(#loc3) + %5 = fir.load %3 : !fir.ref + %6 = fir.convert %5 : (i32) -> index + %9 = fir.load %4 : !fir.ref + %10 = fir.convert %9 : (i32) -> index + %15 = fircg.ext_declare %arg0(%6, %10) dummy_scope %2 {uniq_name = "_QFfnEb"} : (!fir.ref>, index, index, !fir.dscope) -> !fir.ref> loc(#loc4) + %16 = fircg.ext_embox %15(%6, %10) : (!fir.ref>, index, index) -> !fir.box> + %17:3 = fir.box_dims %16, %c0 : (!fir.box>, index) -> (index, index, index) + %18 = arith.subi %17#1, %c1 : index + %19 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%18 : index) extent(%17#1 : index) stride(%17#2 : index) start_idx(%c1 : index) {stride_in_bytes = true} + %20 = arith.muli %17#2, %17#1 : index + %21:3 = fir.box_dims %16, %c1 : (!fir.box>, index) -> (index, index, index) + %22 = arith.subi %21#1, %c1 : index + %23 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%22 : index) extent(%21#1 : index) stride(%20 : index) start_idx(%c1 : index) {stride_in_bytes = true} + %24 = omp.map.info var_ptr(%15 : !fir.ref>, i32) map_clauses(tofrom) capture(ByRef) bounds(%19, %23) -> !fir.ref> {name = "b"} + %25 = omp.map.info var_ptr(%1 : !fir.ref, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref {name = ""} + %26 = omp.map.info var_ptr(%0 : !fir.ref, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref {name = ""} + omp.target map_entries(%24 -> %arg3, %25 -> %arg4, %26 -> %arg5 : !fir.ref>, !fir.ref, !fir.ref) { + %27 = fir.load %arg5 : !fir.ref + %28 = fir.load %arg4 : !fir.ref + %29 = fir.convert %27 : (i32) -> index + %31 = fir.convert %28 : (i32) -> index + %37 = fircg.ext_declare %arg3(%29, %31) {uniq_name = "_QFfnEb"} : (!fir.ref>, index, index) -> !fir.ref> loc(#loc5) + omp.terminator + } loc(#loc6) + return + } loc(#loc7) +} +#loc1 = loc("test.f90":1:1) +#loc2 = loc("test.f90":3:1) +#loc3 = loc("test.f90":7:1) +#loc4 = loc("test.f90":8:1) +#loc5 = loc("test.f90":6:1) +#loc6 = loc("test.f90":16:1) +#loc7 = loc("test.f90":26:1) + + +// Test that variable size arrays inside target regions get their own +// compiler generated variables for size. + +// CHECK: #[[SP:.*]] = #llvm.di_subprogram<{{.*}}name = "__omp_offloading_{{.*}}_fn__l16"{{.*}}> +// CHECK: #llvm.di_local_variable +// CHECK: #llvm.di_local_variable From b4d7e29984d8f7181f461801b779f6bb517da15c Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Sun, 18 May 2025 11:23:52 +0100 Subject: [PATCH 2/5] Handle review comments. Main change is that we also take care of the case when only line table information is requested. --- .../lib/Optimizer/Transforms/AddDebugInfo.cpp | 128 ++++++++++-------- .../test/Transforms/debug-omp-target-op-1.fir | 5 + 2 files changed, 75 insertions(+), 58 deletions(-) diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 8eb538da3a6eb..89be212d46088 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -110,7 +110,7 @@ bool debugInfoIsAlreadySet(mlir::Location loc) { // getTargetEntryUniqueInfo and // TargetRegionEntryInfo::getTargetRegionEntryFnName to generate the same name. // But even if there was a slight mismatch, it is not a problem because this -// name is artifical and not important to debug experience. +// name is artificial and not important to debug experience. mlir::StringAttr getTargetFunctionName(mlir::MLIRContext *context, mlir::Location Loc, llvm::StringRef parentName) { @@ -478,6 +478,73 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, line - 1, false); } + auto addTargetOpDISP = [&](bool lineTableOnly, + const llvm::SmallVector &entities) { + // When we process the DeclareOp inside the OpenMP target region, all the + // variables get the DISubprogram of the parent function of the target op as + // the scope. In the codegen (to llvm ir), OpenMP target op results in the + // creation of a separate function. As the variables in the debug info have + // the DISubprogram of the parent function as the scope, the variables + // need to be updated at codegen time to avoid verification failures. + + // This updating after the fact becomes more and more difficult when types + // are dependent on local variables like in the case of variable size arrays + // or string. We not only have to generate new variables but also new types. + // We can avoid this problem by generating a DISubprogramAttr here for the + // target op and make sure that all the variables inside the target region + // get the correct scope in the first place. + funcOp.walk([&](mlir::omp::TargetOp targetOp) { + unsigned line = getLineFromLoc(targetOp.getLoc()); + mlir::StringAttr name = + getTargetFunctionName(context, targetOp.getLoc(), funcOp.getName()); + mlir::LLVM::DISubprogramFlags flags = + mlir::LLVM::DISubprogramFlags::Definition | + mlir::LLVM::DISubprogramFlags::LocalToUnit; + if (isOptimized) + flags = flags | mlir::LLVM::DISubprogramFlags::Optimized; + + mlir::DistinctAttr id = + mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); + llvm::SmallVector types; + types.push_back(mlir::LLVM::DINullTypeAttr::get(context)); + mlir::LLVM::DISubroutineTypeAttr spTy = + mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types); + if (lineTableOnly) { + auto spAttr = mlir::LLVM::DISubprogramAttr::get( + context, id, compilationUnit, Scope, name, name, funcFileAttr, line, + line, flags, spTy, /*retainedNodes=*/{}, /*annotations=*/{}); + targetOp->setLoc(builder.getFusedLoc({targetOp.getLoc()}, spAttr)); + return; + } + mlir::DistinctAttr recId = + mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); + auto spAttr = mlir::LLVM::DISubprogramAttr::get( + context, recId, /*isRecSelf=*/true, id, compilationUnit, Scope, name, + name, funcFileAttr, line, line, flags, spTy, /*retainedNodes=*/{}, + /*annotations=*/{}); + + // Make sure that information about the imported modules is copied in the + // new function. + llvm::SmallVector opEntities; + for (mlir::LLVM::DINodeAttr N : entities) { + if (auto entity = mlir::dyn_cast(N)) { + auto importedEntity = mlir::LLVM::DIImportedEntityAttr::get( + context, llvm::dwarf::DW_TAG_imported_module, spAttr, + entity.getEntity(), fileAttr, /*line=*/1, /*name=*/nullptr, + /*elements*/ {}); + opEntities.push_back(importedEntity); + } + } + + id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); + spAttr = mlir::LLVM::DISubprogramAttr::get( + context, recId, /*isRecSelf=*/false, id, compilationUnit, Scope, name, + name, funcFileAttr, line, line, flags, spTy, opEntities, + /*annotations=*/{}); + targetOp->setLoc(builder.getFusedLoc({targetOp.getLoc()}, spAttr)); + }); + }; + // Don't process variables if user asked for line tables only. if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly) { auto spAttr = mlir::LLVM::DISubprogramAttr::get( @@ -485,6 +552,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, line, line, subprogramFlags, subTypeAttr, /*retainedNodes=*/{}, /*annotations=*/{}); funcOp->setLoc(builder.getFusedLoc({l}, spAttr)); + addTargetOpDISP(true, {}); return; } @@ -542,63 +610,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, funcName, fullName, funcFileAttr, line, line, subprogramFlags, subTypeAttr, entities, /*annotations=*/{}); funcOp->setLoc(builder.getFusedLoc({l}, spAttr)); - - /* When we process the DeclareOp inside the OpenMP target region, all the - variables get the DISubprogram of the parent function of the target op as - the scope. In the codegen (to llvm ir), OpenMP target op results in the - creation of a separate function. As the variables in the debug info have - the DISubprogram of the parent function as the scope, the variables - need to be updated at codegen time to avoid verification failures. - - This updating after the fact becomes more and more difficult when types - are dependent on local variables like in the case of variable size arrays - or string. We not only have to generate new variables but also new types. - We can avoid this problem by generating a DISubprogramAttr here for the - target op and make sure that all the variables inside the target region - get the correct scope in the first place. */ - funcOp.walk([&](mlir::omp::TargetOp targetOp) { - unsigned line = getLineFromLoc(targetOp.getLoc()); - mlir::StringAttr Name = - getTargetFunctionName(context, targetOp.getLoc(), funcOp.getName()); - mlir::LLVM::DISubprogramFlags flags = - mlir::LLVM::DISubprogramFlags::Definition | - mlir::LLVM::DISubprogramFlags::LocalToUnit; - if (isOptimized) - flags = flags | mlir::LLVM::DISubprogramFlags::Optimized; - - mlir::DistinctAttr recId = - mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); - mlir::DistinctAttr Id = - mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); - llvm::SmallVector types; - types.push_back(mlir::LLVM::DINullTypeAttr::get(context)); - mlir::LLVM::DISubroutineTypeAttr spTy = - mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types); - auto spAttr = mlir::LLVM::DISubprogramAttr::get( - context, recId, /*isRecSelf=*/true, Id, compilationUnit, Scope, Name, - Name, funcFileAttr, line, line, flags, spTy, /*retainedNodes=*/{}, - /*annotations=*/{}); - - // Make sure that information about the imported modules in copied from the - // parent function. - llvm::SmallVector OpEntities; - for (mlir::LLVM::DINodeAttr N : entities) { - if (auto entity = mlir::dyn_cast(N)) { - auto importedEntity = mlir::LLVM::DIImportedEntityAttr::get( - context, llvm::dwarf::DW_TAG_imported_module, spAttr, - entity.getEntity(), fileAttr, /*line=*/1, /*name=*/nullptr, - /*elements*/ {}); - OpEntities.push_back(importedEntity); - } - } - - Id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); - spAttr = mlir::LLVM::DISubprogramAttr::get( - context, recId, /*isRecSelf=*/false, Id, compilationUnit, Scope, Name, - Name, funcFileAttr, line, line, flags, spTy, OpEntities, - /*annotations=*/{}); - targetOp->setLoc(builder.getFusedLoc({targetOp.getLoc()}, spAttr)); - }); + addTargetOpDISP(false, entities); funcOp.walk([&](fir::cg::XDeclareOp declOp) { mlir::LLVM::DISubprogramAttr spTy = spAttr; diff --git a/flang/test/Transforms/debug-omp-target-op-1.fir b/flang/test/Transforms/debug-omp-target-op-1.fir index bb586cdf6e9ab..6b895b732c42b 100644 --- a/flang/test/Transforms/debug-omp-target-op-1.fir +++ b/flang/test/Transforms/debug-omp-target-op-1.fir @@ -1,4 +1,5 @@ // RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s +// RUN: fir-opt --add-debug-info="debug-level=LineTablesOnly" --mlir-print-debuginfo %s | FileCheck %s --check-prefix=LINETABLE module attributes {dlti.dl_spec = #dlti.dl_spec<>} { func.func @_QQmain() attributes {fir.bindc_name = "test"} { @@ -33,3 +34,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} { // CHECK: #llvm.di_local_variable // CHECK: #llvm.di_local_variable // CHECK: #llvm.di_local_variable + +// LINETABLE: #[[SP:.*]] = #llvm.di_subprogram<{{.*}}name = "test"{{.*}}> +// LINETABLE: #[[SP1:.*]] = #llvm.di_subprogram<{{.*}}name = "__omp_offloading_{{.*}}_QQmain_l6"{{.*}}line = 6{{.*}}subprogramFlags = "LocalToUnit|Definition"{{.*}}> +// LINETABLE-NOT: #llvm.di_local_variable From 8b09d38fdaff5efb30c79fc30131caa28091de85 Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Tue, 20 May 2025 12:12:38 +0100 Subject: [PATCH 3/5] Handle review comments. Use the arguments to the TargetOp in the subroutine type created for it. --- flang/lib/Optimizer/Transforms/AddDebugInfo.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 89be212d46088..20e89071307e3 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -507,6 +507,12 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); llvm::SmallVector types; types.push_back(mlir::LLVM::DINullTypeAttr::get(context)); + for (auto arg : targetOp.getRegion().getArguments()) { + auto tyAttr = typeGen.convertType(fir::unwrapRefType(arg.getType()), + fileAttr, cuAttr, /*declOp=*/nullptr); + types.push_back(tyAttr); + } + CC = llvm::dwarf::getCallingConvention("DW_CC_normal"); mlir::LLVM::DISubroutineTypeAttr spTy = mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types); if (lineTableOnly) { From 6c325bdf0fe234afcda23c173ab63d59b788a5a8 Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Tue, 20 May 2025 12:29:10 +0100 Subject: [PATCH 4/5] Fix formatting issues. --- flang/lib/Optimizer/Transforms/AddDebugInfo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 20e89071307e3..0f319ff5518c0 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -479,7 +479,8 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, } auto addTargetOpDISP = [&](bool lineTableOnly, - const llvm::SmallVector &entities) { + const llvm::SmallVector + &entities) { // When we process the DeclareOp inside the OpenMP target region, all the // variables get the DISubprogram of the parent function of the target op as // the scope. In the codegen (to llvm ir), OpenMP target op results in the From 0d51206eae656847ac480c56163375535206d384 Mon Sep 17 00:00:00 2001 From: Abid Qadeer Date: Wed, 18 Jun 2025 15:19:58 +0100 Subject: [PATCH 5/5] Handle review comments. --- flang/lib/Optimizer/Transforms/AddDebugInfo.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 0f319ff5518c0..6eb914e67fd54 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -479,8 +479,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, } auto addTargetOpDISP = [&](bool lineTableOnly, - const llvm::SmallVector - &entities) { + llvm::ArrayRef entities) { // When we process the DeclareOp inside the OpenMP target region, all the // variables get the DISubprogram of the parent function of the target op as // the scope. In the codegen (to llvm ir), OpenMP target op results in the @@ -559,7 +558,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, line, line, subprogramFlags, subTypeAttr, /*retainedNodes=*/{}, /*annotations=*/{}); funcOp->setLoc(builder.getFusedLoc({l}, spAttr)); - addTargetOpDISP(true, {}); + addTargetOpDISP(/*lineTableOnly=*/true, /*entities=*/{}); return; } @@ -617,7 +616,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp, funcName, fullName, funcFileAttr, line, line, subprogramFlags, subTypeAttr, entities, /*annotations=*/{}); funcOp->setLoc(builder.getFusedLoc({l}, spAttr)); - addTargetOpDISP(false, entities); + addTargetOpDISP(/*lineTableOnly=*/false, entities); funcOp.walk([&](fir::cg::XDeclareOp declOp) { mlir::LLVM::DISubprogramAttr spTy = spAttr;