[flang-commits] [clang] [flang] [flang] Implement -grecord-command-line for Flang (PR #181686)
Yangyu Chen via flang-commits
flang-commits at lists.llvm.org
Tue Feb 24 00:16:37 PST 2026
https://github.com/cyyself updated https://github.com/llvm/llvm-project/pull/181686
>From d3c8fbfb4528726349e255ec8c1ebad7b1c7fc9b Mon Sep 17 00:00:00 2001
From: Yangyu Chen <cyy at cyyself.name>
Date: Mon, 16 Feb 2026 23:25:54 +0800
Subject: [PATCH] [flang] Implement -grecord-command-line for Flang
Enable Flang to match Clang behavior for command-line recording in DWARF
producer strings when using -grecord-command-line.
Signed-off-by: Yangyu Chen <cyy at cyyself.name>
---
clang/include/clang/Options/Options.td | 12 ++++++-----
flang/include/flang/Frontend/CodeGenOptions.h | 5 +++++
.../flang/Optimizer/Passes/Pipelines.h | 7 +++++--
.../flang/Optimizer/Transforms/Passes.td | 5 ++++-
flang/include/flang/Tools/CrossToolHelpers.h | 2 ++
flang/lib/Frontend/CompilerInvocation.cpp | 5 +++++
flang/lib/Optimizer/Passes/Pipelines.cpp | 12 +++++++----
.../lib/Optimizer/Transforms/AddDebugInfo.cpp | 8 ++++++--
flang/test/Driver/grecord-command-line.f90 | 14 +++++++++++++
.../Transforms/debug-dwarf-debug-flags.fir | 20 +++++++++++++++++++
10 files changed, 76 insertions(+), 14 deletions(-)
create mode 100644 flang/test/Driver/grecord-command-line.f90
create mode 100644 flang/test/Transforms/debug-dwarf-debug-flags.fir
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index a274017953b1d..11c56d6eb519b 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4938,9 +4938,11 @@ def gxcoff : Joined<["-"], "gxcoff">, Group<g_Group>, Flags<[Unsupported]>;
def gvms : Joined<["-"], "gvms">, Group<g_Group>, Flags<[Unsupported]>;
def gtoggle : Flag<["-"], "gtoggle">, Group<g_flags_Group>, Flags<[Unsupported]>;
def grecord_command_line : Flag<["-"], "grecord-command-line">,
- Group<g_flags_Group>;
+ Group<g_flags_Group>,
+ Visibility<[ClangOption, FlangOption]>;
def gno_record_command_line : Flag<["-"], "gno-record-command-line">,
- Group<g_flags_Group>;
+ Group<g_flags_Group>,
+ Visibility<[ClangOption, FlangOption]>;
def : Flag<["-"], "grecord-gcc-switches">, Alias<grecord_command_line>;
def : Flag<["-"], "gno-record-gcc-switches">, Alias<gno_record_command_line>;
defm strict_dwarf : BoolOption<"g", "strict-dwarf",
@@ -7887,6 +7889,9 @@ def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
def record_command_line : Separate<["-"], "record-command-line">,
HelpText<"The string to embed in the .LLVM.command.line section.">,
MarshallingInfoString<CodeGenOpts<"RecordCommandLine">>;
+def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
+ HelpText<"The string to embed in the Dwarf debug flags record.">,
+ MarshallingInfoString<CodeGenOpts<"DwarfDebugFlags">>;
def dwarf_version_EQ : Joined<["-"], "dwarf-version=">,
MarshallingInfoInt<CodeGenOpts<"DwarfVersion">>;
@@ -7908,9 +7913,6 @@ def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">,
Values<"gdb,lldb,sce,dbx">,
NormalizedValuesScope<"llvm::DebuggerKind">, NormalizedValues<["GDB", "LLDB", "SCE", "DBX"]>,
MarshallingInfoEnum<CodeGenOpts<"DebuggerTuning">, "Default">;
-def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
- HelpText<"The string to embed in the Dwarf debug flags record.">,
- MarshallingInfoString<CodeGenOpts<"DwarfDebugFlags">>;
def compress_debug_sections_EQ : Joined<["-", "--"], "compress-debug-sections=">,
HelpText<"DWARF debug sections compression type">, Values<"none,zlib,zstd">,
NormalizedValuesScope<"llvm::DebugCompressionType">, NormalizedValues<["None", "Zlib", "Zstd"]>,
diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h
index 3dca169d43b39..5a141e3c0a87d 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -73,6 +73,11 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// The string containing the commandline for the llvm.commandline metadata.
std::optional<std::string> RecordCommandLine;
+ /// The value from -dwarf-debug-flags to append to DW_AT_producer.
+ /// This is typically a reconstructed user command line (e.g. from
+ /// -grecord-command-line) and may contain multiple space-separated flags.
+ std::string DwarfDebugFlags;
+
/// The name of the file to which the backend should save YAML optimization
/// records.
std::string OptRecordFile;
diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h b/flang/include/flang/Optimizer/Passes/Pipelines.h
index 1a7ff4ff3dfa2..8f2ff5f82299d 100644
--- a/flang/include/flang/Optimizer/Passes/Pipelines.h
+++ b/flang/include/flang/Optimizer/Passes/Pipelines.h
@@ -103,7 +103,9 @@ void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm);
void addDebugInfoPass(mlir::PassManager &pm,
llvm::codegenoptions::DebugInfoKind debugLevel,
llvm::OptimizationLevel optLevel,
- llvm::StringRef inputFilename, int32_t dwarfVersion);
+ llvm::StringRef inputFilename, int32_t dwarfVersion,
+ llvm::StringRef splitDwarfFile,
+ llvm::StringRef dwarfDebugFlags);
/// Create FIRToLLVMPassOptions from pipeline configuration.
FIRToLLVMPassOptions
@@ -164,7 +166,8 @@ void createDebugPasses(mlir::PassManager &pm,
llvm::codegenoptions::DebugInfoKind debugLevel,
llvm::OptimizationLevel OptLevel,
llvm::StringRef inputFilename, int32_t dwarfVersion,
- llvm::StringRef splitDwarfFile);
+ llvm::StringRef splitDwarfFile,
+ llvm::StringRef dwarfDebugFlags);
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 d812e271b158d..bdee252d14c72 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -260,7 +260,10 @@ def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> {
"dwarf version">,
Option<"splitDwarfFile", "split-dwarf-file",
"std::string", /*default=*/"std::string{}",
- "Name of the split dwarf file">
+ "Name of the split dwarf file">,
+ Option<"dwarfDebugFlags", "dwarf-debug-flags",
+ "std::string", /*default=*/"std::string{}",
+ "Command-line flags to append to DWARF producer">
];
}
diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h
index 44fb252d2b366..f29fc8ef0ea56 100644
--- a/flang/include/flang/Tools/CrossToolHelpers.h
+++ b/flang/include/flang/Tools/CrossToolHelpers.h
@@ -110,6 +110,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
}
DwarfVersion = opts.DwarfVersion;
SplitDwarfFile = opts.SplitDwarfFile;
+ DwarfDebugFlags = opts.DwarfDebugFlags;
}
llvm::OptimizationLevel OptLevel; ///< optimisation level
@@ -148,6 +149,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
CX_Full; ///< Method for calculating complex number division
int32_t DwarfVersion = 0; ///< Version of DWARF debug info to generate
std::string SplitDwarfFile = ""; ///< File name for the split debug info
+ std::string DwarfDebugFlags = ""; ///< Debug flags to append to DWARF producer
};
struct OffloadModuleOpts {
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index fc4975f9592eb..72b766e52ab3b 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -165,6 +165,11 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
args.getLastArg(clang::options::OPT_split_dwarf_output))
opts.SplitDwarfOutput = a->getValue();
}
+
+ if (const llvm::opt::Arg *arg =
+ args.getLastArg(clang::options::OPT_dwarf_debug_flags))
+ opts.DwarfDebugFlags = arg->getValue();
+
return true;
}
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 9b73d587ee7bc..64e925c0a4922 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -97,13 +97,15 @@ void addDebugInfoPass(mlir::PassManager &pm,
llvm::codegenoptions::DebugInfoKind debugLevel,
llvm::OptimizationLevel optLevel,
llvm::StringRef inputFilename, int32_t dwarfVersion,
- llvm::StringRef splitDwarfFile) {
+ llvm::StringRef splitDwarfFile,
+ llvm::StringRef dwarfDebugFlags) {
fir::AddDebugInfoOptions options;
options.debugLevel = getEmissionKind(debugLevel);
options.isOptimized = optLevel != llvm::OptimizationLevel::O0;
options.inputFilename = inputFilename;
options.dwarfVersion = dwarfVersion;
options.splitDwarfFile = splitDwarfFile;
+ options.dwarfDebugFlags = dwarfDebugFlags;
addPassConditionally(pm, disableDebugInfo,
[&]() { return fir::createAddDebugInfoPass(options); });
}
@@ -362,10 +364,11 @@ void createDebugPasses(mlir::PassManager &pm,
llvm::codegenoptions::DebugInfoKind debugLevel,
llvm::OptimizationLevel OptLevel,
llvm::StringRef inputFilename, int32_t dwarfVersion,
- llvm::StringRef splitDwarfFile) {
+ llvm::StringRef splitDwarfFile,
+ llvm::StringRef dwarfDebugFlags) {
if (debugLevel != llvm::codegenoptions::NoDebugInfo)
addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename, dwarfVersion,
- splitDwarfFile);
+ splitDwarfFile, dwarfDebugFlags);
}
void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
@@ -384,7 +387,8 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo));
fir::addExternalNameConversionPass(pm, config.Underscoring);
fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename,
- config.DwarfVersion, config.SplitDwarfFile);
+ config.DwarfVersion, config.SplitDwarfFile,
+ config.DwarfDebugFlags);
fir::addTargetRewritePass(pm);
fir::addCompilerGeneratedNamesConversionPass(pm);
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 35d8a2f6c3aa9..8f712ab5fe262 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -861,8 +861,12 @@ void AddDebugInfoPass::runOnOperation() {
mlir::LLVM::DIFileAttr fileAttr =
mlir::LLVM::DIFileAttr::get(context, fileName, filePath);
- mlir::StringAttr producer =
- mlir::StringAttr::get(context, Fortran::common::getFlangFullVersion());
+ // Match Clang style by starting with the full compiler version and
+ // appending -dwarf-debug-flags content when provided.
+ std::string producerString = Fortran::common::getFlangFullVersion();
+ if (!dwarfDebugFlags.empty())
+ producerString += " " + dwarfDebugFlags;
+ mlir::StringAttr producer = mlir::StringAttr::get(context, producerString);
mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get(
mlir::DistinctAttr::create(mlir::UnitAttr::get(context)),
llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer,
diff --git a/flang/test/Driver/grecord-command-line.f90 b/flang/test/Driver/grecord-command-line.f90
new file mode 100644
index 0000000000000..269381e464e7d
--- /dev/null
+++ b/flang/test/Driver/grecord-command-line.f90
@@ -0,0 +1,14 @@
+! This checks that -grecord-command-line is forwarded by the flang driver to
+! an FC1 -dwarf-debug-flags argument and that -gno-record-command-line
+! disables it, matching clang behavior.
+!
+! RUN: %flang -### -grecord-command-line %s 2>&1 | FileCheck --check-prefix=GRECORD %s
+! RUN: %flang -### -gno-record-command-line %s 2>&1 | FileCheck --check-prefix=GNO_RECORD %s
+! RUN: %flang -### -grecord-command-line -gno-record-command-line %s 2>&1 | FileCheck --check-prefix=GNO_RECORD %s
+!
+! GRECORD: "-dwarf-debug-flags"
+!
+! GNO_RECORD-NOT: "-dwarf-debug-flags"
+
+program p
+end program p
diff --git a/flang/test/Transforms/debug-dwarf-debug-flags.fir b/flang/test/Transforms/debug-dwarf-debug-flags.fir
new file mode 100644
index 0000000000000..e3b43508a6a89
--- /dev/null
+++ b/flang/test/Transforms/debug-dwarf-debug-flags.fir
@@ -0,0 +1,20 @@
+// Test the dwarf-debug-flags option will passed to MLIR correctly and show
+// up in the generated debug info.
+// RUN: fir-opt --add-debug-info="debug-level=Full" --mlir-print-debuginfo %s \
+// RUN: | FileCheck --check-prefix=CHECK-NO-FLAGS %s
+// RUN: fir-opt --add-debug-info="debug-level=Full dwarf-debug-flags=\"-grecord-command-line -O2\"" \
+// RUN: --mlir-print-debuginfo %s | FileCheck --check-prefix=CHECK-FLAGS %s
+
+module {
+ func.func @_QPs() {
+ return loc(#loc_s)
+ } loc(#loc_s)
+} loc(#loc_module)
+#loc_module = loc("simple.f90":1:1)
+#loc_s = loc("simple.f90":2:1)
+
+// CHECK-NO-FLAGS: #llvm.di_compile_unit<
+// CHECK-NO-FLAGS-SAME: producer = "{{.*}}flang{{.*}}"
+
+// CHECK-FLAGS: #llvm.di_compile_unit<
+// CHECK-FLAGS-SAME: producer = "{{.*}} -grecord-command-line -O2"
More information about the flang-commits
mailing list