Skip to content

Commit 96675a4

Browse files
authored
[flang][Driver] Support -gsplit-dwarf. (#160540)
This flags enables the compiler to generate most of the debug information in a separate file which can be useful for executable size and link times. Clang already supports this flag. I have tried to follow the logic of the clang implementation where possible. Some functions were moved where they could be used by both clang and flang. The `addOtherOptions` was renamed to `addDebugOptions` to better reflect its purpose. Clang also set the `splitDebugFilename` field of the `DICompileUnit` in the IR when this option is present. That part is currently missing from this patch and will come in a follow-up PR.
1 parent c731291 commit 96675a4

File tree

12 files changed

+199
-52
lines changed

12 files changed

+199
-52
lines changed

clang/include/clang/Driver/CommonArgs.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ unsigned DwarfVersionNum(StringRef ArgValue);
105105
const llvm::opt::Arg *getDwarfNArg(const llvm::opt::ArgList &Args);
106106
unsigned getDwarfVersion(const ToolChain &TC, const llvm::opt::ArgList &Args);
107107

108+
enum class DwarfFissionKind { None, Split, Single };
109+
110+
DwarfFissionKind getDebugFissionKind(const Driver &D,
111+
const llvm::opt::ArgList &Args,
112+
llvm::opt::Arg *&Arg);
113+
114+
bool checkDebugInfoOption(const llvm::opt::Arg *A,
115+
const llvm::opt::ArgList &Args, const Driver &D,
116+
const ToolChain &TC);
117+
108118
void AddAssemblerKPIC(const ToolChain &ToolChain,
109119
const llvm::opt::ArgList &Args,
110120
llvm::opt::ArgStringList &CmdArgs);

clang/include/clang/Driver/Options.td

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4754,13 +4754,13 @@ defm column_info : BoolOption<"g", "column-info",
47544754
PosFlag<SetTrue>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>,
47554755
Group<g_flags_Group>;
47564756
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>,
4757-
Visibility<[ClangOption, CLOption, DXCOption]>;
4757+
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;
47584758
def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_Group>,
4759-
Visibility<[ClangOption, CLOption, DXCOption]>,
4759+
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
47604760
HelpText<"Set DWARF fission mode">,
47614761
Values<"split,single">;
47624762
def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group<g_flags_Group>,
4763-
Visibility<[ClangOption, CLOption, DXCOption]>;
4763+
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;
47644764
def gtemplate_alias : Flag<["-"], "gtemplate-alias">, Group<g_flags_Group>, Visibility<[ClangOption, CC1Option]>;
47654765
def gno_template_alias : Flag<["-"], "gno-template-alias">, Group<g_flags_Group>, Visibility<[ClangOption]>;
47664766
def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group<g_flags_Group>;
@@ -8405,7 +8405,7 @@ def main_file_name : Separate<["-"], "main-file-name">,
84058405
MarshallingInfoString<CodeGenOpts<"MainFileName">>;
84068406
def split_dwarf_output : Separate<["-"], "split-dwarf-output">,
84078407
HelpText<"File name to use for split dwarf debug info output">,
8408-
Visibility<[CC1Option, CC1AsOption]>,
8408+
Visibility<[CC1Option, CC1AsOption, FC1Option]>,
84098409
MarshallingInfoString<CodeGenOpts<"SplitDwarfOutput">>;
84108410

84118411
let Visibility = [CC1Option, FC1Option] in {
@@ -8437,6 +8437,10 @@ def dependent_lib : Joined<["--"], "dependent-lib=">,
84378437
HelpText<"Add dependent library">,
84388438
MarshallingInfoStringVector<CodeGenOpts<"DependentLibraries">>;
84398439

8440+
def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
8441+
HelpText<"Name of the split dwarf debug info file to encode in the object file">,
8442+
MarshallingInfoString<CodeGenOpts<"SplitDwarfFile">>;
8443+
84408444
} // let Visibility = [CC1Option, FC1Option]
84418445

84428446
let Visibility = [CC1Option] in {
@@ -8447,9 +8451,6 @@ def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
84478451
def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">,
84488452
HelpText<"Assume all functions with C linkage do not unwind">,
84498453
MarshallingInfoFlag<LangOpts<"ExternCNoUnwind">>;
8450-
def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
8451-
HelpText<"Name of the split dwarf debug info file to encode in the object file">,
8452-
MarshallingInfoString<CodeGenOpts<"SplitDwarfFile">>;
84538454
def fno_wchar : Flag<["-"], "fno-wchar">,
84548455
HelpText<"Disable C++ builtin type wchar_t">,
84558456
MarshallingInfoNegativeFlag<LangOpts<"WChar">, cplusplus.KeyPath>,

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -695,16 +695,6 @@ RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
695695
}
696696
}
697697

698-
static bool checkDebugInfoOption(const Arg *A, const ArgList &Args,
699-
const Driver &D, const ToolChain &TC) {
700-
assert(A && "Expected non-nullptr argument.");
701-
if (TC.supportsDebugInfoOption(A))
702-
return true;
703-
D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
704-
<< A->getAsString(Args) << TC.getTripleString();
705-
return false;
706-
}
707-
708698
static void RenderDebugInfoCompressionArgs(const ArgList &Args,
709699
ArgStringList &CmdArgs,
710700
const Driver &D,
@@ -4325,27 +4315,6 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
43254315
Args.addLastArg(CmdArgs, options::OPT_warning_suppression_mappings_EQ);
43264316
}
43274317

4328-
DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
4329-
const ArgList &Args, Arg *&Arg) {
4330-
Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
4331-
options::OPT_gno_split_dwarf);
4332-
if (!Arg || Arg->getOption().matches(options::OPT_gno_split_dwarf))
4333-
return DwarfFissionKind::None;
4334-
4335-
if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
4336-
return DwarfFissionKind::Split;
4337-
4338-
StringRef Value = Arg->getValue();
4339-
if (Value == "split")
4340-
return DwarfFissionKind::Split;
4341-
if (Value == "single")
4342-
return DwarfFissionKind::Single;
4343-
4344-
D.Diag(diag::err_drv_unsupported_option_argument)
4345-
<< Arg->getSpelling() << Arg->getValue();
4346-
return DwarfFissionKind::None;
4347-
}
4348-
43494318
static void renderDwarfFormat(const Driver &D, const llvm::Triple &T,
43504319
const ArgList &Args, ArgStringList &CmdArgs,
43514320
unsigned DwarfVersion) {

clang/lib/Driver/ToolChains/Clang.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,6 @@ class LLVM_LIBRARY_VISIBILITY LinkerWrapper final : public Tool {
187187
const char *LinkingOutput) const override;
188188
};
189189

190-
enum class DwarfFissionKind { None, Split, Single };
191-
192-
DwarfFissionKind getDebugFissionKind(const Driver &D,
193-
const llvm::opt::ArgList &Args,
194-
llvm::opt::Arg *&Arg);
195-
196190
// Calculate the output path of the module file when compiling a module unit
197191
// with the `-fmodule-output` option or `-fmodule-output=` option specified.
198192
// The behavior is:

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,6 +2270,37 @@ unsigned tools::getDwarfVersion(const ToolChain &TC,
22702270
return DwarfVersion;
22712271
}
22722272

2273+
DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
2274+
const ArgList &Args, Arg *&Arg) {
2275+
Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
2276+
options::OPT_gno_split_dwarf);
2277+
if (!Arg || Arg->getOption().matches(options::OPT_gno_split_dwarf))
2278+
return DwarfFissionKind::None;
2279+
2280+
if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
2281+
return DwarfFissionKind::Split;
2282+
2283+
StringRef Value = Arg->getValue();
2284+
if (Value == "split")
2285+
return DwarfFissionKind::Split;
2286+
if (Value == "single")
2287+
return DwarfFissionKind::Single;
2288+
2289+
D.Diag(diag::err_drv_unsupported_option_argument)
2290+
<< Arg->getSpelling() << Arg->getValue();
2291+
return DwarfFissionKind::None;
2292+
}
2293+
2294+
bool tools::checkDebugInfoOption(const Arg *A, const ArgList &Args,
2295+
const Driver &D, const ToolChain &TC) {
2296+
assert(A && "Expected non-nullptr argument.");
2297+
if (TC.supportsDebugInfoOption(A))
2298+
return true;
2299+
D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
2300+
<< A->getAsString(Args) << TC.getTripleString();
2301+
return false;
2302+
}
2303+
22732304
void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
22742305
ArgStringList &CmdArgs) {
22752306
llvm::Reloc::Model RelocationModel;

clang/lib/Driver/ToolChains/Flang.cpp

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ static bool shouldLoopVersion(const ArgList &Args) {
120120
return false;
121121
}
122122

123-
void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
123+
void Flang::addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA,
124+
const InputInfo &Output, const InputInfo &Input,
125+
llvm::opt::ArgStringList &CmdArgs) const {
126+
const auto &TC = getToolChain();
127+
const Driver &D = TC.getDriver();
124128
Args.addAllArgs(CmdArgs,
125129
{options::OPT_module_dir, options::OPT_fdebug_module_writer,
126130
options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
@@ -131,20 +135,60 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
131135
options::OPT_finstrument_functions});
132136

133137
llvm::codegenoptions::DebugInfoKind DebugInfoKind;
138+
bool hasDwarfNArg = getDwarfNArg(Args) != nullptr;
134139
if (Args.hasArg(options::OPT_gN_Group)) {
135140
Arg *gNArg = Args.getLastArg(options::OPT_gN_Group);
136141
DebugInfoKind = debugLevelToInfoKind(*gNArg);
137-
} else if (Args.hasArg(options::OPT_g_Group)) {
142+
} else if (Args.hasArg(options::OPT_g_Flag) || hasDwarfNArg) {
138143
DebugInfoKind = llvm::codegenoptions::FullDebugInfo;
139144
} else {
140145
DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
141146
}
142147
addDebugInfoKind(CmdArgs, DebugInfoKind);
143-
if (getDwarfNArg(Args)) {
148+
if (hasDwarfNArg) {
144149
const unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);
145150
CmdArgs.push_back(
146151
Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion)));
147152
}
153+
if (Args.hasArg(options::OPT_gsplit_dwarf) ||
154+
Args.hasArg(options::OPT_gsplit_dwarf_EQ)) {
155+
// FIXME: -gsplit-dwarf on AIX is currently unimplemented.
156+
if (TC.getTriple().isOSAIX()) {
157+
D.Diag(diag::err_drv_unsupported_opt_for_target)
158+
<< Args.getLastArg(options::OPT_gsplit_dwarf)->getSpelling()
159+
<< TC.getTriple().str();
160+
return;
161+
}
162+
if (DebugInfoKind == llvm::codegenoptions::NoDebugInfo)
163+
return;
164+
165+
Arg *SplitDWARFArg;
166+
DwarfFissionKind DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg);
167+
168+
if (DwarfFission == DwarfFissionKind::None ||
169+
!checkDebugInfoOption(SplitDWARFArg, Args, D, TC))
170+
return;
171+
172+
if (!TC.getTriple().isOSBinFormatELF() &&
173+
!TC.getTriple().isOSBinFormatWasm() &&
174+
!TC.getTriple().isOSBinFormatCOFF()) {
175+
D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
176+
<< SplitDWARFArg->getSpelling() << TC.getTriple().str();
177+
return;
178+
}
179+
180+
if (!isa<AssembleJobAction>(JA) && !isa<CompileJobAction>(JA) &&
181+
isa<BackendJobAction>(JA))
182+
return;
183+
184+
const char *SplitDWARFOut = SplitDebugName(JA, Args, Input, Output);
185+
CmdArgs.push_back("-split-dwarf-file");
186+
CmdArgs.push_back(SplitDWARFOut);
187+
if (DwarfFission == DwarfFissionKind::Split) {
188+
CmdArgs.push_back("-split-dwarf-output");
189+
CmdArgs.push_back(SplitDWARFOut);
190+
}
191+
}
148192
}
149193

150194
void Flang::addCodegenOptions(const ArgList &Args,
@@ -936,8 +980,8 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
936980
if (willEmitRemarks(Args))
937981
renderRemarksOptions(Args, CmdArgs, Input);
938982

939-
// Add other compile options
940-
addOtherOptions(Args, CmdArgs);
983+
// Add debug compile options
984+
addDebugOptions(Args, JA, Output, Input, CmdArgs);
941985

942986
// Disable all warnings
943987
// TODO: Handle interactions between -w, -pedantic, -Wall, -WOption

clang/lib/Driver/ToolChains/Flang.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,16 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
125125
void addCodegenOptions(const llvm::opt::ArgList &Args,
126126
llvm::opt::ArgStringList &CmdArgs) const;
127127

128-
/// Extract other compilation options from the driver arguments and add them
128+
/// Extract debug compilation options from the driver arguments and add them
129129
/// to the command arguments.
130130
///
131131
/// \param [in] Args The list of input driver arguments
132+
/// \param [in] JA The job action
133+
/// \param [in] Output The output information on the current file output
134+
/// \param [in] Input The input information on the current file input
132135
/// \param [out] CmdArgs The list of output command arguments
133-
void addOtherOptions(const llvm::opt::ArgList &Args,
136+
void addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA,
137+
const InputInfo &Output, const InputInfo &Input,
134138
llvm::opt::ArgStringList &CmdArgs) const;
135139

136140
public:

flang/include/flang/Frontend/CodeGenOptions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ class CodeGenOptions : public CodeGenOptionsBase {
168168
/// by -fprofile-sample-use or -fprofile-instr-use.
169169
std::string ProfileRemappingFile;
170170

171+
/// The name for the split debug info file used for the DW_AT_[GNU_]dwo_name
172+
/// attribute in the skeleton CU.
173+
std::string SplitDwarfFile;
174+
175+
/// Output filename for the split debug info, not used in the skeleton CU.
176+
std::string SplitDwarfOutput;
177+
171178
/// Check if Clang profile instrumenation is on.
172179
bool hasProfileClangInstr() const {
173180
return getProfileInstr() == llvm::driver::ProfileClangInstr;

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
160160
opts.DwarfVersion =
161161
getLastArgIntValue(args, clang::driver::options::OPT_dwarf_version_EQ,
162162
/*Default=*/0, diags);
163+
if (const llvm::opt::Arg *a =
164+
args.getLastArg(clang::driver::options::OPT_split_dwarf_file))
165+
opts.SplitDwarfFile = a->getValue();
166+
if (const llvm::opt::Arg *a =
167+
args.getLastArg(clang::driver::options::OPT_split_dwarf_output))
168+
opts.SplitDwarfOutput = a->getValue();
163169
}
164170
return true;
165171
}

flang/lib/Frontend/FrontendActions.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,19 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags,
898898
llvm::CodeGenFileType cgft = (act == BackendActionTy::Backend_EmitAssembly)
899899
? llvm::CodeGenFileType::AssemblyFile
900900
: llvm::CodeGenFileType::ObjectFile;
901-
if (tm.addPassesToEmitFile(codeGenPasses, os, nullptr, cgft)) {
901+
std::unique_ptr<llvm::ToolOutputFile> dwoOS;
902+
if (!codeGenOpts.SplitDwarfOutput.empty()) {
903+
std::error_code ec;
904+
dwoOS = std::make_unique<llvm::ToolOutputFile>(codeGenOpts.SplitDwarfOutput,
905+
ec, llvm::sys::fs::OF_None);
906+
if (ec) {
907+
diags.Report(clang::diag::err_fe_unable_to_open_output)
908+
<< codeGenOpts.SplitDwarfOutput << ec.message();
909+
return;
910+
}
911+
}
912+
if (tm.addPassesToEmitFile(codeGenPasses, os, dwoOS ? &dwoOS->os() : nullptr,
913+
cgft)) {
902914
unsigned diagID =
903915
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
904916
"emission of this file type is not supported");
@@ -909,6 +921,9 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags,
909921
// Run the passes
910922
codeGenPasses.run(llvmModule);
911923

924+
if (dwoOS)
925+
dwoOS->keep();
926+
912927
// Cleanup
913928
delete tlii;
914929
}
@@ -1322,6 +1337,7 @@ void CodeGenAction::executeAction() {
13221337
llvm::TargetMachine &targetMachine = ci.getTargetMachine();
13231338

13241339
targetMachine.Options.MCOptions.AsmVerbose = targetOpts.asmVerbose;
1340+
targetMachine.Options.MCOptions.SplitDwarfFile = codeGenOpts.SplitDwarfFile;
13251341

13261342
const llvm::Triple &theTriple = targetMachine.getTargetTriple();
13271343

0 commit comments

Comments
 (0)