Skip to content

Commit 5f3f9d1

Browse files
authored
[flang] Remove hardcoded bits from AddDebugInfo. (#89231)
This PR adds following options to the AddDebugInfo pass. 1. IsOptimized flag. 2. Level of debug info to generate. 3. Name of the source file This enables us to remove the hard coded values from the code. It also allows us to test the pass with different options. The tests have been modified to take advantage of that. The calling convention flag and producer name have also been improved.
1 parent 5fe93b0 commit 5f3f9d1

File tree

8 files changed

+121
-59
lines changed

8 files changed

+121
-59
lines changed

flang/include/flang/Optimizer/Transforms/Passes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ namespace fir {
4747
#define GEN_PASS_DECL_ALGEBRAICSIMPLIFICATION
4848
#define GEN_PASS_DECL_POLYMORPHICOPCONVERSION
4949
#define GEN_PASS_DECL_OPENACCDATAOPERANDCONVERSION
50+
#define GEN_PASS_DECL_ADDDEBUGINFO
5051
#include "flang/Optimizer/Transforms/Passes.h.inc"
5152

5253
std::unique_ptr<mlir::Pass> createAffineDemotionPass();
@@ -64,7 +65,8 @@ std::unique_ptr<mlir::Pass> createMemoryAllocationPass();
6465
std::unique_ptr<mlir::Pass> createStackArraysPass();
6566
std::unique_ptr<mlir::Pass> createAliasTagsPass();
6667
std::unique_ptr<mlir::Pass> createSimplifyIntrinsicsPass();
67-
std::unique_ptr<mlir::Pass> createAddDebugInfoPass();
68+
std::unique_ptr<mlir::Pass>
69+
createAddDebugInfoPass(fir::AddDebugInfoOptions options = {});
6870
std::unique_ptr<mlir::Pass> createLoopVersioningPass();
6971

7072
std::unique_ptr<mlir::Pass>

flang/include/flang/Optimizer/Transforms/Passes.td

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,25 @@ def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> {
202202
let dependentDialects = [
203203
"fir::FIROpsDialect", "mlir::func::FuncDialect", "mlir::LLVM::LLVMDialect"
204204
];
205+
let options = [
206+
Option<"debugLevel", "debug-level",
207+
"mlir::LLVM::DIEmissionKind",
208+
/*default=*/"mlir::LLVM::DIEmissionKind::Full",
209+
"debug level",
210+
[{::llvm::cl::values(
211+
clEnumValN(mlir::LLVM::DIEmissionKind::Full, "Full", "Emit full debug info"),
212+
clEnumValN(mlir::LLVM::DIEmissionKind::LineTablesOnly, "LineTablesOnly", "Emit line tables only"),
213+
clEnumValN(mlir::LLVM::DIEmissionKind::None, "None", "Emit no debug information")
214+
)}]
215+
>,
216+
Option<"isOptimized", "is-optimized",
217+
"bool", /*default=*/"false",
218+
"is optimized.">,
219+
Option<"inputFilename", "file-name",
220+
"std::string",
221+
/*default=*/"std::string{}",
222+
"name of the input source file">,
223+
];
205224
}
206225

207226
// This needs to be a "mlir::ModuleOp" pass, because it inserts simplified

flang/include/flang/Tools/CLOptions.inc

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,27 @@ inline void addTargetRewritePass(mlir::PassManager &pm) {
179179
});
180180
}
181181

182-
inline void addDebugInfoPass(mlir::PassManager &pm) {
183-
addPassConditionally(
184-
pm, disableDebugInfo, [&]() { return fir::createAddDebugInfoPass(); });
182+
inline mlir::LLVM::DIEmissionKind getEmissionKind(
183+
llvm::codegenoptions::DebugInfoKind kind) {
184+
switch (kind) {
185+
case llvm::codegenoptions::DebugInfoKind::FullDebugInfo:
186+
return mlir::LLVM::DIEmissionKind::Full;
187+
case llvm::codegenoptions::DebugInfoKind::DebugLineTablesOnly:
188+
return mlir::LLVM::DIEmissionKind::LineTablesOnly;
189+
default:
190+
return mlir::LLVM::DIEmissionKind::None;
191+
}
192+
}
193+
194+
inline void addDebugInfoPass(mlir::PassManager &pm,
195+
llvm::codegenoptions::DebugInfoKind debugLevel,
196+
llvm::OptimizationLevel optLevel, llvm::StringRef inputFilename) {
197+
fir::AddDebugInfoOptions options;
198+
options.debugLevel = getEmissionKind(debugLevel);
199+
options.isOptimized = optLevel != llvm::OptimizationLevel::O0;
200+
options.inputFilename = inputFilename;
201+
addPassConditionally(pm, disableDebugInfo,
202+
[&]() { return fir::createAddDebugInfoPass(options); });
185203
}
186204

187205
inline void addFIRToLLVMPass(
@@ -307,32 +325,21 @@ inline void createOpenMPFIRPassPipeline(
307325
}
308326

309327
#if !defined(FLANG_EXCLUDE_CODEGEN)
310-
inline void createDebugPasses(
311-
mlir::PassManager &pm, llvm::codegenoptions::DebugInfoKind debugLevel) {
312-
// Currently only -g1, -g, -gline-tables-only supported
313-
switch (debugLevel) {
314-
case llvm::codegenoptions::DebugLineTablesOnly:
315-
addDebugInfoPass(pm);
316-
return;
317-
case llvm::codegenoptions::NoDebugInfo:
318-
return;
319-
default:
320-
// TODO: Add cases and passes for other debug options.
321-
// All other debug options not implemented yet, currently emits warning
322-
// and generates as much debug information as possible.
323-
addDebugInfoPass(pm);
324-
return;
325-
}
328+
inline void createDebugPasses(mlir::PassManager &pm,
329+
llvm::codegenoptions::DebugInfoKind debugLevel,
330+
llvm::OptimizationLevel OptLevel, llvm::StringRef inputFilename) {
331+
if (debugLevel != llvm::codegenoptions::NoDebugInfo)
332+
addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename);
326333
}
327334

328-
inline void createDefaultFIRCodeGenPassPipeline(
329-
mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config) {
335+
inline void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
336+
MLIRToLLVMPassPipelineConfig config, llvm::StringRef inputFilename = {}) {
330337
fir::addBoxedProcedurePass(pm);
331338
addNestedPassToAllTopLevelOperations(pm, fir::createAbstractResultOpt);
332339
fir::addCodeGenRewritePass(pm);
333340
fir::addTargetRewritePass(pm);
334341
fir::addExternalNameConversionPass(pm, config.Underscoring);
335-
fir::createDebugPasses(pm, config.DebugInfo);
342+
fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename);
336343

337344
if (config.VScaleMin != 0)
338345
pm.addPass(fir::createVScaleAttrPass({config.VScaleMin, config.VScaleMax}));
@@ -366,15 +373,16 @@ inline void createDefaultFIRCodeGenPassPipeline(
366373
/// \param pm - MLIR pass manager that will hold the pipeline definition
367374
/// \param optLevel - optimization level used for creating FIR optimization
368375
/// passes pipeline
369-
inline void createMLIRToLLVMPassPipeline(
370-
mlir::PassManager &pm, const MLIRToLLVMPassPipelineConfig &config) {
376+
inline void createMLIRToLLVMPassPipeline(mlir::PassManager &pm,
377+
const MLIRToLLVMPassPipelineConfig &config,
378+
llvm::StringRef inputFilename = {}) {
371379
fir::createHLFIRToFIRPassPipeline(pm, config.OptLevel);
372380

373381
// Add default optimizer pass pipeline.
374382
fir::createDefaultFIROptimizerPassPipeline(pm, config);
375383

376384
// Add codegen pass pipeline.
377-
fir::createDefaultFIRCodeGenPassPipeline(pm, config);
385+
fir::createDefaultFIRCodeGenPassPipeline(pm, config, inputFilename);
378386
}
379387
#undef FLANG_EXCLUDE_CODEGEN
380388
#endif

flang/lib/Frontend/FrontendActions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ void CodeGenAction::generateLLVMIR() {
809809
}
810810

811811
// Create the pass pipeline
812-
fir::createMLIRToLLVMPassPipeline(pm, config);
812+
fir::createMLIRToLLVMPassPipeline(pm, config, getCurrentFile());
813813
(void)mlir::applyPassManagerCLOptions(pm);
814814

815815
// run the pass manager

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
/// This pass populates some debug information for the module and functions.
1212
//===----------------------------------------------------------------------===//
1313

14+
#include "flang/Common/Version.h"
1415
#include "flang/Optimizer/Builder/FIRBuilder.h"
1516
#include "flang/Optimizer/Builder/Todo.h"
1617
#include "flang/Optimizer/Dialect/FIRDialect.h"
1718
#include "flang/Optimizer/Dialect/FIROps.h"
1819
#include "flang/Optimizer/Dialect/FIRType.h"
1920
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
21+
#include "flang/Optimizer/Support/InternalNames.h"
2022
#include "flang/Optimizer/Transforms/Passes.h"
2123
#include "mlir/Dialect/Func/IR/FuncOps.h"
2224
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
@@ -28,12 +30,12 @@
2830
#include "mlir/Transforms/RegionUtils.h"
2931
#include "llvm/BinaryFormat/Dwarf.h"
3032
#include "llvm/Support/Debug.h"
33+
#include "llvm/Support/FileSystem.h"
3134
#include "llvm/Support/Path.h"
3235
#include "llvm/Support/raw_ostream.h"
3336

3437
namespace fir {
3538
#define GEN_PASS_DEF_ADDDEBUGINFO
36-
#define GEN_PASS_DECL_ADDDEBUGINFO
3739
#include "flang/Optimizer/Transforms/Passes.h.inc"
3840
} // namespace fir
3941

@@ -43,6 +45,7 @@ namespace {
4345

4446
class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {
4547
public:
48+
AddDebugInfoPass(fir::AddDebugInfoOptions options) : Base(options) {}
4649
void runOnOperation() override;
4750
};
4851

@@ -52,21 +55,40 @@ void AddDebugInfoPass::runOnOperation() {
5255
mlir::ModuleOp module = getOperation();
5356
mlir::MLIRContext *context = &getContext();
5457
mlir::OpBuilder builder(context);
55-
std::string inputFilePath("-");
56-
if (auto fileLoc = module.getLoc().dyn_cast<mlir::FileLineColLoc>())
57-
inputFilePath = fileLoc.getFilename().getValue();
58+
llvm::StringRef fileName;
59+
std::string filePath;
60+
// We need 2 type of file paths here.
61+
// 1. Name of the file as was presented to compiler. This can be absolute
62+
// or relative to 2.
63+
// 2. Current working directory
64+
//
65+
// We are also dealing with 2 different situations below. One is normal
66+
// compilation where we will have a value in 'inputFilename' and we can
67+
// obtain the current directory using 'current_path'.
68+
// The 2nd case is when this pass is invoked directly from 'fir-opt' tool.
69+
// In that case, 'inputFilename' may be empty. Location embedded in the
70+
// module will be used to get file name and its directory.
71+
if (inputFilename.empty()) {
72+
if (auto fileLoc = module.getLoc().dyn_cast<mlir::FileLineColLoc>()) {
73+
fileName = llvm::sys::path::filename(fileLoc.getFilename().getValue());
74+
filePath = llvm::sys::path::parent_path(fileLoc.getFilename().getValue());
75+
} else
76+
fileName = "-";
77+
} else {
78+
fileName = inputFilename;
79+
llvm::SmallString<256> cwd;
80+
if (!llvm::sys::fs::current_path(cwd))
81+
filePath = cwd.str();
82+
}
5883

59-
auto getFileAttr = [context](llvm::StringRef path) -> mlir::LLVM::DIFileAttr {
60-
return mlir::LLVM::DIFileAttr::get(context, llvm::sys::path::filename(path),
61-
llvm::sys::path::parent_path(path));
62-
};
63-
64-
mlir::LLVM::DIFileAttr fileAttr = getFileAttr(inputFilePath);
65-
mlir::StringAttr producer = mlir::StringAttr::get(context, "Flang");
84+
mlir::LLVM::DIFileAttr fileAttr =
85+
mlir::LLVM::DIFileAttr::get(context, fileName, filePath);
86+
mlir::StringAttr producer =
87+
mlir::StringAttr::get(context, Fortran::common::getFlangFullVersion());
6688
mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get(
6789
mlir::DistinctAttr::create(mlir::UnitAttr::get(context)),
6890
llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer,
69-
/*isOptimized=*/false, mlir::LLVM::DIEmissionKind::LineTablesOnly);
91+
isOptimized, debugLevel);
7092

7193
module.walk([&](mlir::func::FuncOp funcOp) {
7294
mlir::Location l = funcOp->getLoc();
@@ -75,43 +97,49 @@ void AddDebugInfoPass::runOnOperation() {
7597
if (l.dyn_cast<mlir::FusedLoc>())
7698
return;
7799

78-
llvm::StringRef funcFilePath;
79-
if (l.dyn_cast<mlir::FileLineColLoc>())
80-
funcFilePath =
81-
l.dyn_cast<mlir::FileLineColLoc>().getFilename().getValue();
82-
else
83-
funcFilePath = inputFilePath;
100+
unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry())
101+
? llvm::dwarf::getCallingConvention("DW_CC_program")
102+
: llvm::dwarf::getCallingConvention("DW_CC_normal");
103+
104+
if (auto funcLoc = l.dyn_cast<mlir::FileLineColLoc>()) {
105+
fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue());
106+
filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue());
107+
}
84108

85109
mlir::StringAttr funcName =
86110
mlir::StringAttr::get(context, funcOp.getName());
87111
mlir::LLVM::DIBasicTypeAttr bT = mlir::LLVM::DIBasicTypeAttr::get(
88112
context, llvm::dwarf::DW_TAG_base_type, "void", /*sizeInBits=*/0,
89113
/*encoding=*/1);
114+
// FIXME: Provide proper type for subroutine
90115
mlir::LLVM::DISubroutineTypeAttr subTypeAttr =
91-
mlir::LLVM::DISubroutineTypeAttr::get(
92-
context, llvm::dwarf::getCallingConvention("DW_CC_normal"),
93-
{bT, bT});
94-
mlir::LLVM::DIFileAttr funcFileAttr = getFileAttr(funcFilePath);
116+
mlir::LLVM::DISubroutineTypeAttr::get(context, CC, {bT, bT});
117+
mlir::LLVM::DIFileAttr funcFileAttr =
118+
mlir::LLVM::DIFileAttr::get(context, fileName, filePath);
95119

96120
// Only definitions need a distinct identifier and a compilation unit.
97121
mlir::DistinctAttr id;
98122
mlir::LLVM::DICompileUnitAttr compilationUnit;
99-
auto subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized;
123+
mlir::LLVM::DISubprogramFlags subprogramFlags =
124+
mlir::LLVM::DISubprogramFlags{};
125+
if (isOptimized)
126+
subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized;
100127
if (!funcOp.isExternal()) {
101128
id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context));
102129
compilationUnit = cuAttr;
103130
subprogramFlags =
104131
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
105132
}
133+
// FIXME: Provide proper line and scopeline.
106134
auto spAttr = mlir::LLVM::DISubprogramAttr::get(
107135
context, id, compilationUnit, fileAttr, funcName, funcName,
108-
funcFileAttr,
109-
/*line=*/1,
110-
/*scopeline=*/1, subprogramFlags, subTypeAttr);
136+
funcFileAttr, /*line=*/1, /*scopeline=*/1, subprogramFlags,
137+
subTypeAttr);
111138
funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));
112139
});
113140
}
114141

115-
std::unique_ptr<mlir::Pass> fir::createAddDebugInfoPass() {
116-
return std::make_unique<AddDebugInfoPass>();
142+
std::unique_ptr<mlir::Pass>
143+
fir::createAddDebugInfoPass(fir::AddDebugInfoOptions options) {
144+
return std::make_unique<AddDebugInfoPass>(options);
117145
}

flang/lib/Optimizer/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ add_flang_library(FIRTransforms
3535
FIRDialect
3636
FIRDialectSupport
3737
FIRSupport
38+
FortranCommon
3839
HLFIRDialect
3940
MLIRAffineUtils
4041
MLIRFuncDialect

flang/test/Transforms/debug-line-table-inc-file.fir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s
2+
// RUN: fir-opt --add-debug-info="debug-level=LineTablesOnly" --mlir-print-debuginfo %s | FileCheck %s
33
// REQUIRES: system-linux
44

55
// Test for included functions that have a different debug location than the current file
@@ -30,7 +30,7 @@ module attributes {} {
3030
// CHECK: #[[MODULE_LOC]] = loc("{{.*}}simple.f90":0:0)
3131
// CHECK: #[[LOC_INC_FILE:.*]] = loc("{{.*}}inc.f90":1:1)
3232
// CHECK: #[[LOC_FILE:.*]] = loc("{{.*}}simple.f90":3:1)
33-
// CHECK: #[[DI_CU:.*]] = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #[[DI_FILE]], producer = "Flang", isOptimized = false, emissionKind = LineTablesOnly>
33+
// CHECK: #[[DI_CU:.*]] = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #[[DI_FILE]], producer = "flang{{.*}}", isOptimized = false, emissionKind = LineTablesOnly>
3434
// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QPsinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}>
3535
// CHECK: #[[DI_SP:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QQmain", linkageName = "_QQmain", file = #[[DI_FILE]], {{.*}}>
3636
// CHECK: #[[FUSED_LOC_INC_FILE]] = loc(fused<#[[DI_SP_INC]]>[#[[LOC_INC_FILE]]])

flang/test/Transforms/debug-line-table.fir

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

2-
// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s
2+
// RUN: fir-opt --add-debug-info="debug-level=Full" --mlir-print-debuginfo %s | FileCheck %s --check-prefix=FULL
3+
// RUN: fir-opt --add-debug-info="debug-level=LineTablesOnly" --mlir-print-debuginfo %s | FileCheck %s --check-prefix=LINETABLE
4+
// RUN: fir-opt --add-debug-info="is-optimized=true" --mlir-print-debuginfo %s | FileCheck %s --check-prefix=OPT
35

46
module attributes { fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", llvm.target_triple = "aarch64-unknown-linux-gnu"} {
57
func.func @_QPsb() {
@@ -22,7 +24,9 @@ module attributes { fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.dat
2224
// CHECK: #[[MODULE_LOC]] = loc("[[DIR_NAME]]/[[FILE_NAME]]":1:1)
2325
// CHECK: #[[SB_LOC]] = loc("./simple.f90":2:1)
2426
// CHECK: #[[DECL_LOC:.*]] = loc("./simple.f90":10:1)
25-
// CHECK: #di_compile_unit = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "Flang", isOptimized = false, emissionKind = LineTablesOnly>
27+
// FULL: #di_compile_unit = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang{{.*}}", isOptimized = false, emissionKind = Full>
28+
// OPT: #di_compile_unit = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang{{.*}}", isOptimized = true, emissionKind = Full>
29+
// LINETABLE: #di_compile_unit = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "flang{{.*}}", isOptimized = false, emissionKind = LineTablesOnly>
2630
// CHECK: #di_subroutine_type = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #di_basic_type, #di_basic_type>
2731
// CHECK: #[[SB_SUBPROGRAM:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #di_compile_unit, scope = #di_file, name = "[[SB_NAME]]", linkageName = "[[SB_NAME]]", file = #di_file, line = 1, scopeLine = 1, subprogramFlags = "Definition|Optimized", type = #di_subroutine_type>
2832
// CHECK: #[[DECL_SUBPROGRAM:.*]] = #llvm.di_subprogram<scope = #di_file, name = "[[DECL_NAME]]", linkageName = "[[DECL_NAME]]", file = #di_file, line = 1, scopeLine = 1, subprogramFlags = Optimized, type = #di_subroutine_type>

0 commit comments

Comments
 (0)