Skip to content

Commit

Permalink
[Clang] - Add '-gsplit-dwarf[=split,=single]' version for '-gsplit-dw…
Browse files Browse the repository at this point in the history
…arf' option.

The DWARF5 specification says(Appendix F.1):

"The sections that do not require relocation, however, can be
written to the relocatable object (.o) file but ignored by the
linker or they can be written to a separate DWARF object (.dwo)
file that need not be accessed by the linker."

The first part describes a single file split DWARF feature and there
is no way to trigger this behavior atm. 
Fortunately, no many changes are required to keep *.dwo sections
in a .o, the patch does that.

Differential revision: https://reviews.llvm.org/D52296

llvm-svn: 346837
  • Loading branch information
George Rimar committed Nov 14, 2018
1 parent 39e86fa commit 91829ee
Show file tree
Hide file tree
Showing 15 changed files with 130 additions and 26 deletions.
4 changes: 3 additions & 1 deletion clang/include/clang/Driver/CC1Options.td
Expand Up @@ -649,7 +649,9 @@ def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">,
HelpText<"Assume all functions with C linkage do not unwind">;
def enable_split_dwarf : Flag<["-"], "enable-split-dwarf">,
HelpText<"Use split dwarf/Fission">;
HelpText<"Use DWARF fission in 'split' mode">;
def enable_split_dwarf_EQ : Joined<["-"], "enable-split-dwarf=">,
HelpText<"Set DWARF fission mode to either 'split' or 'single'">, Values<"split,single">;
def fno_wchar : Flag<["-"], "fno-wchar">,
HelpText<"Disable C++ builtin type wchar_t">;
def fconstant_string_class : Separate<["-"], "fconstant-string-class">,
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -1840,6 +1840,9 @@ def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_Group>,
HelpText<"Set DWARF fission mode to either 'split' or 'single'">,
Values<"split,single">;
def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gno_gnu_pubnames : Flag<["-"], "gno-gnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gpubnames : Flag<["-"], "gpubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Frontend/CodeGenOptions.def
Expand Up @@ -252,7 +252,9 @@ CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain
CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
///< contain explicit imports for
///< anonymous namespaces
CODEGENOPT(EnableSplitDwarf, 1, 0) ///< Whether to enable split DWARF

ENUM_CODEGENOPT(SplitDwarfMode, DwarfFissionKind, 2, NoFission) ///< DWARF fission mode to use.

CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the
///< skeleton CU to allow for symbolication
///< of inline stack frames without .dwo files.
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Frontend/CodeGenOptions.h
Expand Up @@ -71,6 +71,8 @@ class CodeGenOptions : public CodeGenOptionsBase {
LocalExecTLSModel
};

enum DwarfFissionKind { NoFission, SplitFileFission, SingleFileFission };

/// Clang versions with different platform ABI conformance.
enum class ClangABI {
/// Attempt to be ABI-compatible with code generated by Clang 3.8.x
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/CodeGen/BackendUtil.cpp
Expand Up @@ -468,7 +468,7 @@ static void initTargetOptions(llvm::TargetOptions &Options,
Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
Options.EmitAddrsig = CodeGenOpts.Addrsig;

if (CodeGenOpts.EnableSplitDwarf)
if (CodeGenOpts.getSplitDwarfMode() != CodeGenOptions::NoFission)
Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;
Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;
Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;
Expand Down Expand Up @@ -832,7 +832,8 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
break;

default:
if (!CodeGenOpts.SplitDwarfFile.empty()) {
if (!CodeGenOpts.SplitDwarfFile.empty() &&
(CodeGenOpts.getSplitDwarfMode() == CodeGenOptions::SplitFileFission)) {
DwoOS = openOutputFile(CodeGenOpts.SplitDwarfFile);
if (!DwoOS)
return;
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Expand Up @@ -581,8 +581,11 @@ void CGDebugInfo::CreateCompileUnit() {
CGOpts.EmitVersionIdentMetadata ? Producer : "",
LO.Optimize || CGOpts.PrepareForLTO || CGOpts.PrepareForThinLTO,
CGOpts.DwarfDebugFlags, RuntimeVers,
CGOpts.EnableSplitDwarf ? "" : CGOpts.SplitDwarfFile, EmissionKind,
0 /* DWOid */, CGOpts.SplitDwarfInlining, CGOpts.DebugInfoForProfiling,
(CGOpts.getSplitDwarfMode() != CodeGenOptions::NoFission)
? ""
: CGOpts.SplitDwarfFile,
EmissionKind, 0 /* DWOid */, CGOpts.SplitDwarfInlining,
CGOpts.DebugInfoForProfiling,
CGM.getTarget().getTriple().isNVPTX()
? llvm::DICompileUnit::DebugNameTableKind::None
: static_cast<llvm::DICompileUnit::DebugNameTableKind>(
Expand Down
61 changes: 46 additions & 15 deletions clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -2986,12 +2986,35 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
CmdArgs.push_back("-fno-spell-checking");
}

enum class DwarfFissionKind { None, Split, Single };

static DwarfFissionKind getDebugFissionKind(const Driver &D,
const ArgList &Args, Arg *&Arg) {
Arg =
Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ);
if (!Arg)
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->getOption().getName() << Arg->getValue();
return DwarfFissionKind::None;
}

static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
const llvm::Triple &T, const ArgList &Args,
bool EmitCodeView, bool IsWindowsMSVC,
ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind &DebugInfoKind,
const Arg *&SplitDWARFArg) {
DwarfFissionKind &DwarfFission) {
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
options::OPT_fno_debug_info_for_profiling, false) &&
checkDebugInfoOption(
Expand All @@ -3016,10 +3039,12 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,

Args.ClaimAllArgs(options::OPT_g_Group);

SplitDWARFArg = Args.getLastArg(options::OPT_gsplit_dwarf);
Arg* SplitDWARFArg;
DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg);

if (SplitDWARFArg && !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
SplitDWARFArg = nullptr;
if (DwarfFission != DwarfFissionKind::None &&
!checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
DwarfFission = DwarfFissionKind::None;
SplitDWARFInlining = false;
}

Expand All @@ -3036,13 +3061,13 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// composing split-dwarf and line-tables-only, so let those compose
// naturally in that case. And if you just turned off debug info,
// (-gsplit-dwarf -g0) - do that.
if (SplitDWARFArg) {
if (DwarfFission != DwarfFissionKind::None) {
if (A->getIndex() > SplitDWARFArg->getIndex()) {
if (DebugInfoKind == codegenoptions::NoDebugInfo ||
DebugInfoKind == codegenoptions::DebugDirectivesOnly ||
(DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
SplitDWARFInlining))
SplitDWARFArg = nullptr;
DwarfFission = DwarfFissionKind::None;
} else if (SplitDWARFInlining)
DebugInfoKind = codegenoptions::NoDebugInfo;
}
Expand Down Expand Up @@ -3130,10 +3155,14 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
if (!SplitDWARFInlining)
CmdArgs.push_back("-fno-split-dwarf-inlining");

if (SplitDWARFArg) {
if (DwarfFission != DwarfFissionKind::None) {
if (DebugInfoKind == codegenoptions::NoDebugInfo)
DebugInfoKind = codegenoptions::LimitedDebugInfo;
CmdArgs.push_back("-enable-split-dwarf");

if (DwarfFission == DwarfFissionKind::Single)
CmdArgs.push_back("-enable-split-dwarf=single");
else
CmdArgs.push_back("-enable-split-dwarf");
}
}

Expand Down Expand Up @@ -3178,7 +3207,8 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
const auto *PubnamesArg =
Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
options::OPT_gpubnames, options::OPT_gno_pubnames);
if (SplitDWARFArg || DebuggerTuning == llvm::DebuggerKind::LLDB ||
if (DwarfFission != DwarfFissionKind::None ||
DebuggerTuning == llvm::DebuggerKind::LLDB ||
(PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC)))
if (!PubnamesArg ||
(!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) &&
Expand Down Expand Up @@ -3887,20 +3917,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else
EmitCodeView = Args.hasArg(options::OPT_gcodeview);

const Arg *SplitDWARFArg = nullptr;
DwarfFissionKind DwarfFission;
RenderDebugOptions(TC, D, RawTriple, Args, EmitCodeView, IsWindowsMSVC,
CmdArgs, DebugInfoKind, SplitDWARFArg);
CmdArgs, DebugInfoKind, DwarfFission);

// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
bool SplitDWARF = SplitDWARFArg &&
bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) &&
(RawTriple.isOSLinux() || RawTriple.isOSFuchsia()) &&
(isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
isa<BackendJobAction>(JA));
const char *SplitDWARFOut;
if (SplitDWARF) {
CmdArgs.push_back("-split-dwarf-file");
SplitDWARFOut = SplitDebugName(Args, Input);
SplitDWARFOut = SplitDebugName(Args, Input, Output);
CmdArgs.push_back(SplitDWARFOut);
}

Expand Down Expand Up @@ -5863,10 +5893,11 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Output.getFilename());

const llvm::Triple &T = getToolChain().getTriple();
if (Args.hasArg(options::OPT_gsplit_dwarf) &&
Arg *A;
if ((getDebugFissionKind(D, Args, A) == DwarfFissionKind::Split) &&
(T.isOSLinux() || T.isOSFuchsia())) {
CmdArgs.push_back("-split-dwarf-file");
CmdArgs.push_back(SplitDebugName(Args, Input));
CmdArgs.push_back(SplitDebugName(Args, Input, Output));
}

assert(Input.isFilename() && "Invalid input.");
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.cpp
Expand Up @@ -808,7 +808,12 @@ bool tools::areOptimizationsEnabled(const ArgList &Args) {
return false;
}

const char *tools::SplitDebugName(const ArgList &Args, const InputInfo &Input) {
const char *tools::SplitDebugName(const ArgList &Args, const InputInfo &Input,
const InputInfo &Output) {
if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ))
if (StringRef(A->getValue()) == "single")
return Args.MakeArgString(Output.getFilename());

Arg *FinalOutput = Args.getLastArg(options::OPT_o);
if (FinalOutput && Args.hasArg(options::OPT_c)) {
SmallString<128> T(FinalOutput->getValue());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.h
Expand Up @@ -63,7 +63,7 @@ void AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
const Tool &T);

const char *SplitDebugName(const llvm::opt::ArgList &Args,
const InputInfo &Input);
const InputInfo &Input, const InputInfo &Output);

void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
const JobAction &JA, const llvm::opt::ArgList &Args,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Gnu.cpp
Expand Up @@ -817,7 +817,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
if (Args.hasArg(options::OPT_gsplit_dwarf) &&
getToolChain().getTriple().isOSLinux())
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
SplitDebugName(Args, Inputs[0]));
SplitDebugName(Args, Inputs[0], Output));
}

namespace {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/MinGW.cpp
Expand Up @@ -54,7 +54,7 @@ void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,

if (Args.hasArg(options::OPT_gsplit_dwarf))
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
SplitDebugName(Args, Inputs[0]));
SplitDebugName(Args, Inputs[0], Output));
}

void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
Expand Down
18 changes: 17 additions & 1 deletion clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -596,9 +596,25 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro);
Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std);
Opts.EnableSplitDwarf = Args.hasArg(OPT_enable_split_dwarf);
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining);

if (Arg *A =
Args.getLastArg(OPT_enable_split_dwarf, OPT_enable_split_dwarf_EQ)) {
if (A->getOption().matches(options::OPT_enable_split_dwarf)) {
Opts.setSplitDwarfMode(CodeGenOptions::SplitFileFission);
} else {
StringRef Name = A->getValue();
if (Name == "single")
Opts.setSplitDwarfMode(CodeGenOptions::SingleFileFission);
else if (Name == "split")
Opts.setSplitDwarfMode(CodeGenOptions::SplitFileFission);
else
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << Name;
}
}

Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import);
Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params);
Expand Down
17 changes: 17 additions & 0 deletions clang/test/CodeGen/split-debug-single-file.c
@@ -0,0 +1,17 @@
// REQUIRES: x86-registered-target

// Testing to ensure -enable-split-dwarf=single allows to place .dwo sections into regular output object.
// RUN: %clang_cc1 -debug-info-kind=limited -triple x86_64-unknown-linux \
// RUN: -enable-split-dwarf=single -split-dwarf-file %t.o -emit-obj -o %t.o %s
// RUN: llvm-objdump -section-headers %t.o | FileCheck --check-prefix=MODE-SINGLE %s
// MODE-SINGLE: .dwo

// Testing to ensure -enable-split-dwarf=split does not place .dwo sections into regular output object.
// RUN: %clang_cc1 -debug-info-kind=limited -triple x86_64-unknown-linux \
// RUN: -enable-split-dwarf=split -split-dwarf-file %t.o -emit-obj -o %t.o %s
// RUN: llvm-objdump -section-headers %t.o | FileCheck --check-prefix=MODE-SPLIT %s
// MODE-SPLIT-NOT: .dwo

int main (void) {
return 0;
}
15 changes: 15 additions & 0 deletions clang/test/Driver/split-debug.c
Expand Up @@ -5,6 +5,21 @@
//
// CHECK-ACTIONS: "-split-dwarf-file" "split-debug.dwo"

// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s
// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=split -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s

// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=single -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-ACTIONS-SINGLE-SPLIT < %t %s
//
// CHECK-ACTIONS-SINGLE-SPLIT: "-enable-split-dwarf=single"
// CHECK-ACTIONS-SINGLE-SPLIT: "-split-dwarf-file" "split-debug.o"

// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=single -c -### -o %tfoo.o %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-SINGLE-SPLIT-FILENAME < %t %s
//
// CHECK-SINGLE-SPLIT-FILENAME: "-split-dwarf-file" "{{.*}}foo.o"

// RUN: %clang -target x86_64-macosx -gsplit-dwarf -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Driver/split-debug.s
Expand Up @@ -5,6 +5,13 @@
//
// CHECK-ACTIONS: "-split-dwarf-file" "split-debug.dwo"

// Check we pass -split-dwarf-file to `as` if -gsplit-dwarf=split.
// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=split -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-ACTIONS < %t %s

// Check we do not pass any -split-dwarf* commands to `as` if -gsplit-dwarf=single.
// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf=single -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s

// RUN: %clang -target x86_64-macosx -gsplit-dwarf -c -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-NO-ACTIONS < %t %s
Expand Down

0 comments on commit 91829ee

Please sign in to comment.