-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[flang][Driver] Support -gsplit-dwarf. #160540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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. The 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 it will come in a follow-up PR.
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-clang Author: Abid Qadeer (abidh) ChangesThis 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 Clang also set the Patch is 20.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/160540.diff 12 Files Affected:
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index 1464ce4e1b31b..40ae40665b040 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -105,6 +105,16 @@ unsigned DwarfVersionNum(StringRef ArgValue);
const llvm::opt::Arg *getDwarfNArg(const llvm::opt::ArgList &Args);
unsigned getDwarfVersion(const ToolChain &TC, const llvm::opt::ArgList &Args);
+enum class DwarfFissionKind { None, Split, Single };
+
+DwarfFissionKind getDebugFissionKind(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::Arg *&Arg);
+
+bool checkDebugInfoOption(const llvm::opt::Arg *A,
+ const llvm::opt::ArgList &Args, const Driver &D,
+ const ToolChain &TC);
+
void AddAssemblerKPIC(const ToolChain &ToolChain,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 16e1c396fedbe..61fd0fa3794ee 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4754,13 +4754,13 @@ defm column_info : BoolOption<"g", "column-info",
PosFlag<SetTrue>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>,
Group<g_flags_Group>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>,
- Visibility<[ClangOption, CLOption, DXCOption]>;
+ Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;
def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_Group>,
- Visibility<[ClangOption, CLOption, DXCOption]>,
+ Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
HelpText<"Set DWARF fission mode">,
Values<"split,single">;
def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group<g_flags_Group>,
- Visibility<[ClangOption, CLOption, DXCOption]>;
+ Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;
def gtemplate_alias : Flag<["-"], "gtemplate-alias">, Group<g_flags_Group>, Visibility<[ClangOption, CC1Option]>;
def gno_template_alias : Flag<["-"], "gno-template-alias">, Group<g_flags_Group>, Visibility<[ClangOption]>;
def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group<g_flags_Group>;
@@ -8405,7 +8405,7 @@ def main_file_name : Separate<["-"], "main-file-name">,
MarshallingInfoString<CodeGenOpts<"MainFileName">>;
def split_dwarf_output : Separate<["-"], "split-dwarf-output">,
HelpText<"File name to use for split dwarf debug info output">,
- Visibility<[CC1Option, CC1AsOption]>,
+ Visibility<[CC1Option, CC1AsOption, FC1Option]>,
MarshallingInfoString<CodeGenOpts<"SplitDwarfOutput">>;
let Visibility = [CC1Option, FC1Option] in {
@@ -8437,6 +8437,10 @@ def dependent_lib : Joined<["--"], "dependent-lib=">,
HelpText<"Add dependent library">,
MarshallingInfoStringVector<CodeGenOpts<"DependentLibraries">>;
+def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
+ HelpText<"Name of the split dwarf debug info file to encode in the object file">,
+ MarshallingInfoString<CodeGenOpts<"SplitDwarfFile">>;
+
} // let Visibility = [CC1Option, FC1Option]
let Visibility = [CC1Option] in {
@@ -8447,9 +8451,6 @@ def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">,
HelpText<"Assume all functions with C linkage do not unwind">,
MarshallingInfoFlag<LangOpts<"ExternCNoUnwind">>;
-def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
- HelpText<"Name of the split dwarf debug info file to encode in the object file">,
- MarshallingInfoString<CodeGenOpts<"SplitDwarfFile">>;
def fno_wchar : Flag<["-"], "fno-wchar">,
HelpText<"Disable C++ builtin type wchar_t">,
MarshallingInfoNegativeFlag<LangOpts<"WChar">, cplusplus.KeyPath>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index e7aabee273a34..43cf8f54e272e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -695,16 +695,6 @@ RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
}
}
-static bool checkDebugInfoOption(const Arg *A, const ArgList &Args,
- const Driver &D, const ToolChain &TC) {
- assert(A && "Expected non-nullptr argument.");
- if (TC.supportsDebugInfoOption(A))
- return true;
- D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
- << A->getAsString(Args) << TC.getTripleString();
- return false;
-}
-
static void RenderDebugInfoCompressionArgs(const ArgList &Args,
ArgStringList &CmdArgs,
const Driver &D,
@@ -4327,27 +4317,6 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
Args.addLastArg(CmdArgs, options::OPT_warning_suppression_mappings_EQ);
}
-DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
- const ArgList &Args, Arg *&Arg) {
- Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
- options::OPT_gno_split_dwarf);
- if (!Arg || Arg->getOption().matches(options::OPT_gno_split_dwarf))
- return DwarfFissionKind::None;
-
- if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
- return DwarfFissionKind::Split;
-
- StringRef Value = Arg->getValue();
- if (Value == "split")
- return DwarfFissionKind::Split;
- if (Value == "single")
- return DwarfFissionKind::Single;
-
- D.Diag(diag::err_drv_unsupported_option_argument)
- << Arg->getSpelling() << Arg->getValue();
- return DwarfFissionKind::None;
-}
-
static void renderDwarfFormat(const Driver &D, const llvm::Triple &T,
const ArgList &Args, ArgStringList &CmdArgs,
unsigned DwarfVersion) {
diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h
index 18f6c5ed06a59..c22789591e00a 100644
--- a/clang/lib/Driver/ToolChains/Clang.h
+++ b/clang/lib/Driver/ToolChains/Clang.h
@@ -187,12 +187,6 @@ class LLVM_LIBRARY_VISIBILITY LinkerWrapper final : public Tool {
const char *LinkingOutput) const override;
};
-enum class DwarfFissionKind { None, Split, Single };
-
-DwarfFissionKind getDebugFissionKind(const Driver &D,
- const llvm::opt::ArgList &Args,
- llvm::opt::Arg *&Arg);
-
// Calculate the output path of the module file when compiling a module unit
// with the `-fmodule-output` option or `-fmodule-output=` option specified.
// The behavior is:
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 08cd98fd04df0..4902c2f3c0cbe 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -2270,6 +2270,37 @@ unsigned tools::getDwarfVersion(const ToolChain &TC,
return DwarfVersion;
}
+DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
+ const ArgList &Args, Arg *&Arg) {
+ Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
+ options::OPT_gno_split_dwarf);
+ if (!Arg || Arg->getOption().matches(options::OPT_gno_split_dwarf))
+ return DwarfFissionKind::None;
+
+ if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
+ return DwarfFissionKind::Split;
+
+ StringRef Value = Arg->getValue();
+ if (Value == "split")
+ return DwarfFissionKind::Split;
+ if (Value == "single")
+ return DwarfFissionKind::Single;
+
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getSpelling() << Arg->getValue();
+ return DwarfFissionKind::None;
+}
+
+bool tools::checkDebugInfoOption(const Arg *A, const ArgList &Args,
+ const Driver &D, const ToolChain &TC) {
+ assert(A && "Expected non-nullptr argument.");
+ if (TC.supportsDebugInfoOption(A))
+ return true;
+ D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
+ << A->getAsString(Args) << TC.getTripleString();
+ return false;
+}
+
void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
ArgStringList &CmdArgs) {
llvm::Reloc::Model RelocationModel;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 6fc372eb75eb7..3e8444c151f36 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -120,7 +120,11 @@ static bool shouldLoopVersion(const ArgList &Args) {
return false;
}
-void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
+void Flang::addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA,
+ const InputInfo &Output, const InputInfo &Input,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ const auto &TC = getToolChain();
+ const Driver &D = TC.getDriver();
Args.addAllArgs(CmdArgs,
{options::OPT_module_dir, options::OPT_fdebug_module_writer,
options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
@@ -131,20 +135,57 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
options::OPT_finstrument_functions});
llvm::codegenoptions::DebugInfoKind DebugInfoKind;
+ bool hasDwarfNArg = getDwarfNArg(Args) != nullptr;
if (Args.hasArg(options::OPT_gN_Group)) {
Arg *gNArg = Args.getLastArg(options::OPT_gN_Group);
DebugInfoKind = debugLevelToInfoKind(*gNArg);
- } else if (Args.hasArg(options::OPT_g_Group)) {
+ } else if (Args.hasArg(options::OPT_g_Flag) || hasDwarfNArg) {
DebugInfoKind = llvm::codegenoptions::FullDebugInfo;
} else {
DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
}
addDebugInfoKind(CmdArgs, DebugInfoKind);
- if (getDwarfNArg(Args)) {
+ if (hasDwarfNArg) {
const unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);
CmdArgs.push_back(
Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion)));
}
+ if (Args.hasArg(options::OPT_gsplit_dwarf) ||
+ Args.hasArg(options::OPT_gsplit_dwarf_EQ)) {
+ // FIXME: -gsplit-dwarf on AIX is currently unimplemented.
+ if (TC.getTriple().isOSAIX()) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Args.getLastArg(options::OPT_gsplit_dwarf)->getSpelling()
+ << TC.getTriple().str();
+ return;
+ }
+ if (DebugInfoKind == llvm::codegenoptions::NoDebugInfo)
+ return;
+
+ Arg *SplitDWARFArg;
+ DwarfFissionKind DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg);
+
+ if (DwarfFission == DwarfFissionKind::None ||
+ !checkDebugInfoOption(SplitDWARFArg, Args, D, TC))
+ return;
+
+ if (!TC.getTriple().isOSBinFormatELF() &&
+ !TC.getTriple().isOSBinFormatWasm() &&
+ !TC.getTriple().isOSBinFormatCOFF())
+ return;
+
+ if (!isa<AssembleJobAction>(JA) && !isa<CompileJobAction>(JA) &&
+ isa<BackendJobAction>(JA))
+ return;
+
+ const char *SplitDWARFOut = SplitDebugName(JA, Args, Input, Output);
+ CmdArgs.push_back("-split-dwarf-file");
+ CmdArgs.push_back(SplitDWARFOut);
+ if (DwarfFission == DwarfFissionKind::Split) {
+ CmdArgs.push_back("-split-dwarf-output");
+ CmdArgs.push_back(SplitDWARFOut);
+ }
+ }
}
void Flang::addCodegenOptions(const ArgList &Args,
@@ -936,8 +977,8 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
if (willEmitRemarks(Args))
renderRemarksOptions(Args, CmdArgs, Input);
- // Add other compile options
- addOtherOptions(Args, CmdArgs);
+ // Add debug compile options
+ addDebugOptions(Args, JA, Output, Input, CmdArgs);
// Disable all warnings
// TODO: Handle interactions between -w, -pedantic, -Wall, -WOption
diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h
index 98167e1b75e15..c0837b80c032e 100644
--- a/clang/lib/Driver/ToolChains/Flang.h
+++ b/clang/lib/Driver/ToolChains/Flang.h
@@ -125,12 +125,16 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
void addCodegenOptions(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- /// Extract other compilation options from the driver arguments and add them
+ /// Extract debug compilation options from the driver arguments and add them
/// to the command arguments.
///
/// \param [in] Args The list of input driver arguments
+ /// \param [in] JA The job action
+ /// \param [in] Output The output information on the current file output
+ /// \param [in] Input The input information on the current file input
/// \param [out] CmdArgs The list of output command arguments
- void addOtherOptions(const llvm::opt::ArgList &Args,
+ void addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA,
+ const InputInfo &Output, const InputInfo &Input,
llvm::opt::ArgStringList &CmdArgs) const;
public:
diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h
index df6063cc90340..3dca169d43b39 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -168,6 +168,13 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// by -fprofile-sample-use or -fprofile-instr-use.
std::string ProfileRemappingFile;
+ /// The name for the split debug info file used for the DW_AT_[GNU_]dwo_name
+ /// attribute in the skeleton CU.
+ std::string SplitDwarfFile;
+
+ /// Output filename for the split debug info, not used in the skeleton CU.
+ std::string SplitDwarfOutput;
+
/// Check if Clang profile instrumenation is on.
bool hasProfileClangInstr() const {
return getProfileInstr() == llvm::driver::ProfileClangInstr;
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 09b51730d6216..81610edee36fb 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -160,6 +160,12 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
opts.DwarfVersion =
getLastArgIntValue(args, clang::driver::options::OPT_dwarf_version_EQ,
/*Default=*/0, diags);
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_split_dwarf_file))
+ opts.SplitDwarfFile = a->getValue();
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_split_dwarf_output))
+ opts.SplitDwarfOutput = a->getValue();
}
return true;
}
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index c3c53d51015a2..867797ff1efdb 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -898,7 +898,19 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags,
llvm::CodeGenFileType cgft = (act == BackendActionTy::Backend_EmitAssembly)
? llvm::CodeGenFileType::AssemblyFile
: llvm::CodeGenFileType::ObjectFile;
- if (tm.addPassesToEmitFile(codeGenPasses, os, nullptr, cgft)) {
+ std::unique_ptr<llvm::ToolOutputFile> DwoOS;
+ if (!codeGenOpts.SplitDwarfOutput.empty()) {
+ std::error_code EC;
+ DwoOS = std::make_unique<llvm::ToolOutputFile>(codeGenOpts.SplitDwarfOutput,
+ EC, llvm::sys::fs::OF_None);
+ if (EC) {
+ diags.Report(clang::diag::err_fe_unable_to_open_output)
+ << codeGenOpts.SplitDwarfOutput << EC.message();
+ return;
+ }
+ }
+ if (tm.addPassesToEmitFile(codeGenPasses, os, DwoOS ? &DwoOS->os() : nullptr,
+ cgft)) {
unsigned diagID =
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
"emission of this file type is not supported");
@@ -909,6 +921,9 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags,
// Run the passes
codeGenPasses.run(llvmModule);
+ if (DwoOS)
+ DwoOS->keep();
+
// Cleanup
delete tlii;
}
@@ -1324,6 +1339,7 @@ void CodeGenAction::executeAction() {
llvm::TargetMachine &targetMachine = ci.getTargetMachine();
targetMachine.Options.MCOptions.AsmVerbose = targetOpts.asmVerbose;
+ targetMachine.Options.MCOptions.SplitDwarfFile = codeGenOpts.SplitDwarfFile;
const llvm::Triple &theTriple = targetMachine.getTargetTriple();
diff --git a/flang/test/Driver/split-debug.f90 b/flang/test/Driver/split-debug.f90
new file mode 100644
index 0000000000000..a63024328d807
--- /dev/null
+++ b/flang/test/Driver/split-debug.f90
@@ -0,0 +1,43 @@
+! Test -gsplit-dwarf and -gsplit-dwarf={split,single}.
+
+! RUN: %flang -### -c -target x86_64 -g -gsplit-dwarf %s 2>&1 | FileCheck %s --check-prefixes=SPLIT
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefixes=SPLIT
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf=split -g %s 2>&1 | FileCheck %s --check-prefixes=SPLIT
+
+! SPLIT: "-split-dwarf-file" "split-debug.dwo" "-split-dwarf-output" "split-debug.dwo"
+
+! -gsplit-dwarf is a no-op on a non-ELF platform.
+! RUN: %flang -### -c -target x86_64-apple-darwin -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=DARWIN
+! DARWIN-NOT: "-split-dwarf
+
+
+! -gno-split-dwarf disables debug fission.
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf -g -gno-split-dwarf %s 2>&1 | FileCheck %s --check-prefix=NOSPLIT
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf=single -g -gno-split-dwarf %s 2>&1 | FileCheck %s --check-prefix=NOSPLIT
+! RUN: %flang -### -c -target x86_64 -gno-split-dwarf -g -gsplit-dwarf %s 2>&1 | FileCheck %s --check-prefixes=SPLIT
+
+! NOSPLIT-NOT: "-split-dwarf
+
+! Test -gsplit-dwarf=single.
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf=single -g %s 2>&1 | FileCheck %s --check-prefix=SINGLE
+
+! SINGLE: "-split-dwarf-file" "split-debug.o"
+! SINGLE-NOT: "-split-dwarf-output"
+
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf=single -g -o %tfoo.o %s 2>&1 | FileCheck %s --check-prefix=SINGLE_WITH_FILENAME
+! SINGLE_WITH_FILENAME: "-split-dwarf-file" "{{.*}}foo.o"
+! SINGLE_WITH_FILENAME-NOT: "-split-dwarf-output"
+
+
+! Invoke objcopy if not using the integrated assembler.
+! RUN: %flang -### -c -target x86_64-unknown-linux-gnu -fno-integrated-as -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=OBJCOPY
+! OBJCOPY: objcopy{{(.exe)?}}" "--extract-dwo"
+! OBJCOPY-NEXT: objcopy{{(.exe)?}}" "--strip-dwo"
+
+! RUN: not %flang -target powerpc-ibm-aix -gdwarf-4 -gsplit-dwarf %s 2>&1 \
+! RUN: | FileCheck %s --check-prefix=UNSUP_OPT_AIX
+! RUN: not %flang -target powerpc64-ibm-aix -gdwarf-4 -gsplit-dwarf %s 2>&1 \
+! RUN: | FileCheck %s --check-prefix=UNSUP_OPT_AIX64
+
+// UNSUP_OPT_AIX: error: unsupported option '-gsplit-dwarf' for target 'powerpc-ibm-aix'
+// UNSUP_OPT_AIX64: error: unsupported option '-gsplit-dwarf' for target 'powerpc64-ibm-aix'
diff --git a/flang/test/Integration/debug-split-dwarf.f90 b/flang/test/Integration/debug-split-dwarf.f90
new file mode 100644
index 0000000000000..60373efddc358
--- /dev/null
+++ b/flang/test/Integration/debug-split-dwarf.f90
@@ -0,0 +1,21 @@
+! REQUIRES: x86-registered-target
+
+! Testing to ensure that setting only -split-dwarf-file allows to place
+! .dwo sections into regular output object.
+! RUN: %flang_fc1 -debug-info-kind=standalone -triple x86_64-unknown-linux \
+! RUN: -split-dwarf-file %t.o -emit-obj -o %t.o %s
+! RUN: llvm-readobj -S %t.o | FileCheck --check-prefix=DWO %s
+
+! Testing to ensure that setting both -split-dwarf-file and -split-dwarf-output
+! does not place .dwo sections into regular output object but in a separate
+! file.
+! RUN: %flang_fc1 -debug-info-kind=standalone -triple x86_64-unknown-linux \
+! RUN: -split-dwarf-file %t.dwo -split-dwarf-output %t.dwo -emit-obj -o %t.o %s
+! RUN: llvm-readobj -S %t.dwo | FileCheck --check-prefix=DWO %s
+! RUN: llvm-readobj -S %t.o ...
[truncated]
|
@llvm/pr-subscribers-flang-driver Author: Abid Qadeer (abidh) ChangesThis 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 Clang also set the Patch is 20.10 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/160540.diff 12 Files Affected:
diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h
index 1464ce4e1b31b..40ae40665b040 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -105,6 +105,16 @@ unsigned DwarfVersionNum(StringRef ArgValue);
const llvm::opt::Arg *getDwarfNArg(const llvm::opt::ArgList &Args);
unsigned getDwarfVersion(const ToolChain &TC, const llvm::opt::ArgList &Args);
+enum class DwarfFissionKind { None, Split, Single };
+
+DwarfFissionKind getDebugFissionKind(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::Arg *&Arg);
+
+bool checkDebugInfoOption(const llvm::opt::Arg *A,
+ const llvm::opt::ArgList &Args, const Driver &D,
+ const ToolChain &TC);
+
void AddAssemblerKPIC(const ToolChain &ToolChain,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 16e1c396fedbe..61fd0fa3794ee 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4754,13 +4754,13 @@ defm column_info : BoolOption<"g", "column-info",
PosFlag<SetTrue>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>,
Group<g_flags_Group>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>,
- Visibility<[ClangOption, CLOption, DXCOption]>;
+ Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;
def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_Group>,
- Visibility<[ClangOption, CLOption, DXCOption]>,
+ Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
HelpText<"Set DWARF fission mode">,
Values<"split,single">;
def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group<g_flags_Group>,
- Visibility<[ClangOption, CLOption, DXCOption]>;
+ Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;
def gtemplate_alias : Flag<["-"], "gtemplate-alias">, Group<g_flags_Group>, Visibility<[ClangOption, CC1Option]>;
def gno_template_alias : Flag<["-"], "gno-template-alias">, Group<g_flags_Group>, Visibility<[ClangOption]>;
def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group<g_flags_Group>;
@@ -8405,7 +8405,7 @@ def main_file_name : Separate<["-"], "main-file-name">,
MarshallingInfoString<CodeGenOpts<"MainFileName">>;
def split_dwarf_output : Separate<["-"], "split-dwarf-output">,
HelpText<"File name to use for split dwarf debug info output">,
- Visibility<[CC1Option, CC1AsOption]>,
+ Visibility<[CC1Option, CC1AsOption, FC1Option]>,
MarshallingInfoString<CodeGenOpts<"SplitDwarfOutput">>;
let Visibility = [CC1Option, FC1Option] in {
@@ -8437,6 +8437,10 @@ def dependent_lib : Joined<["--"], "dependent-lib=">,
HelpText<"Add dependent library">,
MarshallingInfoStringVector<CodeGenOpts<"DependentLibraries">>;
+def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
+ HelpText<"Name of the split dwarf debug info file to encode in the object file">,
+ MarshallingInfoString<CodeGenOpts<"SplitDwarfFile">>;
+
} // let Visibility = [CC1Option, FC1Option]
let Visibility = [CC1Option] in {
@@ -8447,9 +8451,6 @@ def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">,
HelpText<"Assume all functions with C linkage do not unwind">,
MarshallingInfoFlag<LangOpts<"ExternCNoUnwind">>;
-def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
- HelpText<"Name of the split dwarf debug info file to encode in the object file">,
- MarshallingInfoString<CodeGenOpts<"SplitDwarfFile">>;
def fno_wchar : Flag<["-"], "fno-wchar">,
HelpText<"Disable C++ builtin type wchar_t">,
MarshallingInfoNegativeFlag<LangOpts<"WChar">, cplusplus.KeyPath>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index e7aabee273a34..43cf8f54e272e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -695,16 +695,6 @@ RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
}
}
-static bool checkDebugInfoOption(const Arg *A, const ArgList &Args,
- const Driver &D, const ToolChain &TC) {
- assert(A && "Expected non-nullptr argument.");
- if (TC.supportsDebugInfoOption(A))
- return true;
- D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
- << A->getAsString(Args) << TC.getTripleString();
- return false;
-}
-
static void RenderDebugInfoCompressionArgs(const ArgList &Args,
ArgStringList &CmdArgs,
const Driver &D,
@@ -4327,27 +4317,6 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
Args.addLastArg(CmdArgs, options::OPT_warning_suppression_mappings_EQ);
}
-DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
- const ArgList &Args, Arg *&Arg) {
- Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
- options::OPT_gno_split_dwarf);
- if (!Arg || Arg->getOption().matches(options::OPT_gno_split_dwarf))
- return DwarfFissionKind::None;
-
- if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
- return DwarfFissionKind::Split;
-
- StringRef Value = Arg->getValue();
- if (Value == "split")
- return DwarfFissionKind::Split;
- if (Value == "single")
- return DwarfFissionKind::Single;
-
- D.Diag(diag::err_drv_unsupported_option_argument)
- << Arg->getSpelling() << Arg->getValue();
- return DwarfFissionKind::None;
-}
-
static void renderDwarfFormat(const Driver &D, const llvm::Triple &T,
const ArgList &Args, ArgStringList &CmdArgs,
unsigned DwarfVersion) {
diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h
index 18f6c5ed06a59..c22789591e00a 100644
--- a/clang/lib/Driver/ToolChains/Clang.h
+++ b/clang/lib/Driver/ToolChains/Clang.h
@@ -187,12 +187,6 @@ class LLVM_LIBRARY_VISIBILITY LinkerWrapper final : public Tool {
const char *LinkingOutput) const override;
};
-enum class DwarfFissionKind { None, Split, Single };
-
-DwarfFissionKind getDebugFissionKind(const Driver &D,
- const llvm::opt::ArgList &Args,
- llvm::opt::Arg *&Arg);
-
// Calculate the output path of the module file when compiling a module unit
// with the `-fmodule-output` option or `-fmodule-output=` option specified.
// The behavior is:
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 08cd98fd04df0..4902c2f3c0cbe 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -2270,6 +2270,37 @@ unsigned tools::getDwarfVersion(const ToolChain &TC,
return DwarfVersion;
}
+DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
+ const ArgList &Args, Arg *&Arg) {
+ Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
+ options::OPT_gno_split_dwarf);
+ if (!Arg || Arg->getOption().matches(options::OPT_gno_split_dwarf))
+ return DwarfFissionKind::None;
+
+ if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
+ return DwarfFissionKind::Split;
+
+ StringRef Value = Arg->getValue();
+ if (Value == "split")
+ return DwarfFissionKind::Split;
+ if (Value == "single")
+ return DwarfFissionKind::Single;
+
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getSpelling() << Arg->getValue();
+ return DwarfFissionKind::None;
+}
+
+bool tools::checkDebugInfoOption(const Arg *A, const ArgList &Args,
+ const Driver &D, const ToolChain &TC) {
+ assert(A && "Expected non-nullptr argument.");
+ if (TC.supportsDebugInfoOption(A))
+ return true;
+ D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
+ << A->getAsString(Args) << TC.getTripleString();
+ return false;
+}
+
void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
ArgStringList &CmdArgs) {
llvm::Reloc::Model RelocationModel;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 6fc372eb75eb7..3e8444c151f36 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -120,7 +120,11 @@ static bool shouldLoopVersion(const ArgList &Args) {
return false;
}
-void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
+void Flang::addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA,
+ const InputInfo &Output, const InputInfo &Input,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ const auto &TC = getToolChain();
+ const Driver &D = TC.getDriver();
Args.addAllArgs(CmdArgs,
{options::OPT_module_dir, options::OPT_fdebug_module_writer,
options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
@@ -131,20 +135,57 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
options::OPT_finstrument_functions});
llvm::codegenoptions::DebugInfoKind DebugInfoKind;
+ bool hasDwarfNArg = getDwarfNArg(Args) != nullptr;
if (Args.hasArg(options::OPT_gN_Group)) {
Arg *gNArg = Args.getLastArg(options::OPT_gN_Group);
DebugInfoKind = debugLevelToInfoKind(*gNArg);
- } else if (Args.hasArg(options::OPT_g_Group)) {
+ } else if (Args.hasArg(options::OPT_g_Flag) || hasDwarfNArg) {
DebugInfoKind = llvm::codegenoptions::FullDebugInfo;
} else {
DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
}
addDebugInfoKind(CmdArgs, DebugInfoKind);
- if (getDwarfNArg(Args)) {
+ if (hasDwarfNArg) {
const unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);
CmdArgs.push_back(
Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion)));
}
+ if (Args.hasArg(options::OPT_gsplit_dwarf) ||
+ Args.hasArg(options::OPT_gsplit_dwarf_EQ)) {
+ // FIXME: -gsplit-dwarf on AIX is currently unimplemented.
+ if (TC.getTriple().isOSAIX()) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Args.getLastArg(options::OPT_gsplit_dwarf)->getSpelling()
+ << TC.getTriple().str();
+ return;
+ }
+ if (DebugInfoKind == llvm::codegenoptions::NoDebugInfo)
+ return;
+
+ Arg *SplitDWARFArg;
+ DwarfFissionKind DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg);
+
+ if (DwarfFission == DwarfFissionKind::None ||
+ !checkDebugInfoOption(SplitDWARFArg, Args, D, TC))
+ return;
+
+ if (!TC.getTriple().isOSBinFormatELF() &&
+ !TC.getTriple().isOSBinFormatWasm() &&
+ !TC.getTriple().isOSBinFormatCOFF())
+ return;
+
+ if (!isa<AssembleJobAction>(JA) && !isa<CompileJobAction>(JA) &&
+ isa<BackendJobAction>(JA))
+ return;
+
+ const char *SplitDWARFOut = SplitDebugName(JA, Args, Input, Output);
+ CmdArgs.push_back("-split-dwarf-file");
+ CmdArgs.push_back(SplitDWARFOut);
+ if (DwarfFission == DwarfFissionKind::Split) {
+ CmdArgs.push_back("-split-dwarf-output");
+ CmdArgs.push_back(SplitDWARFOut);
+ }
+ }
}
void Flang::addCodegenOptions(const ArgList &Args,
@@ -936,8 +977,8 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
if (willEmitRemarks(Args))
renderRemarksOptions(Args, CmdArgs, Input);
- // Add other compile options
- addOtherOptions(Args, CmdArgs);
+ // Add debug compile options
+ addDebugOptions(Args, JA, Output, Input, CmdArgs);
// Disable all warnings
// TODO: Handle interactions between -w, -pedantic, -Wall, -WOption
diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h
index 98167e1b75e15..c0837b80c032e 100644
--- a/clang/lib/Driver/ToolChains/Flang.h
+++ b/clang/lib/Driver/ToolChains/Flang.h
@@ -125,12 +125,16 @@ class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
void addCodegenOptions(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
- /// Extract other compilation options from the driver arguments and add them
+ /// Extract debug compilation options from the driver arguments and add them
/// to the command arguments.
///
/// \param [in] Args The list of input driver arguments
+ /// \param [in] JA The job action
+ /// \param [in] Output The output information on the current file output
+ /// \param [in] Input The input information on the current file input
/// \param [out] CmdArgs The list of output command arguments
- void addOtherOptions(const llvm::opt::ArgList &Args,
+ void addDebugOptions(const llvm::opt::ArgList &Args, const JobAction &JA,
+ const InputInfo &Output, const InputInfo &Input,
llvm::opt::ArgStringList &CmdArgs) const;
public:
diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h
index df6063cc90340..3dca169d43b39 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -168,6 +168,13 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// by -fprofile-sample-use or -fprofile-instr-use.
std::string ProfileRemappingFile;
+ /// The name for the split debug info file used for the DW_AT_[GNU_]dwo_name
+ /// attribute in the skeleton CU.
+ std::string SplitDwarfFile;
+
+ /// Output filename for the split debug info, not used in the skeleton CU.
+ std::string SplitDwarfOutput;
+
/// Check if Clang profile instrumenation is on.
bool hasProfileClangInstr() const {
return getProfileInstr() == llvm::driver::ProfileClangInstr;
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 09b51730d6216..81610edee36fb 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -160,6 +160,12 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
opts.DwarfVersion =
getLastArgIntValue(args, clang::driver::options::OPT_dwarf_version_EQ,
/*Default=*/0, diags);
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_split_dwarf_file))
+ opts.SplitDwarfFile = a->getValue();
+ if (const llvm::opt::Arg *a =
+ args.getLastArg(clang::driver::options::OPT_split_dwarf_output))
+ opts.SplitDwarfOutput = a->getValue();
}
return true;
}
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index c3c53d51015a2..867797ff1efdb 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -898,7 +898,19 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags,
llvm::CodeGenFileType cgft = (act == BackendActionTy::Backend_EmitAssembly)
? llvm::CodeGenFileType::AssemblyFile
: llvm::CodeGenFileType::ObjectFile;
- if (tm.addPassesToEmitFile(codeGenPasses, os, nullptr, cgft)) {
+ std::unique_ptr<llvm::ToolOutputFile> DwoOS;
+ if (!codeGenOpts.SplitDwarfOutput.empty()) {
+ std::error_code EC;
+ DwoOS = std::make_unique<llvm::ToolOutputFile>(codeGenOpts.SplitDwarfOutput,
+ EC, llvm::sys::fs::OF_None);
+ if (EC) {
+ diags.Report(clang::diag::err_fe_unable_to_open_output)
+ << codeGenOpts.SplitDwarfOutput << EC.message();
+ return;
+ }
+ }
+ if (tm.addPassesToEmitFile(codeGenPasses, os, DwoOS ? &DwoOS->os() : nullptr,
+ cgft)) {
unsigned diagID =
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
"emission of this file type is not supported");
@@ -909,6 +921,9 @@ static void generateMachineCodeOrAssemblyImpl(clang::DiagnosticsEngine &diags,
// Run the passes
codeGenPasses.run(llvmModule);
+ if (DwoOS)
+ DwoOS->keep();
+
// Cleanup
delete tlii;
}
@@ -1324,6 +1339,7 @@ void CodeGenAction::executeAction() {
llvm::TargetMachine &targetMachine = ci.getTargetMachine();
targetMachine.Options.MCOptions.AsmVerbose = targetOpts.asmVerbose;
+ targetMachine.Options.MCOptions.SplitDwarfFile = codeGenOpts.SplitDwarfFile;
const llvm::Triple &theTriple = targetMachine.getTargetTriple();
diff --git a/flang/test/Driver/split-debug.f90 b/flang/test/Driver/split-debug.f90
new file mode 100644
index 0000000000000..a63024328d807
--- /dev/null
+++ b/flang/test/Driver/split-debug.f90
@@ -0,0 +1,43 @@
+! Test -gsplit-dwarf and -gsplit-dwarf={split,single}.
+
+! RUN: %flang -### -c -target x86_64 -g -gsplit-dwarf %s 2>&1 | FileCheck %s --check-prefixes=SPLIT
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefixes=SPLIT
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf=split -g %s 2>&1 | FileCheck %s --check-prefixes=SPLIT
+
+! SPLIT: "-split-dwarf-file" "split-debug.dwo" "-split-dwarf-output" "split-debug.dwo"
+
+! -gsplit-dwarf is a no-op on a non-ELF platform.
+! RUN: %flang -### -c -target x86_64-apple-darwin -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=DARWIN
+! DARWIN-NOT: "-split-dwarf
+
+
+! -gno-split-dwarf disables debug fission.
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf -g -gno-split-dwarf %s 2>&1 | FileCheck %s --check-prefix=NOSPLIT
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf=single -g -gno-split-dwarf %s 2>&1 | FileCheck %s --check-prefix=NOSPLIT
+! RUN: %flang -### -c -target x86_64 -gno-split-dwarf -g -gsplit-dwarf %s 2>&1 | FileCheck %s --check-prefixes=SPLIT
+
+! NOSPLIT-NOT: "-split-dwarf
+
+! Test -gsplit-dwarf=single.
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf=single -g %s 2>&1 | FileCheck %s --check-prefix=SINGLE
+
+! SINGLE: "-split-dwarf-file" "split-debug.o"
+! SINGLE-NOT: "-split-dwarf-output"
+
+! RUN: %flang -### -c -target x86_64 -gsplit-dwarf=single -g -o %tfoo.o %s 2>&1 | FileCheck %s --check-prefix=SINGLE_WITH_FILENAME
+! SINGLE_WITH_FILENAME: "-split-dwarf-file" "{{.*}}foo.o"
+! SINGLE_WITH_FILENAME-NOT: "-split-dwarf-output"
+
+
+! Invoke objcopy if not using the integrated assembler.
+! RUN: %flang -### -c -target x86_64-unknown-linux-gnu -fno-integrated-as -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=OBJCOPY
+! OBJCOPY: objcopy{{(.exe)?}}" "--extract-dwo"
+! OBJCOPY-NEXT: objcopy{{(.exe)?}}" "--strip-dwo"
+
+! RUN: not %flang -target powerpc-ibm-aix -gdwarf-4 -gsplit-dwarf %s 2>&1 \
+! RUN: | FileCheck %s --check-prefix=UNSUP_OPT_AIX
+! RUN: not %flang -target powerpc64-ibm-aix -gdwarf-4 -gsplit-dwarf %s 2>&1 \
+! RUN: | FileCheck %s --check-prefix=UNSUP_OPT_AIX64
+
+// UNSUP_OPT_AIX: error: unsupported option '-gsplit-dwarf' for target 'powerpc-ibm-aix'
+// UNSUP_OPT_AIX64: error: unsupported option '-gsplit-dwarf' for target 'powerpc64-ibm-aix'
diff --git a/flang/test/Integration/debug-split-dwarf.f90 b/flang/test/Integration/debug-split-dwarf.f90
new file mode 100644
index 0000000000000..60373efddc358
--- /dev/null
+++ b/flang/test/Integration/debug-split-dwarf.f90
@@ -0,0 +1,21 @@
+! REQUIRES: x86-registered-target
+
+! Testing to ensure that setting only -split-dwarf-file allows to place
+! .dwo sections into regular output object.
+! RUN: %flang_fc1 -debug-info-kind=standalone -triple x86_64-unknown-linux \
+! RUN: -split-dwarf-file %t.o -emit-obj -o %t.o %s
+! RUN: llvm-readobj -S %t.o | FileCheck --check-prefix=DWO %s
+
+! Testing to ensure that setting both -split-dwarf-file and -split-dwarf-output
+! does not place .dwo sections into regular output object but in a separate
+! file.
+! RUN: %flang_fc1 -debug-info-kind=standalone -triple x86_64-unknown-linux \
+! RUN: -split-dwarf-file %t.dwo -split-dwarf-output %t.dwo -emit-obj -o %t.o %s
+! RUN: llvm-readobj -S %t.dwo | FileCheck --check-prefix=DWO %s
+! RUN: llvm-readobj -S %t.o ...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Barring a couple of things, this looks good.
options::OPT_finstrument_functions}); | ||
|
||
llvm::codegenoptions::DebugInfoKind DebugInfoKind; | ||
bool hasDwarfNArg = getDwarfNArg(Args) != nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it necessary to compare to nullptr
here?
bool hasDwarfNArg = getDwarfNArg(Args) != nullptr; | |
bool hasDwarfNArg = getDwarfNArg(Args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not strictly necessary no because nullptr will be 0==false, but I think this is easier to understand at a glance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I added those for readability but have no strong opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine. I don't have any strong opinion either way. We can leave it as it is.
if (tm.addPassesToEmitFile(codeGenPasses, os, nullptr, cgft)) { | ||
std::unique_ptr<llvm::ToolOutputFile> DwoOS; | ||
if (!codeGenOpts.SplitDwarfOutput.empty()) { | ||
std::error_code EC; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be lowercase.
std::error_code EC; | |
std::error_code ec; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
? llvm::CodeGenFileType::AssemblyFile | ||
: llvm::CodeGenFileType::ObjectFile; | ||
if (tm.addPassesToEmitFile(codeGenPasses, os, nullptr, cgft)) { | ||
std::unique_ptr<llvm::ToolOutputFile> DwoOS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable naming in flang is stricter about use of camel-case than clang. Is the capital D here significant enough to justify an exception?
std::unique_ptr<llvm::ToolOutputFile> DwoOS; | |
std::unique_ptr<llvm::ToolOutputFile> dwoOS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
flang/test/Driver/split-debug.f90
Outdated
// UNSUP_OPT_AIX: error: unsupported option '-gsplit-dwarf' for target 'powerpc-ibm-aix' | ||
// UNSUP_OPT_AIX64: error: unsupported option '-gsplit-dwarf' for target 'powerpc64-ibm-aix' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be !
since this is a .f90 file?
// UNSUP_OPT_AIX: error: unsupported option '-gsplit-dwarf' for target 'powerpc-ibm-aix' | |
// UNSUP_OPT_AIX64: error: unsupported option '-gsplit-dwarf' for target 'powerpc64-ibm-aix' | |
! UNSUP_OPT_AIX: error: unsupported option '-gsplit-dwarf' for target 'powerpc-ibm-aix' | |
! UNSUP_OPT_AIX64: error: unsupported option '-gsplit-dwarf' for target 'powerpc64-ibm-aix' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching this. Fixed.
flang/test/Driver/split-debug.f90
Outdated
|
||
! Invoke objcopy if not using the integrated assembler. | ||
! RUN: %flang -### -c -target x86_64-unknown-linux-gnu -fno-integrated-as -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=OBJCOPY | ||
! OBJCOPY: objcopy{{(.exe)?}}" "--extract-dwo" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is --extract-dwo
required/guaranteed to be the first option that is passed to objcopy
? If so, this is fine, otherwise, it may be better to make this a bit more flexible and allow other options/arguments between objcopy
and --extract-dwo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to use OBJCOPY-SAME to be more flexible.
options::OPT_finstrument_functions}); | ||
|
||
llvm::codegenoptions::DebugInfoKind DebugInfoKind; | ||
bool hasDwarfNArg = getDwarfNArg(Args) != nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not strictly necessary no because nullptr will be 0==false, but I think this is easier to understand at a glance.
if (!TC.getTriple().isOSBinFormatELF() && | ||
!TC.getTriple().isOSBinFormatWasm() && | ||
!TC.getTriple().isOSBinFormatCOFF()) | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we should warn in cases where split dwarf cannot be done instead of silently ignoring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was sort of following what clang was doing here. But happy to add a warning if you think that is better course of action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following clang is good and I don't feel too strongly about it but the warnings won't be hard to add and our code structure already deviates from clang a bit anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added a warning and updated the test accordingly.
There was a problem hiding this 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.
Just a quick comment regarding the help text of the -split-dwarf-file
option. I know that this already existed, but since I didn't immediately understand what it meant, I wondered if it may be worth rephrasing it. We certainly don't have to.
MarshallingInfoStringVector<CodeGenOpts<"DependentLibraries">>; | ||
|
||
def split_dwarf_file : Separate<["-"], "split-dwarf-file">, | ||
HelpText<"Name of the split dwarf debug info file to encode in the object file">, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed this the first time around. I know that is already existed, but the wording is a bit unclear to me. Is the split dwarf debug info file actually encoded e.g. converted to base64 or something, into the object file? Is it "embedded" in the object file? Or is it something else?
It could be that I have misunderstood it. We don't have to do anything about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some background on how this works. Split dwarf means that part of the dwarf which don't need relocations are put in separate sections (generally they have .dwo in the name). These sections could be put in the same object file (-gsplit-dwarf=single) with rest of the sections or in separate file (-gslit-dwarf=split).
This help string could certainly be improved. I will try to do that in a separate PR as it will need broader agreement on the wording.
options::OPT_finstrument_functions}); | ||
|
||
llvm::codegenoptions::DebugInfoKind DebugInfoKind; | ||
bool hasDwarfNArg = getDwarfNArg(Args) != nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine. I don't have any strong opinion either way. We can leave it as it is.
This PR builds on llvm#160540 and allows us to set the splitDebugFilename field in DICompileUnitAttr. I saw some spurious whitespace in a test that I have cleaned up.
…ileUnitAttr. (#161214) This PR builds on llvm/llvm-project#160540 and allows us to set the `splitDebugFilename` field in `DICompileUnitAttr`. The changes are mostly mechanical. I saw some spurious white space in a test that I have cleaned up.
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.
llvm#161214) This PR builds on llvm#160540 and allows us to set the `splitDebugFilename` field in `DICompileUnitAttr`. The changes are mostly mechanical. I saw some spurious white space in a test that I have cleaned up.
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 toaddDebugOptions
to better reflect its purpose.Clang also set the
splitDebugFilename
field of theDICompileUnit
in the IR when this option is present. That part is currently missing from this patch and will come in a follow-up PR.