diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index 3fd62d97930937..974e486a0082bc 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -118,11 +118,11 @@ void toolchains::PS5CPU::addSanitizerArgs(const ArgList &Args, CmdArgs.push_back(arg("SceThreadSanitizer_nosubmission_stub_weak")); } -void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { +void tools::PS4cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { auto &TC = static_cast(getToolChain()); const Driver &D = TC.getDriver(); ArgStringList CmdArgs; @@ -155,14 +155,120 @@ void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, const bool UseLTO = D.isUsingLTO(); const bool UseJMC = Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false); - const bool IsPS4 = TC.getTriple().isPS4(); - const char *PS4LTOArgs = ""; + const char *LTOArgs = ""; auto AddCodeGenFlag = [&](Twine Flag) { - if (IsPS4) - PS4LTOArgs = Args.MakeArgString(Twine(PS4LTOArgs) + " " + Flag); + LTOArgs = Args.MakeArgString(Twine(LTOArgs) + " " + Flag); + }; + + if (UseLTO) { + // We default to creating the arange section, but LTO does not. Enable it + // here. + AddCodeGenFlag("-generate-arange-section"); + + // This tells LTO to perform JustMyCode instrumentation. + if (UseJMC) + AddCodeGenFlag("-enable-jmc-instrument"); + + if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir)) + AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue()); + + StringRef Parallelism = getLTOParallelism(Args, D); + if (!Parallelism.empty()) + AddCodeGenFlag(Twine("-threads=") + Parallelism); + + const char *Prefix = nullptr; + if (D.getLTOMode() == LTOK_Thin) + Prefix = "-lto-thin-debug-options="; + else if (D.getLTOMode() == LTOK_Full) + Prefix = "-lto-debug-options="; else - CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag)); + llvm_unreachable("new LTO mode?"); + + CmdArgs.push_back(Args.MakeArgString(Twine(Prefix) + LTOArgs)); + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) + TC.addSanitizerArgs(Args, CmdArgs, "-l", ""); + + if (D.isUsingLTO() && Args.hasArg(options::OPT_funified_lto)) { + if (D.getLTOMode() == LTOK_Thin) + CmdArgs.push_back("--lto=thin"); + else if (D.getLTOMode() == LTOK_Full) + CmdArgs.push_back("--lto=full"); + } + + Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, + options::OPT_s, options::OPT_t}); + + if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) + CmdArgs.push_back("--no-demangle"); + + AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + + if (Args.hasArg(options::OPT_pthread)) { + CmdArgs.push_back("-lpthread"); + } + + if (UseJMC) { + CmdArgs.push_back("--whole-archive"); + CmdArgs.push_back("-lSceDbgJmc"); + CmdArgs.push_back("--no-whole-archive"); + } + + if (Args.hasArg(options::OPT_fuse_ld_EQ)) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << "-fuse-ld" << TC.getTriple().str(); + } + + std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName()); + const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str())); + + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); +} + +void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + auto &TC = static_cast(getToolChain()); + const Driver &D = TC.getDriver(); + ArgStringList CmdArgs; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + if (Args.hasArg(options::OPT_pie)) + CmdArgs.push_back("-pie"); + + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); + if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("--shared"); + + assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } + + const bool UseLTO = D.isUsingLTO(); + const bool UseJMC = + Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false); + + auto AddCodeGenFlag = [&](Twine Flag) { + CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag)); }; if (UseLTO) { @@ -178,24 +284,8 @@ void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue()); StringRef Parallelism = getLTOParallelism(Args, D); - if (!Parallelism.empty()) { - if (IsPS4) - AddCodeGenFlag(Twine("-threads=") + Parallelism); - else - CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") + Parallelism)); - } - - if (IsPS4) { - const char *Prefix = nullptr; - if (D.getLTOMode() == LTOK_Thin) - Prefix = "-lto-thin-debug-options="; - else if (D.getLTOMode() == LTOK_Full) - Prefix = "-lto-debug-options="; - else - llvm_unreachable("new LTO mode?"); - - CmdArgs.push_back(Args.MakeArgString(Twine(Prefix) + PS4LTOArgs)); - } + if (!Parallelism.empty()) + CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") + Parallelism)); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) @@ -222,10 +312,7 @@ void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (UseJMC) { CmdArgs.push_back("--whole-archive"); - if (IsPS4) - CmdArgs.push_back("-lSceDbgJmc"); - else - CmdArgs.push_back("-lSceJmc_nosubmission"); + CmdArgs.push_back("-lSceJmc_nosubmission"); CmdArgs.push_back("--no-whole-archive"); } @@ -321,14 +408,18 @@ Tool *toolchains::PS4CPU::buildAssembler() const { return new tools::PScpu::Assembler(*this); } +Tool *toolchains::PS4CPU::buildLinker() const { + return new tools::PS4cpu::Linker(*this); +} + Tool *toolchains::PS5CPU::buildAssembler() const { // PS5 does not support an external assembler. getDriver().Diag(clang::diag::err_no_external_assembler); return nullptr; } -Tool *toolchains::PS4PS5Base::buildLinker() const { - return new tools::PScpu::Linker(*this); +Tool *toolchains::PS5CPU::buildLinker() const { + return new tools::PS5cpu::Linker(*this); } SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const { diff --git a/clang/lib/Driver/ToolChains/PS4CPU.h b/clang/lib/Driver/ToolChains/PS4CPU.h index fee80e77462f39..0be90183c637c8 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.h +++ b/clang/lib/Driver/ToolChains/PS4CPU.h @@ -38,10 +38,12 @@ class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; +} // namespace PScpu +namespace PS4cpu { class LLVM_LIBRARY_VISIBILITY Linker final : public Tool { public: - Linker(const ToolChain &TC) : Tool("PScpu::Linker", "linker", TC) {} + Linker(const ToolChain &TC) : Tool("PS4cpu::Linker", "linker", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } @@ -51,7 +53,23 @@ class LLVM_LIBRARY_VISIBILITY Linker final : public Tool { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; -} // namespace PScpu +} // namespace PS4cpu + +namespace PS5cpu { +class LLVM_LIBRARY_VISIBILITY Linker final : public Tool { +public: + Linker(const ToolChain &TC) : Tool("PS5cpu::Linker", "linker", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; +} // namespace PS5cpu + } // namespace tools namespace toolchains { @@ -110,9 +128,6 @@ class LLVM_LIBRARY_VISIBILITY PS4PS5Base : public Generic_ELF { const char *Suffix) const = 0; virtual const char *getProfileRTLibName() const = 0; -protected: - Tool *buildLinker() const override; - private: // We compute the SDK root dir in the ctor, and use it later. std::string SDKRootDir; @@ -143,6 +158,7 @@ class LLVM_LIBRARY_VISIBILITY PS4CPU : public PS4PS5Base { protected: Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; // PS5-specific Toolchain class. @@ -168,6 +184,7 @@ class LLVM_LIBRARY_VISIBILITY PS5CPU : public PS4PS5Base { protected: Tool *buildAssembler() const override; + Tool *buildLinker() const override; }; } // end namespace toolchains diff --git a/clang/test/Driver/ps4-linker.c b/clang/test/Driver/ps4-linker.c new file mode 100644 index 00000000000000..be0103bffe8136 --- /dev/null +++ b/clang/test/Driver/ps4-linker.c @@ -0,0 +1,20 @@ +// Test the driver's control over the JustMyCode behavior with linker flags. + +// RUN: %clang --target=x86_64-scei-ps4 -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-LIB %s +// RUN: %clang --target=x86_64-scei-ps4 -flto=thin -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-THIN-LTO,CHECK-LIB %s +// RUN: %clang --target=x86_64-scei-ps4 -flto=full -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-FULL-LTO,CHECK-LIB %s + +// CHECK-NOT: -enable-jmc-instrument +// CHECK-THIN-LTO: "-lto-thin-debug-options= -generate-arange-section -enable-jmc-instrument" +// CHECK-FULL-LTO: "-lto-debug-options= -generate-arange-section -enable-jmc-instrument" + +// Check the default library name. +// CHECK-LIB: "--whole-archive" "-lSceDbgJmc" "--no-whole-archive" + +// Test the driver's control over the -fcrash-diagnostics-dir behavior with linker flags. + +// RUN: %clang --target=x86_64-scei-ps4 -flto=thin -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG-THIN-LTO %s +// RUN: %clang --target=x86_64-scei-ps4 -flto=full -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG-FULL-LTO %s + +// CHECK-DIAG-THIN-LTO: "-lto-thin-debug-options= -generate-arange-section -crash-diagnostics-dir=mydumps" +// CHECK-DIAG-FULL-LTO: "-lto-debug-options= -generate-arange-section -crash-diagnostics-dir=mydumps" diff --git a/clang/test/Driver/ps4-ps5-linker.c b/clang/test/Driver/ps4-ps5-linker.c deleted file mode 100644 index 8aae94c8388346..00000000000000 --- a/clang/test/Driver/ps4-ps5-linker.c +++ /dev/null @@ -1,29 +0,0 @@ -// Test the driver's control over the JustMyCode behavior with linker flags. - -// RUN: %clang --target=x86_64-scei-ps4 -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-PS4,CHECK-PS4-LIB %s -// RUN: %clang --target=x86_64-scei-ps4 -flto=thin -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-PS4-THIN-LTO,CHECK-PS4-LIB %s -// RUN: %clang --target=x86_64-scei-ps4 -flto=full -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-PS4-FULL-LTO,CHECK-PS4-LIB %s -// RUN: %clang --target=x86_64-scei-ps5 -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-PS5,CHECK-PS5-LIB %s -// RUN: %clang --target=x86_64-scei-ps5 -flto -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-PS5-LTO,CHECK-PS5-LIB %s - -// CHECK-PS4-NOT: -enable-jmc-instrument -// CHECK-PS4-THIN-LTO: "-lto-thin-debug-options= -generate-arange-section -enable-jmc-instrument" -// CHECK-PS4-FULL-LTO: "-lto-debug-options= -generate-arange-section -enable-jmc-instrument" -// CHECK-PS5-NOT: -plugin-opt=-enable-jmc-instrument -// CHECK-PS5-LTO: -plugin-opt=-enable-jmc-instrument - -// Check the default library name. -// CHECK-PS4-LIB: "--whole-archive" "-lSceDbgJmc" "--no-whole-archive" -// CHECK-PS5-LIB: "--whole-archive" "-lSceJmc_nosubmission" "--no-whole-archive" - -// Test the driver's control over the -fcrash-diagnostics-dir behavior with linker flags. - -// RUN: %clang --target=x86_64-scei-ps4 -flto=thin -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG-PS4-THIN-LTO %s -// RUN: %clang --target=x86_64-scei-ps4 -flto=full -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG-PS4-FULL-LTO %s -// RUN: %clang --target=x86_64-scei-ps5 -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG-PS5 %s -// RUN: %clang --target=x86_64-scei-ps5 -flto -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG-PS5-LTO %s - -// CHECK-DIAG-PS4-THIN-LTO: "-lto-thin-debug-options= -generate-arange-section -crash-diagnostics-dir=mydumps" -// CHECK-DIAG-PS4-FULL-LTO: "-lto-debug-options= -generate-arange-section -crash-diagnostics-dir=mydumps" -// CHECK-DIAG-PS5-NOT: -plugin-opt=-crash-diagnostics-dir=mydumps -// CHECK-DIAG-PS5-LTO: -plugin-opt=-crash-diagnostics-dir=mydumps diff --git a/clang/test/Driver/ps5-linker.c b/clang/test/Driver/ps5-linker.c new file mode 100644 index 00000000000000..9f1e3a273b2db2 --- /dev/null +++ b/clang/test/Driver/ps5-linker.c @@ -0,0 +1,18 @@ +// Test the driver's control over the JustMyCode behavior with linker flags. + +// RUN: %clang --target=x86_64-scei-ps5 -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-LIB %s +// RUN: %clang --target=x86_64-scei-ps5 -flto -fjmc %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LTO,CHECK-LIB %s + +// CHECK-NOT: -plugin-opt=-enable-jmc-instrument +// CHECK-LTO: -plugin-opt=-enable-jmc-instrument + +// Check the default library name. +// CHECK-LIB: "--whole-archive" "-lSceJmc_nosubmission" "--no-whole-archive" + +// Test the driver's control over the -fcrash-diagnostics-dir behavior with linker flags. + +// RUN: %clang --target=x86_64-scei-ps5 -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG %s +// RUN: %clang --target=x86_64-scei-ps5 -flto -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG-LTO %s + +// CHECK-DIAG-NOT: -plugin-opt=-crash-diagnostics-dir=mydumps +// CHECK-DIAG-LTO: -plugin-opt=-crash-diagnostics-dir=mydumps