Skip to content

Conversation

abidh
Copy link
Contributor

@abidh abidh commented Sep 16, 2025

This PR builds on the #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.

This PR builds on the llvm#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. This 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.
@llvmbot llvmbot added flang:driver flang Flang issues not falling into any other category flang:fir-hlfir labels Sep 16, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2025

@llvm/pr-subscribers-flang-driver

Author: Abid Qadeer (abidh)

Changes

This PR builds on the #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 --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

@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2025

@llvm/pr-subscribers-flang-fir-hlfir

Author: Abid Qadeer (abidh)

Changes

This PR builds on the #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 --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

Copy link
Contributor

@tarunprabhu tarunprabhu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Abid. Barring some minor comments, this looks good.

@@ -0,0 +1,22 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Unnecessary empty line at start of file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

! 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like both CHECK-WITHOUT-VERSION and CHECK-WITHOUT-DEBUG-KIND check for the absence of "Dwarf version" in the output. We can probably just use CHECK-WITHOUT-VERSION here to eliminate redundant check prefixes.

Suggested change
! RUN: | FileCheck --check-prefix=CHECK-WITHOUT-DEBUG-KIND %s
! RUN: | FileCheck --check-prefix=CHECK-WITHOUT-VERSION %s

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@tarunprabhu tarunprabhu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes

@abidh abidh merged commit 453e410 into llvm:main Sep 17, 2025
9 checks passed
llvm::codegenoptions::DebugInfoKind debugLevel,
llvm::OptimizationLevel OptLevel,
llvm::StringRef inputFilename);
llvm::StringRef inputFilename, int32_t dwarfVersion);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please give dwarfVersion a default value in the declaration?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you kindly describe what problem do you see because the version have a default value both in pass declaration and in opts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:driver flang:fir-hlfir flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants