Skip to content
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

[PS4/PS5][NFC] Split PScpu::Linker into PS4/PS5 classes #98884

Merged
merged 1 commit into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 125 additions & 34 deletions clang/lib/Driver/ToolChains/PS4CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<const toolchains::PS4PS5Base &>(getToolChain());
const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
Expand Down Expand Up @@ -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<Command>(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<const toolchains::PS4PS5Base &>(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) {
Expand All @@ -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))
Expand All @@ -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");
}

Expand Down Expand Up @@ -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 {
Expand Down
27 changes: 22 additions & 5 deletions clang/lib/Driver/ToolChains/PS4CPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -143,6 +158,7 @@ class LLVM_LIBRARY_VISIBILITY PS4CPU : public PS4PS5Base {

protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};

// PS5-specific Toolchain class.
Expand All @@ -168,6 +184,7 @@ class LLVM_LIBRARY_VISIBILITY PS5CPU : public PS4PS5Base {

protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};

} // end namespace toolchains
Expand Down
20 changes: 20 additions & 0 deletions clang/test/Driver/ps4-linker.c
Original file line number Diff line number Diff line change
@@ -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"
29 changes: 0 additions & 29 deletions clang/test/Driver/ps4-ps5-linker.c

This file was deleted.

18 changes: 18 additions & 0 deletions clang/test/Driver/ps5-linker.c
Original file line number Diff line number Diff line change
@@ -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
Loading