diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -708,7 +708,10 @@ loc = cooked->GetSourcePositionRange(block)) { // loc is a pair (begin, end); use the beginning position Fortran::parser::SourcePosition &filePos = loc->first; - return mlir::FileLineColLoc::get(&getMLIRContext(), filePos.file.path(), + llvm::SmallString<256> filePath(filePos.file.path()); + llvm::sys::fs::make_absolute(filePath); + llvm::sys::path::remove_dots(filePath); + return mlir::FileLineColLoc::get(&getMLIRContext(), filePath.str(), filePos.line, filePos.column); } } diff --git a/flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp b/flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp --- a/flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp @@ -26,6 +26,7 @@ #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" #include "mlir/Transforms/RegionUtils.h" +#include "llvm/ADT/StringMap.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Path.h" @@ -57,15 +58,41 @@ if (auto fileLoc = module.getLoc().dyn_cast()) inputFilePath = fileLoc.getFilename().getValue(); - mlir::LLVM::DIFileAttr fileAttr = mlir::LLVM::DIFileAttr::get( - context, llvm::sys::path::filename(inputFilePath), - llvm::sys::path::parent_path(inputFilePath)); + llvm::StringMap fileAttrs; + auto getFileAttr = + [context, &fileAttrs](llvm::StringRef path) -> mlir::LLVM::DIFileAttr { + if (fileAttrs.count(path) == 0) { + mlir::LLVM::DIFileAttr attr = + mlir::LLVM::DIFileAttr::get(context, llvm::sys::path::filename(path), + llvm::sys::path::parent_path(path)); + fileAttrs.insert({path, attr}); + return attr; + } + + return fileAttrs[path]; + }; + + mlir::LLVM::DIFileAttr fileAttr = getFileAttr(inputFilePath); mlir::StringAttr producer = mlir::StringAttr::get(context, "Flang"); mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get( context, llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer, /*isOptimized=*/false, mlir::LLVM::DIEmissionKind::LineTablesOnly); + 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 (l.dyn_cast()) + return; + + llvm::StringRef funcFilePath; + if (l.dyn_cast()) + funcFilePath = + l.dyn_cast().getFilename().getValue(); + else + funcFilePath = inputFilePath; + mlir::StringAttr funcName = mlir::StringAttr::get(context, funcOp.getName()); mlir::LLVM::DIBasicTypeAttr bT = mlir::LLVM::DIBasicTypeAttr::get( @@ -75,8 +102,9 @@ mlir::LLVM::DISubroutineTypeAttr::get( context, llvm::dwarf::getCallingConvention("DW_CC_normal"), {bT, bT}); + mlir::LLVM::DIFileAttr funcFileAttr = getFileAttr(funcFilePath); mlir::LLVM::DISubprogramAttr spAttr = mlir::LLVM::DISubprogramAttr::get( - context, cuAttr, fileAttr, funcName, funcName, fileAttr, /*line=*/1, + context, cuAttr, fileAttr, funcName, funcName, funcFileAttr, /*line=*/1, /*scopeline=*/1, mlir::LLVM::DISubprogramFlags::Definition, subTypeAttr); funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); diff --git a/flang/test/Transforms/debug-line-table-existing.fir b/flang/test/Transforms/debug-line-table-existing.fir new file mode 100644 --- /dev/null +++ b/flang/test/Transforms/debug-line-table-existing.fir @@ -0,0 +1,28 @@ + +// RUN: fir-opt --add-debug-foundation --mlir-print-debuginfo %s | FileCheck %s +// REQUIRES: linux + +// Test that there are no changes to a function with existed fused loc debug +module { + func.func @_QPs1() { + return loc(#loc1) + } loc(#loc2) +} loc(#loc) +#di_basic_type = #llvm.di_basic_type +#di_file = #llvm.di_file<"simple.f90" in "/home/user01/llvm-project/build_release"> +#loc = loc("/home/user01/llvm-project/build_release/simple.f90":0:0) +#loc1 = loc("/home/user01/llvm-project/build_release/simple.f90":1:1) +#di_compile_unit = #llvm.di_compile_unit +#di_subroutine_type = #llvm.di_subroutine_type +#di_subprogram = #llvm.di_subprogram +#loc2 = loc(fused<#di_subprogram>[#loc1]) + +module { + func.func @_QPs1() { + return loc(#loc1) + } loc(#loc2) +} loc(#loc) +// CHECK: #loc = loc("/home/user01/llvm-project/build_release/simple.f90":0:0) +// CHECK: #loc1 = loc("/home/user01/llvm-project/build_release/simple.f90":1:1) +// CHECK: #di_subprogram = #llvm.di_subprogram +// CHECK: #loc2 = loc(fused<#di_subprogram>[#loc1]) diff --git a/flang/test/Transforms/debug-line-table-inc-file.fir b/flang/test/Transforms/debug-line-table-inc-file.fir new file mode 100644 --- /dev/null +++ b/flang/test/Transforms/debug-line-table-inc-file.fir @@ -0,0 +1,37 @@ + +// RUN: fir-opt --add-debug-foundation --mlir-print-debuginfo %s | FileCheck %s +// REQUIRES: linux + +// Test for included functions that have a different debug location than the current file +module attributes {} { + func.func @_QPsinc() { + return loc(#loc2) + } loc(#loc1) + func.func @_QQmain() { + fir.call @_QPsinc() fastmath : () -> () loc(#loc4) + return loc(#loc5) + } loc(#loc3) +} loc(#loc) +#loc = loc("/home/user01/llvm-project/build_release/simple.f90":0:0) +#loc1 = loc("/home/user01/llvm-project/build_release/inc.f90":1:1) +#loc2 = loc("/home/user01/llvm-project/build_release/inc.f90":2:1) +#loc3 = loc("/home/user01/llvm-project/build_release/simple.f90":3:1) +#loc4 = loc("/home/user01/llvm-project/build_release/simple.f90":4:3) +#loc5 = loc("/home/user01/llvm-project/build_release/simple.f90":5:1) + +// CHECK: module { +// CHECK: func.func @_QPsinc() { +// CHECK: } loc(#[[FUSED_LOC_INC_FILE:.*]]) +// CHECK: func.func @_QQmain() { +// CHECK: } loc(#[[FUSED_LOC_FILE:.*]]) +// CHECK: } loc(#[[MODULE_LOC:.*]]) +// CHECK: #[[DI_FILE:.*]] = #llvm.di_file<"[[FILE:.*]]" in "[[DIR:.*]]"> +// CHECK: #[[DI_INC_FILE:.*]] = #llvm.di_file<"[[INC_FILE:.*]]" in "[[DIR]]"> +// CHECK: #[[MODULE_LOC]] = loc("{{.*}}[[FILE]]":0:0) +// CHECK: #[[LOC_INC_FILE:.*]] = loc("{{.*}}[[INC_FILE]]":1:1) +// CHECK: #[[LOC_FILE:.*]] = loc("{{.*}}[[FILE]]":3:1) +// CHECK: #[[DI_CU:.*]] = #llvm.di_compile_unit +// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram +// CHECK: #[[DI_SP:.*]] = #llvm.di_subprogram +// CHECK: #[[FUSED_LOC_INC_FILE]] = loc(fused<#[[DI_SP_INC]]>[#[[LOC_INC_FILE]]]) +// CHECK: #[[FUSED_LOC_FILE]] = loc(fused<#[[DI_SP]]>[#[[LOC_FILE]]]) diff --git a/flang/test/Transforms/debug-line-table-inc-same-file.fir b/flang/test/Transforms/debug-line-table-inc-same-file.fir new file mode 100644 --- /dev/null +++ b/flang/test/Transforms/debug-line-table-inc-same-file.fir @@ -0,0 +1,23 @@ + +// RUN: fir-opt --add-debug-foundation --mlir-print-debuginfo %s | FileCheck %s +// REQUIRES: linux + +// Test that there is only one FileAttribute generated for multiple functions +// in the same file. +module attributes {} { + func.func @_QPs1() { + return loc(#loc2) + } loc(#loc1) + func.func @_QPs2() { + return loc(#loc2) + } loc(#loc1) + func.func @_QQmain() { + return loc(#loc3) + } loc(#loc1) +} loc(#loc) +#loc = loc("/home/user01/llvm-project/build_release/simple.f90":0:0) +#loc1 = loc("/home/user01/llvm-project/build_release/simple.f90":1:1) +#loc2 = loc("/home/user01/llvm-project/build_release/simple.f90":2:1) +#loc3 = loc("/home/user01/llvm-project/build_release/simple.f90":3:1) + +// CHECK-COUNT-1: #llvm.di_file