diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1057,26 +1057,6 @@ RelaxDefault); } -// Extract the integer N from a string spelled "-dwarf-N", returning 0 -// on mismatch. The StringRef input (rather than an Arg) allows -// for use by the "-Xassembler" option parser. -static unsigned DwarfVersionNum(StringRef ArgValue) { - return llvm::StringSwitch(ArgValue) - .Case("-gdwarf-2", 2) - .Case("-gdwarf-3", 3) - .Case("-gdwarf-4", 4) - .Case("-gdwarf-5", 5) - .Default(0); -} - -// Find a DWARF format version option. -// This function is a complementary for DwarfVersionNum(). -static const Arg *getDwarfNArg(const ArgList &Args) { - return Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3, - options::OPT_gdwarf_4, options::OPT_gdwarf_5, - options::OPT_gdwarf); -} - static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs, codegenoptions::DebugInfoKind DebugInfoKind, unsigned DwarfVersion, @@ -4204,19 +4184,12 @@ } // If a -gdwarf argument appeared, remember it. - const Arg *GDwarfN = getDwarfNArg(Args); bool EmitDwarf = false; - if (GDwarfN) { - if (checkDebugInfoOption(GDwarfN, Args, D, TC)) - EmitDwarf = true; - else - GDwarfN = nullptr; - } + if (const Arg *A = getDwarfNArg(Args)) + EmitDwarf = checkDebugInfoOption(A, Args, D, TC); - if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) { - if (checkDebugInfoOption(A, Args, D, TC)) - EmitCodeView = true; - } + if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) + EmitCodeView = checkDebugInfoOption(A, Args, D, TC); // If the user asked for debug info but did not explicitly specify -gcodeview // or -gdwarf, ask the toolchain for the default format. @@ -4235,22 +4208,8 @@ unsigned RequestedDWARFVersion = 0; // DWARF version requested by the user unsigned EffectiveDWARFVersion = 0; // DWARF version TC can generate. It may // be lower than what the user wanted. - unsigned DefaultDWARFVersion = ParseDebugDefaultVersion(TC, Args); if (EmitDwarf) { - // Start with the platform default DWARF version - RequestedDWARFVersion = TC.GetDefaultDwarfVersion(); - assert(RequestedDWARFVersion && - "toolchain default DWARF version must be nonzero"); - - // If the user specified a default DWARF version, that takes precedence - // over the platform default. - if (DefaultDWARFVersion) - RequestedDWARFVersion = DefaultDWARFVersion; - - // Override with a user-specified DWARF version - if (GDwarfN) - if (auto ExplicitVersion = DwarfVersionNum(GDwarfN->getSpelling())) - RequestedDWARFVersion = ExplicitVersion; + RequestedDWARFVersion = getDwarfVersion(TC, Args); // Clamp effective DWARF version to the max supported by the toolchain. EffectiveDWARFVersion = std::min(RequestedDWARFVersion, TC.getMaxDwarfVersion()); @@ -7978,13 +7937,6 @@ WantDebug = !A->getOption().matches(options::OPT_g0) && !A->getOption().matches(options::OPT_ggdb0); - unsigned DwarfVersion = ParseDebugDefaultVersion(getToolChain(), Args); - if (const Arg *GDwarfN = getDwarfNArg(Args)) - DwarfVersion = DwarfVersionNum(GDwarfN->getSpelling()); - - if (DwarfVersion == 0) - DwarfVersion = getToolChain().GetDefaultDwarfVersion(); - codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo; // Add the -fdebug-compilation-dir flag if needed. @@ -8011,6 +7963,7 @@ // And pass along -I options Args.AddAllArgs(CmdArgs, options::OPT_I); } + const unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args); RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion, llvm::DebuggerKind::Default); renderDwarfFormat(D, Triple, Args, CmdArgs, DwarfVersion); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -14,6 +14,9 @@ #include "clang/Driver/Multilib.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" namespace clang { @@ -101,8 +104,14 @@ unsigned ParseFunctionAlignment(const ToolChain &TC, const llvm::opt::ArgList &Args); -unsigned ParseDebugDefaultVersion(const ToolChain &TC, - const llvm::opt::ArgList &Args); +// Extract the integer N from a string spelled "-dwarf-N", returning 0 +// on mismatch. The StringRef input (rather than an Arg) allows +// for use by the "-Xassembler" option parser. +unsigned DwarfVersionNum(StringRef ArgValue); +// Find a DWARF format version option. +// This function is a complementary for DwarfVersionNum(). +const llvm::opt::Arg *getDwarfNArg(const llvm::opt::ArgList &Args); +unsigned getDwarfVersion(const ToolChain &TC, const llvm::opt::ArgList &Args); void AddAssemblerKPIC(const ToolChain &ToolChain, const llvm::opt::ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1520,7 +1520,7 @@ return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value; } -unsigned tools::ParseDebugDefaultVersion(const ToolChain &TC, +static unsigned ParseDebugDefaultVersion(const ToolChain &TC, const ArgList &Args) { const Arg *A = Args.getLastArg(options::OPT_fdebug_default_version); @@ -1535,6 +1535,36 @@ return Value; } +unsigned tools::DwarfVersionNum(StringRef ArgValue) { + return llvm::StringSwitch(ArgValue) + .Case("-gdwarf-2", 2) + .Case("-gdwarf-3", 3) + .Case("-gdwarf-4", 4) + .Case("-gdwarf-5", 5) + .Default(0); +} + +const Arg *tools::getDwarfNArg(const ArgList &Args) { + return Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3, + options::OPT_gdwarf_4, options::OPT_gdwarf_5, + options::OPT_gdwarf); +} + +unsigned tools::getDwarfVersion(const ToolChain &TC, + const llvm::opt::ArgList &Args) { + unsigned DwarfVersion = ParseDebugDefaultVersion(TC, Args); + if (const Arg* GDwarfN = getDwarfNArg(Args)) + if (int N = DwarfVersionNum(GDwarfN->getSpelling())) + DwarfVersion = N; + if (DwarfVersion == 0) { + DwarfVersion = TC.GetDefaultDwarfVersion(); + assert(DwarfVersion && + "toolchain default DWARF version must be nonzero"); + } + return DwarfVersion; +} + + void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs) { llvm::Reloc::Model RelocationModel; diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -23,6 +23,7 @@ #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" +#include "llvm/ADT/Twine.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Path.h" @@ -969,10 +970,17 @@ for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); - if (Arg *A = Args.getLastArg(options::OPT_g_Flag, options::OPT_gN_Group)) - if (!A->getOption().matches(options::OPT_g0)) + if (Arg *A = Args.getLastArg(options::OPT_g_Flag, options::OPT_gN_Group, + options::OPT_gdwarf_2, options::OPT_gdwarf_3, options::OPT_gdwarf_4, + options::OPT_gdwarf_5, options::OPT_gdwarf)) + if (!A->getOption().matches(options::OPT_g0)) { Args.AddLastArg(CmdArgs, options::OPT_g_Flag); + unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args); + Twine DV = "-gdwarf-" + Twine(DwarfVersion); + CmdArgs.push_back(Args.MakeArgString(DV)); + } + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler)); C.addCommand(std::make_unique(JA, *this, diff --git a/clang/test/Driver/as-options.s b/clang/test/Driver/as-options.s --- a/clang/test/Driver/as-options.s +++ b/clang/test/Driver/as-options.s @@ -122,7 +122,33 @@ // RUN: FileCheck --check-prefix=DEBUG %s // RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -g0 -g %s -### 2>&1 | \ // RUN: FileCheck --check-prefix=DEBUG %s -// DEBUG: "-g" +// DEBUG: "-g" "-gdwarf-5" // RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -g -g0 %s -### 2>&1 | \ // RUN: FileCheck --check-prefix=NODEBUG %s +// RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -gdwarf-5 -g0 %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=NODEBUG %s // NODEBUG-NOT: "-g" +// NODEBUG-NOT: "-gdwarf- + +// Test that -gdwarf-* is passed through to GAS. +// TODO: test without -g +// RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -gdwarf-5 %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=GDWARF5 %s +// RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -gdwarf-4 %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=GDWARF4 %s +// RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -gdwarf-3 %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=GDWARF3 %s +// RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -gdwarf-2 %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=GDWARF2 %s +// RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -gdwarf %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=GDWARF5 %s + +// RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -gdwarf-5 %s -### 2>&1 | \ +// RUN: FileCheck --check-prefix=GDWARF5 %s +// RUN: %clang --target=aarch64-linux-gnu -fno-integrated-as -g \ +// RUN: -fdebug-default-version=2 %s -### 2>&1 | FileCheck --check-prefix=GDWARF2 %s + +// GDWARF5: "-gdwarf-5" +// GDWARF4: "-gdwarf-4" +// GDWARF3: "-gdwarf-3" +// GDWARF2: "-gdwarf-2"