aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Driver/Tools.cpp
diff options
context:
space:
mode:
authorEkaterina Romanova <katya_romanova@playstation.sony.com>2015-10-13 23:40:02 +0000
committerEkaterina Romanova <katya_romanova@playstation.sony.com>2015-10-13 23:40:02 +0000
commita59fcbae4ff25ed039728ac66af0fcf625fa22d4 (patch)
tree9a83bd700839695ae3b3e349ddf04cf933cd1a71 /clang/lib/Driver/Tools.cpp
parent16e7ff171bce9d10e684c5ad1c928242078fcccc (diff)
downloadllvm-a59fcbae4ff25ed039728ac66af0fcf625fa22d4.zip
llvm-a59fcbae4ff25ed039728ac66af0fcf625fa22d4.tar.gz
llvm-a59fcbae4ff25ed039728ac66af0fcf625fa22d4.tar.bz2
This patch adds missing pieces to clang, including the PS4 toolchain
definition, added warnings, PS4 defaults, and Driver changes needed for our compiler. A patch by Filipe Cabecinhas, Pierre Gousseau and Katya Romanova! Differential Revision: http://reviews.llvm.org/D13482 llvm-svn: 250252
Diffstat (limited to 'clang/lib/Driver/Tools.cpp')
-rw-r--r--clang/lib/Driver/Tools.cpp348
1 files changed, 341 insertions, 7 deletions
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index 8a8904d..21939e0 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -3110,15 +3110,23 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
} else {
PIE = PIC = false;
+ if (Triple.isPS4CPU()) {
+ Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ);
+ StringRef Model = ModelArg ? ModelArg->getValue() : "";
+ if (Model != "kernel") {
+ PIC = true;
+ ToolChain.getDriver().Diag(diag::warn_drv_ps4_force_pic)
+ << LastPICArg->getSpelling();
+ }
+ }
}
}
}
- // Introduce a Darwin-specific hack. If the default is PIC, but the
- // PIC level would've been set to level 1, force it back to level 2
- // PIC instead. This matches the behavior of Darwin GCC (based on
- // chandlerc's informal testing in 2012).
- if (PIC && ToolChain.getTriple().isOSDarwin())
+ // Introduce a Darwin and PS4-specific hack. If the default is PIC, but the
+ // PIC level would've been set to level 1, force it back to level 2 PIC
+ // instead.
+ if (PIC && (ToolChain.getTriple().isOSDarwin() || Triple.isPS4CPU()))
IsPICLevelTwo |= ToolChain.isPICDefault();
// This kernel flags are a trump-card: they will disable PIC/PIE
@@ -3190,6 +3198,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool IsWindowsCygnus =
getToolChain().getTriple().isWindowsCygwinEnvironment();
bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();
+ bool IsPS4CPU = getToolChain().getTriple().isPS4CPU();
// Check number of inputs for sanity. We need at least one input.
assert(Inputs.size() >= 1 && "Must have at least one input.");
@@ -3843,8 +3852,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
Args.ClaimAllArgs(options::OPT_g_flags_Group);
+
+ // PS4 defaults to no column info
if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
- /*Default*/ true))
+ /*Default=*/ !IsPS4CPU))
CmdArgs.push_back("-dwarf-column-info");
// FIXME: Move backend command line options to the module.
@@ -3883,7 +3894,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -gdwarf-aranges turns on the emission of the aranges section in the
// backend.
- if (Args.hasArg(options::OPT_gdwarf_aranges)) {
+ // Always enabled on the PS4.
+ if (Args.hasArg(options::OPT_gdwarf_aranges) || IsPS4CPU) {
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-generate-arange-section");
}
@@ -9919,3 +9931,325 @@ void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
CmdArgs, Inputs));
}
+
+void PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ assert(Inputs.size() == 1 && "Unexpected number of inputs.");
+ const InputInfo &Input = Inputs[0];
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ps4-as"));
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
+static void AddPS4ProfileRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ false) ||
+ Args.hasArg(options::OPT_fprofile_generate) ||
+ Args.hasArg(options::OPT_fprofile_instr_generate) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_coverage)))
+ return;
+
+ assert(TC.getTriple().isPS4CPU() &&
+ "Profiling libraries are only implemented for the PS4 CPU");
+ CmdArgs.push_back("-lclang_rt.profile-x86_64");
+}
+
+static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ if (SanArgs.needsUbsanRt()) {
+ CmdArgs.push_back("-lSceDbgUBSanitizer_stub_weak");
+ }
+ if (SanArgs.needsAsanRt()) {
+ CmdArgs.push_back("-lSceDbgAddressSanitizer_stub_weak");
+ }
+}
+
+static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
+ const JobAction &JA, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) {
+ const toolchains::FreeBSD &ToolChain =
+ static_cast<const toolchains::FreeBSD &>(T.getToolChain());
+ const Driver &D = ToolChain.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("--oformat=so");
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("--no-demangle");
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (Args.hasArg(options::OPT_pthread)) {
+ CmdArgs.push_back("-lpthread");
+ }
+
+ AddPS4ProfileRT(ToolChain, Args, CmdArgs);
+ AddPS4SanitizerArgs(ToolChain, CmdArgs);
+
+ const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld"));
+
+ C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs));
+}
+
+static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
+ const JobAction &JA, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) {
+ const toolchains::FreeBSD &ToolChain =
+ static_cast<const toolchains::FreeBSD &>(T.getToolChain());
+ const Driver &D = ToolChain.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_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("--eh-frame-hdr");
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-Bshareable");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back("/libexec/ld-elf.so.1");
+ }
+ CmdArgs.push_back("--enable-new-dtags");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ const char *crt1 = NULL;
+ if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ crt1 = "gcrt1.o";
+ else if (Args.hasArg(options::OPT_pie))
+ crt1 = "Scrt1.o";
+ else
+ crt1 = "crt1.o";
+ }
+ if (crt1)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+
+ const char *crtbegin = NULL;
+ if (Args.hasArg(options::OPT_static))
+ crtbegin = "crtbeginT.o";
+ else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ crtbegin = "crtbeginS.o";
+ else
+ crtbegin = "crtbegin.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+
+ const ToolChain::path_list Paths = ToolChain.getFilePaths();
+ for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end();
+ i != e; ++i)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
+
+ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("--no-demangle");
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // For PS4, we always want to pass libm, libstdc++ and libkernel
+ // libraries for both C and C++ compilations.
+ CmdArgs.push_back("-lkernel");
+ if (D.CCCIsCXX()) {
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+ // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
+ // the default system libraries. Just mimic this for now.
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lgcc_p");
+ else
+ CmdArgs.push_back("-lcompiler_rt");
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lstdc++");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lstdc++");
+ CmdArgs.push_back("--no-as-needed");
+ }
+
+ if (Args.hasArg(options::OPT_pthread)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lpthread_p");
+ else
+ CmdArgs.push_back("-lpthread");
+ }
+
+ if (Args.hasArg(options::OPT_pg)) {
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ else {
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc_p");
+ CmdArgs.push_back("-lpthread_p");
+ CmdArgs.push_back("--end-group");
+ } else {
+ CmdArgs.push_back("-lc_p");
+ }
+ }
+ CmdArgs.push_back("-lgcc_p");
+ } else {
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("--end-group");
+ } else {
+ CmdArgs.push_back("-lc");
+ }
+ CmdArgs.push_back("-lcompiler_rt");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-lstdc++");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
+ } else {
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lstdc++");
+ CmdArgs.push_back("--no-as-needed");
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+
+ AddPS4ProfileRT(ToolChain, Args, CmdArgs);
+ AddPS4SanitizerArgs(ToolChain, CmdArgs);
+
+ const char *Exec =
+#ifdef LLVM_ON_WIN32
+ Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld.gold.exe"));
+#else
+ Args.MakeArgString(ToolChain.GetProgramPath("ps4-ld"));
+#endif
+
+ C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs));
+}
+
+void PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::FreeBSD &ToolChain =
+ static_cast<const toolchains::FreeBSD &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ bool PS4Linker;
+ StringRef LinkerOptName;
+ if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ LinkerOptName = A->getValue();
+ if (LinkerOptName != "ps4" && LinkerOptName != "gold")
+ D.Diag(diag::err_drv_unsupported_linker) << LinkerOptName;
+ }
+
+ if (LinkerOptName == "gold")
+ PS4Linker = false;
+ else if (LinkerOptName == "ps4")
+ PS4Linker = true;
+ else
+ PS4Linker = !Args.hasArg(options::OPT_shared);
+
+ if (PS4Linker)
+ ConstructPS4LinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput);
+ else
+ ConstructGoldLinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput);
+}