[flang-commits] [flang] 87e547d - [Flang] Add/Restore basic debug support (1/n)
Kiran Chandramohan via flang-commits
flang-commits at lists.llvm.org
Thu Jan 12 02:44:13 PST 2023
Author: Kiran Chandramohan
Date: 2023-01-12T10:40:59Z
New Revision: 87e547d8f035c8de321e246629dd2b1ccec31662
URL: https://github.com/llvm/llvm-project/commit/87e547d8f035c8de321e246629dd2b1ccec31662
DIFF: https://github.com/llvm/llvm-project/commit/87e547d8f035c8de321e246629dd2b1ccec31662.diff
LOG: [Flang] Add/Restore basic debug support (1/n)
Recent changes to MLIR meant that Flang does not generate any debug line
table information.
This patch adds a pass that provides some foundation work with which
basic line table debug info can be generated. A walk is performed on
all the `func` ops in the module and they are decorated with a fusedLoc
op that contains the debug metadata for the subroutine along with
location information.
Alternatives include populating this info during lowering or during FIR
to LLVM Dialect conversion.
Note: Patches in future will add
-> more realistic debug info for types and other fields.
-> driver flags to control generation of debug.
Fixes #58634.
Reviewed By: awarzynski, vzakhari
Differential Revision: https://reviews.llvm.org/D137956
Added:
flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp
flang/test/Lower/module-debug-file-loc.f90
flang/test/Transforms/debug-line-table.fir
Modified:
flang/include/flang/Lower/Bridge.h
flang/include/flang/Optimizer/Transforms/Passes.h
flang/include/flang/Optimizer/Transforms/Passes.td
flang/include/flang/Tools/CLOptions.inc
flang/lib/Frontend/FrontendActions.cpp
flang/lib/Lower/Bridge.cpp
flang/lib/Optimizer/Transforms/CMakeLists.txt
flang/tools/bbc/bbc.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Lower/Bridge.h b/flang/include/flang/Lower/Bridge.h
index dabbe72fc3764..38109a37396c4 100644
--- a/flang/include/flang/Lower/Bridge.h
+++ b/flang/include/flang/Lower/Bridge.h
@@ -57,10 +57,11 @@ class LoweringBridge {
const Fortran::parser::AllCookedSources &allCooked,
llvm::StringRef triple, fir::KindMapping &kindMap,
const Fortran::lower::LoweringOptions &loweringOptions,
- const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults) {
+ const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
+ llvm::StringRef filePath) {
return LoweringBridge(ctx, semanticsContext, defaultKinds, intrinsics,
targetCharacteristics, allCooked, triple, kindMap,
- loweringOptions, envDefaults);
+ loweringOptions, envDefaults, filePath);
}
//===--------------------------------------------------------------------===//
@@ -129,7 +130,8 @@ class LoweringBridge {
const Fortran::parser::AllCookedSources &cooked, llvm::StringRef triple,
fir::KindMapping &kindMap,
const Fortran::lower::LoweringOptions &loweringOptions,
- const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults);
+ const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
+ llvm::StringRef filePath);
LoweringBridge() = delete;
LoweringBridge(const LoweringBridge &) = delete;
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h
index 419dbdc4da738..762ea9d90c40e 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.h
+++ b/flang/include/flang/Optimizer/Transforms/Passes.h
@@ -55,6 +55,7 @@ std::unique_ptr<mlir::Pass> createMemDataFlowOptPass();
std::unique_ptr<mlir::Pass> createPromoteToAffinePass();
std::unique_ptr<mlir::Pass> createMemoryAllocationPass();
std::unique_ptr<mlir::Pass> createSimplifyIntrinsicsPass();
+std::unique_ptr<mlir::Pass> createAddDebugFoundationPass();
std::unique_ptr<mlir::Pass>
createMemoryAllocationPass(bool dynOnHeap, std::size_t maxStackSize);
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index 4ed3b823e999c..6aec8b330573c 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -178,6 +178,19 @@ def MemRefDataFlowOpt : Pass<"fir-memref-dataflow-opt", "::mlir::func::FuncOp">
];
}
+// This needs to be a "mlir::ModuleOp" pass, because we are creating debug for
+// the module in this pass.
+def AddDebugFoundation : Pass<"add-debug-foundation", "mlir::ModuleOp"> {
+ let summary = "Add the foundation for debug info";
+ let description = [{
+ Add the foundation for emitting debug info that can be understood by llvm.
+ }];
+ let constructor = "::fir::createAddDebugFoundationPass()";
+ let dependentDialects = [
+ "fir::FIROpsDialect", "mlir::func::FuncDialect", "mlir::LLVM::LLVMDialect"
+ ];
+}
+
// This needs to be a "mlir::ModuleOp" pass, because it inserts simplified
// functions into the module, which is invalid if a finer grain mlir::Operation
// is used as the pass specification says to not touch things outside hte scope
diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc
index 2c772030d33ba..6dad1c2e93605 100644
--- a/flang/include/flang/Tools/CLOptions.inc
+++ b/flang/include/flang/Tools/CLOptions.inc
@@ -65,6 +65,7 @@ DisableOption(
#if !defined(FLANG_EXCLUDE_CODEGEN)
DisableOption(CodeGenRewrite, "codegen-rewrite", "rewrite FIR for codegen");
DisableOption(TargetRewrite, "target-rewrite", "rewrite FIR for target");
+DisableOption(DebugFoundation, "debug-foundation", "Add debug foundation");
DisableOption(FirToLlvmIr, "fir-to-llvmir", "FIR to LLVM-IR dialect");
DisableOption(LlvmIrToLlvm, "llvm", "conversion to LLVM");
DisableOption(BoxedProcedureRewrite, "boxed-procedure-rewrite",
@@ -127,6 +128,11 @@ inline void addTargetRewritePass(mlir::PassManager &pm) {
});
}
+inline void addDebugFoundationPass(mlir::PassManager &pm) {
+ addPassConditionally(pm, disableDebugFoundation,
+ [&]() { return fir::createAddDebugFoundationPass(); });
+}
+
inline void addFIRToLLVMPass(mlir::PassManager &pm) {
fir::FIRToLLVMPassOptions options;
options.ignoreMissingTypeDescriptors = ignoreMissingTypeDescriptors;
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 6c457857ce999..16badc769d90a 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -171,7 +171,8 @@ bool CodeGenAction::beginSourceFileAction() {
ci.getInvocation().getSemanticsContext().targetCharacteristics(),
ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
kindMap, ci.getInvocation().getLoweringOpts(),
- ci.getInvocation().getFrontendOpts().envDefaults);
+ ci.getInvocation().getFrontendOpts().envDefaults,
+ getCurrentFileOrBufferName());
// Fetch module from lb, so we can set
mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule());
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 5bddf958d9b2d..104422c8001e4 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -3792,7 +3792,8 @@ Fortran::lower::LoweringBridge::LoweringBridge(
const Fortran::parser::AllCookedSources &cooked, llvm::StringRef triple,
fir::KindMapping &kindMap,
const Fortran::lower::LoweringOptions &loweringOptions,
- const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults)
+ const std::vector<Fortran::lower::EnvironmentDefault> &envDefaults,
+ llvm::StringRef filePath)
: semanticsContext{semanticsContext}, defaultKinds{defaultKinds},
intrinsics{intrinsics}, targetCharacteristics{targetCharacteristics},
cooked{&cooked}, context{context}, kindMap{kindMap},
@@ -3822,7 +3823,8 @@ Fortran::lower::LoweringBridge::LoweringBridge(
// Create the module and attach the attributes.
module = std::make_unique<mlir::ModuleOp>(
- mlir::ModuleOp::create(mlir::UnknownLoc::get(&context)));
+ mlir::ModuleOp::create(mlir::FileLineColLoc::get(
+ &getMLIRContext(), filePath, /*line=*/0, /*col=*/0)));
assert(module.get() && "module was not created");
fir::setTargetTriple(*module.get(), triple);
fir::setKindMapping(*module.get(), kindMap);
diff --git a/flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp b/flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp
new file mode 100644
index 0000000000000..1d30a8d2889f8
--- /dev/null
+++ b/flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp
@@ -0,0 +1,89 @@
+//===- AddDebugFoundation.cpp -- add basic debug linetable info -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+/// \file
+/// This pass populates some debug information for the module and functions.
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/Dialect/FIRDialect.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/Support/FIRContext.h"
+#include "flang/Optimizer/Transforms/Passes.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/Matchers.h"
+#include "mlir/IR/TypeUtilities.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+#include "mlir/Transforms/RegionUtils.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace fir {
+#define GEN_PASS_DEF_ADDDEBUGFOUNDATION
+#define GEN_PASS_DECL_ADDDEBUGFOUNDATION
+#include "flang/Optimizer/Transforms/Passes.h.inc"
+} // namespace fir
+
+#define DEBUG_TYPE "flang-add-debug-foundation"
+
+namespace {
+
+class AddDebugFoundationPass
+ : public fir::impl::AddDebugFoundationBase<AddDebugFoundationPass> {
+public:
+ void runOnOperation() override;
+};
+
+} // namespace
+
+void AddDebugFoundationPass::runOnOperation() {
+ mlir::ModuleOp module = getOperation();
+ mlir::MLIRContext *context = &getContext();
+ mlir::OpBuilder builder(context);
+ std::string inputFilePath("-");
+ if (auto fileLoc = module.getLoc().dyn_cast<mlir::FileLineColLoc>())
+ inputFilePath = fileLoc.getFilename().getValue();
+
+ mlir::LLVM::DIFileAttr fileAttr = mlir::LLVM::DIFileAttr::get(
+ context, llvm::sys::path::filename(inputFilePath),
+ llvm::sys::path::parent_path(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::StringAttr funcName =
+ mlir::StringAttr::get(context, funcOp.getName());
+ mlir::LLVM::DIBasicTypeAttr bT = mlir::LLVM::DIBasicTypeAttr::get(
+ context, llvm::dwarf::DW_TAG_base_type, "void", /*sizeInBits=*/0,
+ /*encoding=*/1);
+ mlir::LLVM::DISubroutineTypeAttr subTypeAttr =
+ mlir::LLVM::DISubroutineTypeAttr::get(
+ context, llvm::dwarf::getCallingConvention("DW_CC_normal"), bT,
+ {bT});
+ mlir::LLVM::DISubprogramAttr spAttr = mlir::LLVM::DISubprogramAttr::get(
+ context, cuAttr, fileAttr, funcName, funcName, fileAttr, /*line=*/1,
+ /*scopeline=*/1, mlir::LLVM::DISubprogramFlags::Definition,
+ subTypeAttr);
+ funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));
+ });
+}
+
+std::unique_ptr<mlir::Pass> fir::createAddDebugFoundationPass() {
+ return std::make_unique<AddDebugFoundationPass>();
+}
diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt
index 0e8bce8ee56fe..8ec683aac9480 100644
--- a/flang/lib/Optimizer/Transforms/CMakeLists.txt
+++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt
@@ -12,6 +12,7 @@ add_flang_library(FIRTransforms
SimplifyRegionLite.cpp
AlgebraicSimplification.cpp
SimplifyIntrinsics.cpp
+ AddDebugFoundation.cpp
DEPENDS
FIRBuilder
diff --git a/flang/test/Lower/module-debug-file-loc.f90 b/flang/test/Lower/module-debug-file-loc.f90
new file mode 100644
index 0000000000000..69a21d84183dd
--- /dev/null
+++ b/flang/test/Lower/module-debug-file-loc.f90
@@ -0,0 +1,12 @@
+! Test that the module has the location information
+
+! RUN: %flang_fc1 -mmlir --mlir-print-debuginfo -emit-fir -o - %s | FileCheck %s
+
+subroutine sb1()
+end subroutine
+
+! CHECK: module attributes
+! CHECK: func.func @_QPsb1() {
+! CHECK: }
+! CHECK: } loc(#[[MODULE_LOC:.*]])
+! CHECK: #[[MODULE_LOC]] = loc("{{.*}}module-debug-file-loc.f90":0:0)
diff --git a/flang/test/Transforms/debug-line-table.fir b/flang/test/Transforms/debug-line-table.fir
new file mode 100644
index 0000000000000..ff78b4c534270
--- /dev/null
+++ b/flang/test/Transforms/debug-line-table.fir
@@ -0,0 +1,24 @@
+
+// RUN: fir-opt --add-debug-foundation --mlir-print-debuginfo %s | FileCheck %s
+
+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"} {
+ func.func @_QPsb() {
+ return loc(#loc_sb)
+ } loc(#loc_sb)
+} loc(#loc_module)
+#loc_module = loc("./simple.f90":1:1)
+#loc_sb = loc("./simple.f90":2:1)
+
+// CHECK: module attributes
+// CHECK: func.func @[[SB_NAME:.*]]() {
+// CHECK: return loc(#[[SB_LOC:.*]])
+// CHECK: } loc(#[[FUSED_SB_LOC:.*]])
+// CHECK: } loc(#[[MODULE_LOC:.*]])
+// CHECK: #di_basic_type = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "void", encoding = DW_ATE_address>
+// CHECK: #di_file = #llvm.di_file<"[[FILE_NAME:.*]]" in "[[DIR_NAME:.*]]">
+// CHECK: #[[MODULE_LOC]] = loc("[[DIR_NAME]]/[[FILE_NAME]]":1:1)
+// CHECK: #[[SB_LOC]] = loc("./simple.f90":2:1)
+// CHECK: #di_compile_unit = #llvm.di_compile_unit<sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "Flang", isOptimized = false, emissionKind = LineTablesOnly>
+// CHECK: #di_subroutine_type = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, resultType = #di_basic_type, argumentTypes = #di_basic_type>
+// CHECK: #di_subprogram = #llvm.di_subprogram<compileUnit = #di_compile_unit, scope = #di_file, name = "[[SB_NAME]]", linkageName = "[[SB_NAME]]", file = #di_file, line = 1, scopeLine = 1, subprogramFlags = Definition, type = #di_subroutine_type>
+// CHECK: #[[FUSED_SB_LOC]] = loc(fused<#di_subprogram>[#[[SB_LOC]]])
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 796e7faa28807..289c5ad675a3f 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -235,7 +235,7 @@ static mlir::LogicalResult convertFortranSourceToMLIR(
auto burnside = Fortran::lower::LoweringBridge::create(
ctx, semanticsContext, defKinds, semanticsContext.intrinsics(),
semanticsContext.targetCharacteristics(), parsing.allCooked(), "",
- kindMap, loweringOptions, {});
+ kindMap, loweringOptions, {}, inputFilename);
burnside.lower(parseTree, semanticsContext);
mlir::ModuleOp mlirModule = burnside.getModule();
std::error_code ec;
More information about the flang-commits
mailing list