[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