[flang-commits] [flang] [flang] Lowering support for -gdwarf-N flag. (PR #159137)

via flang-commits flang-commits at lists.llvm.org
Tue Sep 16 10:31:10 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-driver

Author: Abid Qadeer (abidh)

<details>
<summary>Changes</summary>

This PR builds on the https://github.com/llvm/llvm-project/pull/158314 and adds the lowering support for `-gdwarf-N` flag. The changes to pass the information to `AddDebugInfo` pass are mostly mechanical. The `AddDebugInfo` pass adds `ModuleFlagsOp` in the module which gets translated to correct llvm metadata during mlir->llvmir translation.

There is minor correction where the version is set to 0 in case no -debug-version flag is provided. Previously it was set to 2 in this case due to misreading of clang code.

---
Full diff: https://github.com/llvm/llvm-project/pull/159137.diff


8 Files Affected:

- (modified) flang/include/flang/Optimizer/Passes/Pipelines.h (+2-2) 
- (modified) flang/include/flang/Optimizer/Transforms/Passes.td (+4) 
- (modified) flang/include/flang/Tools/CrossToolHelpers.h (+2) 
- (modified) flang/lib/Frontend/CompilerInvocation.cpp (+1-2) 
- (modified) flang/lib/Optimizer/Passes/Pipelines.cpp (+6-4) 
- (modified) flang/lib/Optimizer/Transforms/AddDebugInfo.cpp (+13-1) 
- (added) flang/test/Integration/debug-dwarf-flags.f90 (+24) 
- (added) flang/test/Transforms/debug-dwarf-version.fir (+22) 


``````````diff
diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h b/flang/include/flang/Optimizer/Passes/Pipelines.h
index fd8c43cc88a19..f9c41b382abe5 100644
--- a/flang/include/flang/Optimizer/Passes/Pipelines.h
+++ b/flang/include/flang/Optimizer/Passes/Pipelines.h
@@ -102,7 +102,7 @@ void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm);
 void addDebugInfoPass(mlir::PassManager &pm,
                       llvm::codegenoptions::DebugInfoKind debugLevel,
                       llvm::OptimizationLevel optLevel,
-                      llvm::StringRef inputFilename);
+                      llvm::StringRef inputFilename, int32_t dwarfVersion);
 
 void addFIRToLLVMPass(mlir::PassManager &pm,
                       const MLIRToLLVMPassPipelineConfig &config);
@@ -158,7 +158,7 @@ void createOpenMPFIRPassPipeline(mlir::PassManager &pm,
 void createDebugPasses(mlir::PassManager &pm,
                        llvm::codegenoptions::DebugInfoKind debugLevel,
                        llvm::OptimizationLevel OptLevel,
-                       llvm::StringRef inputFilename);
+                       llvm::StringRef inputFilename, int32_t dwarfVersion);
 
 void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
                                          MLIRToLLVMPassPipelineConfig config,
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index e3001454cdf19..b7fa0ca5f5719 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -242,6 +242,10 @@ def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> {
            "std::string",
            /*default=*/"std::string{}",
            "name of the input source file">,
+    Option<"dwarfVersion", "dwarf-version",
+           "int32_t",
+           /*default=*/"0",
+           "dwarf version">,
   ];
 }
 
diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h
index 335f0a45531c8..038f388f2ec0b 100644
--- a/flang/include/flang/Tools/CrossToolHelpers.h
+++ b/flang/include/flang/Tools/CrossToolHelpers.h
@@ -108,6 +108,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
       InstrumentFunctionEntry = "__cyg_profile_func_enter";
       InstrumentFunctionExit = "__cyg_profile_func_exit";
     }
+    DwarfVersion = opts.DwarfVersion;
   }
 
   llvm::OptimizationLevel OptLevel; ///< optimisation level
@@ -143,6 +144,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
   Fortran::frontend::CodeGenOptions::ComplexRangeKind ComplexRange =
       Fortran::frontend::CodeGenOptions::ComplexRangeKind::
           CX_Full; ///< Method for calculating complex number division
+  int32_t DwarfVersion = 0; ///< Version of DWARF debug info to generate
 };
 
 struct OffloadModuleOpts {
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index a00e568bb4a54..4729f8a7611a2 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -157,10 +157,9 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
           clang::DiagnosticsEngine::Warning, "Unsupported debug option: %0");
       diags.Report(debugWarning) << arg->getValue();
     }
-    // The default value of 2 here is to match clang.
     opts.DwarfVersion =
         getLastArgIntValue(args, clang::driver::options::OPT_dwarf_version_EQ,
-                           /*Default=*/2, diags);
+                           /*Default=*/0, diags);
   }
   return true;
 }
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 7c2777baebef1..58f60d43b1d49 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -95,11 +95,12 @@ getEmissionKind(llvm::codegenoptions::DebugInfoKind kind) {
 void addDebugInfoPass(mlir::PassManager &pm,
                       llvm::codegenoptions::DebugInfoKind debugLevel,
                       llvm::OptimizationLevel optLevel,
-                      llvm::StringRef inputFilename) {
+                      llvm::StringRef inputFilename, int32_t dwarfVersion) {
   fir::AddDebugInfoOptions options;
   options.debugLevel = getEmissionKind(debugLevel);
   options.isOptimized = optLevel != llvm::OptimizationLevel::O0;
   options.inputFilename = inputFilename;
+  options.dwarfVersion = dwarfVersion;
   addPassConditionally(pm, disableDebugInfo,
                        [&]() { return fir::createAddDebugInfoPass(options); });
 }
@@ -333,9 +334,9 @@ void createOpenMPFIRPassPipeline(mlir::PassManager &pm,
 void createDebugPasses(mlir::PassManager &pm,
                        llvm::codegenoptions::DebugInfoKind debugLevel,
                        llvm::OptimizationLevel OptLevel,
-                       llvm::StringRef inputFilename) {
+                       llvm::StringRef inputFilename, int32_t dwarfVersion) {
   if (debugLevel != llvm::codegenoptions::NoDebugInfo)
-    addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename);
+    addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename, dwarfVersion);
 }
 
 void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
@@ -352,7 +353,8 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
   fir::addCodeGenRewritePass(
       pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo));
   fir::addExternalNameConversionPass(pm, config.Underscoring);
-  fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename);
+  fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename,
+                         config.DwarfVersion);
   fir::addTargetRewritePass(pm);
   fir::addCompilerGeneratedNamesConversionPass(pm);
 
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 6eb914e67fd54..af96c0be6fae9 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -649,6 +649,19 @@ void AddDebugInfoPass::runOnOperation() {
     signalPassFailure();
     return;
   }
+  mlir::OpBuilder builder(context);
+  if (dwarfVersion > 0) {
+    mlir::OpBuilder::InsertionGuard guard(builder);
+    builder.setInsertionPointToEnd(module.getBody());
+    llvm::SmallVector<mlir::Attribute> moduleFlags;
+    mlir::IntegerType int32Ty = mlir::IntegerType::get(context, 32);
+    moduleFlags.push_back(builder.getAttr<mlir::LLVM::ModuleFlagAttr>(
+        mlir::LLVM::ModFlagBehavior::Max,
+        mlir::StringAttr::get(context, "Dwarf Version"),
+        mlir::IntegerAttr::get(int32Ty, dwarfVersion)));
+    mlir::LLVM::ModuleFlagsOp::create(builder, module.getLoc(),
+                                      builder.getArrayAttr(moduleFlags));
+  }
   fir::DebugTypeGenerator typeGen(module, &symbolTable, *dl);
   // We need 2 type of file paths here.
   // 1. Name of the file as was presented to compiler. This can be absolute
@@ -686,7 +699,6 @@ void AddDebugInfoPass::runOnOperation() {
   module.walk([&](mlir::func::FuncOp funcOp) {
     handleFuncOp(funcOp, fileAttr, cuAttr, typeGen, &symbolTable);
   });
-  mlir::OpBuilder builder(context);
   // We have processed all function. Attach common block variables to the
   // global that represent the storage.
   for (auto [global, exprs] : globalToGlobalExprsMap) {
diff --git a/flang/test/Integration/debug-dwarf-flags.f90 b/flang/test/Integration/debug-dwarf-flags.f90
new file mode 100644
index 0000000000000..8dae74ecb07cd
--- /dev/null
+++ b/flang/test/Integration/debug-dwarf-flags.f90
@@ -0,0 +1,24 @@
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone -dwarf-version=5 %s  \
+! RUN:         -o - | FileCheck --check-prefix=CHECK-DWARF5 %s
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=line-tables-only -dwarf-version=5 \
+! RUN:         %s -o - | FileCheck --check-prefix=CHECK-DWARF5 %s
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone -dwarf-version=4 %s  \
+! RUN:         -o - | FileCheck --check-prefix=CHECK-DWARF4 %s
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone -dwarf-version=3 %s  \
+! RUN:         -o - | FileCheck --check-prefix=CHECK-DWARF3 %s
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone -dwarf-version=2 %s  \
+! RUN:         -o - | FileCheck --check-prefix=CHECK-DWARF2 %s
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s  -o -\
+! RUN:         | FileCheck --check-prefix=CHECK-WITHOUT-VERSION %s
+! RUN: %flang_fc1 -emit-llvm -dwarf-version=5 %s  -o - \
+! RUN:         | FileCheck --check-prefix=CHECK-WITHOUT-DEBUG-KIND %s
+
+program test
+end program test
+
+! CHECK-DWARF5: !{i32 7, !"Dwarf Version", i32 5}
+! CHECK-DWARF4: !{i32 7, !"Dwarf Version", i32 4}
+! CHECK-DWARF3: !{i32 7, !"Dwarf Version", i32 3}
+! CHECK-DWARF2: !{i32 7, !"Dwarf Version", i32 2}
+! CHECK-WITHOUT-VERSION-NOT: "Dwarf Version"
+! CHECK-WITHOUT-DEBUG-KIND-NOT: "Dwarf Version"
diff --git a/flang/test/Transforms/debug-dwarf-version.fir b/flang/test/Transforms/debug-dwarf-version.fir
new file mode 100644
index 0000000000000..d536b8dddbbd6
--- /dev/null
+++ b/flang/test/Transforms/debug-dwarf-version.fir
@@ -0,0 +1,22 @@
+
+// RUN: fir-opt --add-debug-info="dwarf-version=5" --mlir-print-debuginfo %s \
+// RUN:         | FileCheck --check-prefix=CHECK-DWARF5 %s
+// RUN: fir-opt --add-debug-info="dwarf-version=4" --mlir-print-debuginfo %s \
+// RUN:         | FileCheck --check-prefix=CHECK-DWARF4 %s
+// RUN: fir-opt --add-debug-info="dwarf-version=3" --mlir-print-debuginfo %s \
+// RUN:         | FileCheck --check-prefix=CHECK-DWARF3 %s
+// RUN: fir-opt --add-debug-info="dwarf-version=2" --mlir-print-debuginfo %s \
+// RUN:         | FileCheck --check-prefix=CHECK-DWARF2 %s
+// RUN: fir-opt --add-debug-info= --mlir-print-debuginfo %s \
+// RUN:         | FileCheck --check-prefix=CHECK-WITHOUT-VERSION %s
+// REQUIRES: system-linux
+
+module {
+} loc(#loc)
+#loc = loc("simple.f90":0:0)
+
+// CHECK-DWARF5: llvm.module_flags [#llvm.mlir.module_flag<max, "Dwarf Version", 5 : i32>]
+// CHECK-DWARF4: llvm.module_flags [#llvm.mlir.module_flag<max, "Dwarf Version", 4 : i32>]
+// CHECK-DWARF3: llvm.module_flags [#llvm.mlir.module_flag<max, "Dwarf Version", 3 : i32>]
+// CHECK-DWARF2: llvm.module_flags [#llvm.mlir.module_flag<max, "Dwarf Version", 2 : i32>]
+// CHECK-WITHOUT-VERSION-NOT: llvm.module_flags

``````````

</details>


https://github.com/llvm/llvm-project/pull/159137


More information about the flang-commits mailing list