diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5483,6 +5483,7 @@ let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { +def dumpdir : Separate<["-"], "dumpdir">; def debug_info_macro : Flag<["-"], "debug-info-macro">, HelpText<"Emit macro debug information">, MarshallingInfoFlag>; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3875,6 +3875,13 @@ !Args.getLastArgValue(options::OPT_fuse_ld_EQ) .equals_insensitive("lld")) Diag(clang::diag::err_drv_lto_without_lld); + + // Prefer deriving auxiliary file names from the link output name. + Arg *Arg = Args.MakeSeparateArg( + nullptr, getOpts().getOption(options::OPT_dumpdir), + Args.MakeArgString(Args.getLastArgValue(options::OPT_o, "a") + "-")); + Arg->claim(); + Args.append(Arg); } if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) { 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 @@ -4837,6 +4837,8 @@ } } + Args.AddLastArg(CmdArgs, options::OPT_dumpdir); + if (const Arg *A = Args.getLastArg(options::OPT_fthinlto_index_EQ)) { if (!types::isLLVMIR(Input.getType())) D.Diag(diag::err_drv_arg_requires_bitcode_input) << A->getAsString(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 @@ -1248,23 +1248,22 @@ if (StringRef(A->getValue()) == "single") return Args.MakeArgString(Output.getFilename()); + SmallString<128> T; + if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) + T = A->getValue(); + Arg *FinalOutput = Args.getLastArg(options::OPT_o); if (FinalOutput && Args.hasArg(options::OPT_c)) { - SmallString<128> T(FinalOutput->getValue()); + T = FinalOutput->getValue(); llvm::sys::path::remove_filename(T); llvm::sys::path::append(T, llvm::sys::path::stem(FinalOutput->getValue())); AddPostfix(T); return Args.MakeArgString(T); - } else { - // Use the compilation dir. - Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, - options::OPT_fdebug_compilation_dir_EQ); - SmallString<128> T(A ? A->getValue() : ""); - SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput())); - AddPostfix(F); - T += F; - return Args.MakeArgString(T); } + + T += llvm::sys::path::stem(Input.getBaseInput()); + AddPostfix(T); + return Args.MakeArgString(T); } void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, diff --git a/clang/test/Driver/hip-gsplit-dwarf-options.hip b/clang/test/Driver/hip-gsplit-dwarf-options.hip --- a/clang/test/Driver/hip-gsplit-dwarf-options.hip +++ b/clang/test/Driver/hip-gsplit-dwarf-options.hip @@ -13,13 +13,17 @@ // RUN: %clang -### --target=x86_64-unknown-linux-gnu \ // RUN: --offload-arch=gfx906:xnack+ %s -nogpulib -nogpuinc \ // RUN: --offload-arch=gfx900 \ -// RUN: -ggdb -gsplit-dwarf 2>&1 | FileCheck %s +// RUN: -ggdb -gsplit-dwarf 2>&1 | FileCheck %s --check-prefix=LINK // RUN: %clang -### --target=x86_64-unknown-linux-gnu \ // RUN: -fgpu-rdc --offload-arch=gfx906:xnack+ %s -nogpulib -nogpuinc \ // RUN: --offload-arch=gfx900 \ -// RUN: -ggdb -gsplit-dwarf 2>&1 | FileCheck %s +// RUN: -ggdb -gsplit-dwarf 2>&1 | FileCheck %s --check-prefix=LINK // CHECK-DAG: {{".*clang.*".* "-target-cpu" "gfx906".* "-split-dwarf-output" "hip-gsplit-dwarf-options_gfx906:xnack\+.dwo"}} // CHECK-DAG: {{".*clang.*".* "-target-cpu" "gfx900".* "-split-dwarf-output" "hip-gsplit-dwarf-options_gfx900.dwo"}} // CHECK-DAG: {{".*clang.*".* "-target-cpu" "x86-64".* "-split-dwarf-output" "hip-gsplit-dwarf-options.dwo"}} + +// LINK-DAG: {{".*clang.*".* "-target-cpu" "gfx906".* "-split-dwarf-output" "a-hip-gsplit-dwarf-options_gfx906:xnack\+.dwo"}} +// LINK-DAG: {{".*clang.*".* "-target-cpu" "gfx900".* "-split-dwarf-output" "a-hip-gsplit-dwarf-options_gfx900.dwo"}} +// LINK-DAG: {{".*clang.*".* "-target-cpu" "x86-64".* "-split-dwarf-output" "a-hip-gsplit-dwarf-options.dwo"}} diff --git a/clang/test/Driver/split-debug.c b/clang/test/Driver/split-debug.c --- a/clang/test/Driver/split-debug.c +++ b/clang/test/Driver/split-debug.c @@ -9,6 +9,7 @@ // INLINE: "-fsplit-dwarf-inlining" // NOINLINE-NOT: "-fsplit-dwarf-inlining" +// SPLIT-NOT: "-dumpdir" // SPLIT: "-debug-info-kind=constructor" // SPLIT-SAME: "-ggnu-pubnames" // SPLIT-SAME: "-split-dwarf-file" "split-debug.dwo" "-split-dwarf-output" "split-debug.dwo" @@ -54,8 +55,15 @@ // SINGLE_WITH_FILENAME: "-split-dwarf-file" "{{.*}}foo.o" // SINGLE_WITH_FILENAME-NOT: "-split-dwarf-output" -/// Without -c, clang performs linking as well. The output is unchanged. -// RUN: %clang -### -target x86_64-unknown-linux-gnu -gsplit-dwarf -g %s -o ignore.d 2>&1 | FileCheck %s --check-prefix=SPLIT +/// If linking is the final phase, the .dwo filename is derived from -o (if specified) or "a". +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -gsplit-dwarf -g %s -o obj/out 2>&1 | FileCheck %s --check-prefix=SPLIT_LINK +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -gsplit-dwarf -g %s 2>&1 | FileCheck %s --check-prefix=SPLIT_LINK_A + +// SPLIT_LINK: "-dumpdir" "obj/out-" +// SPLIT_LINK: "-debug-info-kind=constructor" +// SPLIT_LINK-SAME: "-split-dwarf-file" "obj/out-split-debug.dwo" "-split-dwarf-output" "obj/out-split-debug.dwo" +// SPLIT_LINK_A: "-dumpdir" "a-" +// SPLIT_LINK_A-SAME: "-split-dwarf-file" "a-split-debug.dwo" "-split-dwarf-output" "a-split-debug.dwo" /// -fsplit-dwarf-inlining // RUN: %clang -### -c -target x86_64 -gsplit-dwarf=split -g -fsplit-dwarf-inlining %s 2>&1 | FileCheck %s --check-prefixes=INLINE,SPLIT