1*0b57cec5SDimitry Andric //===--- PS4CPU.cpp - PS4CPU ToolChain Implementations ----------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "PS4CPU.h" 10*0b57cec5SDimitry Andric #include "FreeBSD.h" 11*0b57cec5SDimitry Andric #include "CommonArgs.h" 12*0b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 13*0b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 14*0b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 15*0b57cec5SDimitry Andric #include "clang/Driver/Options.h" 16*0b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 17*0b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 18*0b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 19*0b57cec5SDimitry Andric #include "llvm/Support/Path.h" 20*0b57cec5SDimitry Andric #include <cstdlib> // ::getenv 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric using namespace clang::driver; 23*0b57cec5SDimitry Andric using namespace clang; 24*0b57cec5SDimitry Andric using namespace llvm::opt; 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric using clang::driver::tools::AddLinkerInputs; 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric void tools::PS4cpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args, 29*0b57cec5SDimitry Andric ArgStringList &CmdArgs) { 30*0b57cec5SDimitry Andric if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, 31*0b57cec5SDimitry Andric false) || 32*0b57cec5SDimitry Andric Args.hasFlag(options::OPT_fprofile_generate, 33*0b57cec5SDimitry Andric options::OPT_fno_profile_instr_generate, false) || 34*0b57cec5SDimitry Andric Args.hasFlag(options::OPT_fprofile_generate_EQ, 35*0b57cec5SDimitry Andric options::OPT_fno_profile_instr_generate, false) || 36*0b57cec5SDimitry Andric Args.hasFlag(options::OPT_fprofile_instr_generate, 37*0b57cec5SDimitry Andric options::OPT_fno_profile_instr_generate, false) || 38*0b57cec5SDimitry Andric Args.hasFlag(options::OPT_fprofile_instr_generate_EQ, 39*0b57cec5SDimitry Andric options::OPT_fno_profile_instr_generate, false) || 40*0b57cec5SDimitry Andric Args.hasArg(options::OPT_fcreate_profile) || 41*0b57cec5SDimitry Andric Args.hasArg(options::OPT_coverage))) 42*0b57cec5SDimitry Andric CmdArgs.push_back("--dependent-lib=libclang_rt.profile-x86_64.a"); 43*0b57cec5SDimitry Andric } 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA, 46*0b57cec5SDimitry Andric const InputInfo &Output, 47*0b57cec5SDimitry Andric const InputInfoList &Inputs, 48*0b57cec5SDimitry Andric const ArgList &Args, 49*0b57cec5SDimitry Andric const char *LinkingOutput) const { 50*0b57cec5SDimitry Andric claimNoWarnArgs(Args); 51*0b57cec5SDimitry Andric ArgStringList CmdArgs; 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric CmdArgs.push_back("-o"); 56*0b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric assert(Inputs.size() == 1 && "Unexpected number of inputs."); 59*0b57cec5SDimitry Andric const InputInfo &Input = Inputs[0]; 60*0b57cec5SDimitry Andric assert(Input.isFilename() && "Invalid input."); 61*0b57cec5SDimitry Andric CmdArgs.push_back(Input.getFilename()); 62*0b57cec5SDimitry Andric 63*0b57cec5SDimitry Andric const char *Exec = 64*0b57cec5SDimitry Andric Args.MakeArgString(getToolChain().GetProgramPath("orbis-as")); 65*0b57cec5SDimitry Andric C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 66*0b57cec5SDimitry Andric } 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) { 69*0b57cec5SDimitry Andric const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); 70*0b57cec5SDimitry Andric if (SanArgs.needsUbsanRt()) { 71*0b57cec5SDimitry Andric CmdArgs.push_back("-lSceDbgUBSanitizer_stub_weak"); 72*0b57cec5SDimitry Andric } 73*0b57cec5SDimitry Andric if (SanArgs.needsAsanRt()) { 74*0b57cec5SDimitry Andric CmdArgs.push_back("-lSceDbgAddressSanitizer_stub_weak"); 75*0b57cec5SDimitry Andric } 76*0b57cec5SDimitry Andric } 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC, 79*0b57cec5SDimitry Andric ArgStringList &CmdArgs) { 80*0b57cec5SDimitry Andric const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); 81*0b57cec5SDimitry Andric if (SanArgs.needsUbsanRt()) 82*0b57cec5SDimitry Andric CmdArgs.push_back("--dependent-lib=libSceDbgUBSanitizer_stub_weak.a"); 83*0b57cec5SDimitry Andric if (SanArgs.needsAsanRt()) 84*0b57cec5SDimitry Andric CmdArgs.push_back("--dependent-lib=libSceDbgAddressSanitizer_stub_weak.a"); 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric static void ConstructPS4LinkJob(const Tool &T, Compilation &C, 88*0b57cec5SDimitry Andric const JobAction &JA, const InputInfo &Output, 89*0b57cec5SDimitry Andric const InputInfoList &Inputs, 90*0b57cec5SDimitry Andric const ArgList &Args, 91*0b57cec5SDimitry Andric const char *LinkingOutput) { 92*0b57cec5SDimitry Andric const toolchains::FreeBSD &ToolChain = 93*0b57cec5SDimitry Andric static_cast<const toolchains::FreeBSD &>(T.getToolChain()); 94*0b57cec5SDimitry Andric const Driver &D = ToolChain.getDriver(); 95*0b57cec5SDimitry Andric ArgStringList CmdArgs; 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric // Silence warning for "clang -g foo.o -o foo" 98*0b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 99*0b57cec5SDimitry Andric // and "clang -emit-llvm foo.o -o foo" 100*0b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 101*0b57cec5SDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 102*0b57cec5SDimitry Andric // handled somewhere else. 103*0b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_w); 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric if (!D.SysRoot.empty()) 106*0b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pie)) 109*0b57cec5SDimitry Andric CmdArgs.push_back("-pie"); 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_rdynamic)) 112*0b57cec5SDimitry Andric CmdArgs.push_back("-export-dynamic"); 113*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared)) 114*0b57cec5SDimitry Andric CmdArgs.push_back("--oformat=so"); 115*0b57cec5SDimitry Andric 116*0b57cec5SDimitry Andric if (Output.isFilename()) { 117*0b57cec5SDimitry Andric CmdArgs.push_back("-o"); 118*0b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 119*0b57cec5SDimitry Andric } else { 120*0b57cec5SDimitry Andric assert(Output.isNothing() && "Invalid output."); 121*0b57cec5SDimitry Andric } 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) 124*0b57cec5SDimitry Andric AddPS4SanitizerArgs(ToolChain, CmdArgs); 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 127*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_T_Group); 128*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_e); 129*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_s); 130*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_t); 131*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_r); 132*0b57cec5SDimitry Andric 133*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 134*0b57cec5SDimitry Andric CmdArgs.push_back("--no-demangle"); 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pthread)) { 139*0b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric static void ConstructGoldLinkJob(const Tool &T, Compilation &C, 148*0b57cec5SDimitry Andric const JobAction &JA, const InputInfo &Output, 149*0b57cec5SDimitry Andric const InputInfoList &Inputs, 150*0b57cec5SDimitry Andric const ArgList &Args, 151*0b57cec5SDimitry Andric const char *LinkingOutput) { 152*0b57cec5SDimitry Andric const toolchains::FreeBSD &ToolChain = 153*0b57cec5SDimitry Andric static_cast<const toolchains::FreeBSD &>(T.getToolChain()); 154*0b57cec5SDimitry Andric const Driver &D = ToolChain.getDriver(); 155*0b57cec5SDimitry Andric ArgStringList CmdArgs; 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric // Silence warning for "clang -g foo.o -o foo" 158*0b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 159*0b57cec5SDimitry Andric // and "clang -emit-llvm foo.o -o foo" 160*0b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 161*0b57cec5SDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 162*0b57cec5SDimitry Andric // handled somewhere else. 163*0b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_w); 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric if (!D.SysRoot.empty()) 166*0b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pie)) 169*0b57cec5SDimitry Andric CmdArgs.push_back("-pie"); 170*0b57cec5SDimitry Andric 171*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) { 172*0b57cec5SDimitry Andric CmdArgs.push_back("-Bstatic"); 173*0b57cec5SDimitry Andric } else { 174*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_rdynamic)) 175*0b57cec5SDimitry Andric CmdArgs.push_back("-export-dynamic"); 176*0b57cec5SDimitry Andric CmdArgs.push_back("--eh-frame-hdr"); 177*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared)) { 178*0b57cec5SDimitry Andric CmdArgs.push_back("-Bshareable"); 179*0b57cec5SDimitry Andric } else { 180*0b57cec5SDimitry Andric CmdArgs.push_back("-dynamic-linker"); 181*0b57cec5SDimitry Andric CmdArgs.push_back("/libexec/ld-elf.so.1"); 182*0b57cec5SDimitry Andric } 183*0b57cec5SDimitry Andric CmdArgs.push_back("--enable-new-dtags"); 184*0b57cec5SDimitry Andric } 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric if (Output.isFilename()) { 187*0b57cec5SDimitry Andric CmdArgs.push_back("-o"); 188*0b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 189*0b57cec5SDimitry Andric } else { 190*0b57cec5SDimitry Andric assert(Output.isNothing() && "Invalid output."); 191*0b57cec5SDimitry Andric } 192*0b57cec5SDimitry Andric 193*0b57cec5SDimitry Andric if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) 194*0b57cec5SDimitry Andric AddPS4SanitizerArgs(ToolChain, CmdArgs); 195*0b57cec5SDimitry Andric 196*0b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 197*0b57cec5SDimitry Andric const char *crt1 = nullptr; 198*0b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_shared)) { 199*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) 200*0b57cec5SDimitry Andric crt1 = "gcrt1.o"; 201*0b57cec5SDimitry Andric else if (Args.hasArg(options::OPT_pie)) 202*0b57cec5SDimitry Andric crt1 = "Scrt1.o"; 203*0b57cec5SDimitry Andric else 204*0b57cec5SDimitry Andric crt1 = "crt1.o"; 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric if (crt1) 207*0b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); 210*0b57cec5SDimitry Andric 211*0b57cec5SDimitry Andric const char *crtbegin = nullptr; 212*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) 213*0b57cec5SDimitry Andric crtbegin = "crtbeginT.o"; 214*0b57cec5SDimitry Andric else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) 215*0b57cec5SDimitry Andric crtbegin = "crtbeginS.o"; 216*0b57cec5SDimitry Andric else 217*0b57cec5SDimitry Andric crtbegin = "crtbegin.o"; 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); 220*0b57cec5SDimitry Andric } 221*0b57cec5SDimitry Andric 222*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 223*0b57cec5SDimitry Andric ToolChain.AddFilePathLibArgs(Args, CmdArgs); 224*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_T_Group); 225*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_e); 226*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_s); 227*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_t); 228*0b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_r); 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 231*0b57cec5SDimitry Andric CmdArgs.push_back("--no-demangle"); 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 234*0b57cec5SDimitry Andric 235*0b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 236*0b57cec5SDimitry Andric // For PS4, we always want to pass libm, libstdc++ and libkernel 237*0b57cec5SDimitry Andric // libraries for both C and C++ compilations. 238*0b57cec5SDimitry Andric CmdArgs.push_back("-lkernel"); 239*0b57cec5SDimitry Andric if (D.CCCIsCXX()) { 240*0b57cec5SDimitry Andric if (ToolChain.ShouldLinkCXXStdlib(Args)) 241*0b57cec5SDimitry Andric ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); 242*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) 243*0b57cec5SDimitry Andric CmdArgs.push_back("-lm_p"); 244*0b57cec5SDimitry Andric else 245*0b57cec5SDimitry Andric CmdArgs.push_back("-lm"); 246*0b57cec5SDimitry Andric } 247*0b57cec5SDimitry Andric // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding 248*0b57cec5SDimitry Andric // the default system libraries. Just mimic this for now. 249*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) 250*0b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_p"); 251*0b57cec5SDimitry Andric else 252*0b57cec5SDimitry Andric CmdArgs.push_back("-lcompiler_rt"); 253*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) { 254*0b57cec5SDimitry Andric CmdArgs.push_back("-lstdc++"); 255*0b57cec5SDimitry Andric } else if (Args.hasArg(options::OPT_pg)) { 256*0b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_eh_p"); 257*0b57cec5SDimitry Andric } else { 258*0b57cec5SDimitry Andric CmdArgs.push_back("--as-needed"); 259*0b57cec5SDimitry Andric CmdArgs.push_back("-lstdc++"); 260*0b57cec5SDimitry Andric CmdArgs.push_back("--no-as-needed"); 261*0b57cec5SDimitry Andric } 262*0b57cec5SDimitry Andric 263*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pthread)) { 264*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) 265*0b57cec5SDimitry Andric CmdArgs.push_back("-lpthread_p"); 266*0b57cec5SDimitry Andric else 267*0b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 268*0b57cec5SDimitry Andric } 269*0b57cec5SDimitry Andric 270*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pg)) { 271*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared)) 272*0b57cec5SDimitry Andric CmdArgs.push_back("-lc"); 273*0b57cec5SDimitry Andric else { 274*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) { 275*0b57cec5SDimitry Andric CmdArgs.push_back("--start-group"); 276*0b57cec5SDimitry Andric CmdArgs.push_back("-lc_p"); 277*0b57cec5SDimitry Andric CmdArgs.push_back("-lpthread_p"); 278*0b57cec5SDimitry Andric CmdArgs.push_back("--end-group"); 279*0b57cec5SDimitry Andric } else { 280*0b57cec5SDimitry Andric CmdArgs.push_back("-lc_p"); 281*0b57cec5SDimitry Andric } 282*0b57cec5SDimitry Andric } 283*0b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_p"); 284*0b57cec5SDimitry Andric } else { 285*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) { 286*0b57cec5SDimitry Andric CmdArgs.push_back("--start-group"); 287*0b57cec5SDimitry Andric CmdArgs.push_back("-lc"); 288*0b57cec5SDimitry Andric CmdArgs.push_back("-lpthread"); 289*0b57cec5SDimitry Andric CmdArgs.push_back("--end-group"); 290*0b57cec5SDimitry Andric } else { 291*0b57cec5SDimitry Andric CmdArgs.push_back("-lc"); 292*0b57cec5SDimitry Andric } 293*0b57cec5SDimitry Andric CmdArgs.push_back("-lcompiler_rt"); 294*0b57cec5SDimitry Andric } 295*0b57cec5SDimitry Andric 296*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static)) { 297*0b57cec5SDimitry Andric CmdArgs.push_back("-lstdc++"); 298*0b57cec5SDimitry Andric } else if (Args.hasArg(options::OPT_pg)) { 299*0b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_eh_p"); 300*0b57cec5SDimitry Andric } else { 301*0b57cec5SDimitry Andric CmdArgs.push_back("--as-needed"); 302*0b57cec5SDimitry Andric CmdArgs.push_back("-lstdc++"); 303*0b57cec5SDimitry Andric CmdArgs.push_back("--no-as-needed"); 304*0b57cec5SDimitry Andric } 305*0b57cec5SDimitry Andric } 306*0b57cec5SDimitry Andric 307*0b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 308*0b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) 309*0b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); 310*0b57cec5SDimitry Andric else 311*0b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); 312*0b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); 313*0b57cec5SDimitry Andric } 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric const char *Exec = 316*0b57cec5SDimitry Andric #ifdef _WIN32 317*0b57cec5SDimitry Andric Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld.gold")); 318*0b57cec5SDimitry Andric #else 319*0b57cec5SDimitry Andric Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); 320*0b57cec5SDimitry Andric #endif 321*0b57cec5SDimitry Andric 322*0b57cec5SDimitry Andric C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); 323*0b57cec5SDimitry Andric } 324*0b57cec5SDimitry Andric 325*0b57cec5SDimitry Andric void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA, 326*0b57cec5SDimitry Andric const InputInfo &Output, 327*0b57cec5SDimitry Andric const InputInfoList &Inputs, 328*0b57cec5SDimitry Andric const ArgList &Args, 329*0b57cec5SDimitry Andric const char *LinkingOutput) const { 330*0b57cec5SDimitry Andric const toolchains::FreeBSD &ToolChain = 331*0b57cec5SDimitry Andric static_cast<const toolchains::FreeBSD &>(getToolChain()); 332*0b57cec5SDimitry Andric const Driver &D = ToolChain.getDriver(); 333*0b57cec5SDimitry Andric bool PS4Linker; 334*0b57cec5SDimitry Andric StringRef LinkerOptName; 335*0b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) { 336*0b57cec5SDimitry Andric LinkerOptName = A->getValue(); 337*0b57cec5SDimitry Andric if (LinkerOptName != "ps4" && LinkerOptName != "gold") 338*0b57cec5SDimitry Andric D.Diag(diag::err_drv_unsupported_linker) << LinkerOptName; 339*0b57cec5SDimitry Andric } 340*0b57cec5SDimitry Andric 341*0b57cec5SDimitry Andric if (LinkerOptName == "gold") 342*0b57cec5SDimitry Andric PS4Linker = false; 343*0b57cec5SDimitry Andric else if (LinkerOptName == "ps4") 344*0b57cec5SDimitry Andric PS4Linker = true; 345*0b57cec5SDimitry Andric else 346*0b57cec5SDimitry Andric PS4Linker = !Args.hasArg(options::OPT_shared); 347*0b57cec5SDimitry Andric 348*0b57cec5SDimitry Andric if (PS4Linker) 349*0b57cec5SDimitry Andric ConstructPS4LinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput); 350*0b57cec5SDimitry Andric else 351*0b57cec5SDimitry Andric ConstructGoldLinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput); 352*0b57cec5SDimitry Andric } 353*0b57cec5SDimitry Andric 354*0b57cec5SDimitry Andric toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple, 355*0b57cec5SDimitry Andric const ArgList &Args) 356*0b57cec5SDimitry Andric : Generic_ELF(D, Triple, Args) { 357*0b57cec5SDimitry Andric if (Args.hasArg(clang::driver::options::OPT_static)) 358*0b57cec5SDimitry Andric D.Diag(clang::diag::err_drv_unsupported_opt_for_target) << "-static" 359*0b57cec5SDimitry Andric << "PS4"; 360*0b57cec5SDimitry Andric 361*0b57cec5SDimitry Andric // Determine where to find the PS4 libraries. We use SCE_ORBIS_SDK_DIR 362*0b57cec5SDimitry Andric // if it exists; otherwise use the driver's installation path, which 363*0b57cec5SDimitry Andric // should be <SDK_DIR>/host_tools/bin. 364*0b57cec5SDimitry Andric 365*0b57cec5SDimitry Andric SmallString<512> PS4SDKDir; 366*0b57cec5SDimitry Andric if (const char *EnvValue = getenv("SCE_ORBIS_SDK_DIR")) { 367*0b57cec5SDimitry Andric if (!llvm::sys::fs::exists(EnvValue)) 368*0b57cec5SDimitry Andric getDriver().Diag(clang::diag::warn_drv_ps4_sdk_dir) << EnvValue; 369*0b57cec5SDimitry Andric PS4SDKDir = EnvValue; 370*0b57cec5SDimitry Andric } else { 371*0b57cec5SDimitry Andric PS4SDKDir = getDriver().Dir; 372*0b57cec5SDimitry Andric llvm::sys::path::append(PS4SDKDir, "/../../"); 373*0b57cec5SDimitry Andric } 374*0b57cec5SDimitry Andric 375*0b57cec5SDimitry Andric // By default, the driver won't report a warning if it can't find 376*0b57cec5SDimitry Andric // PS4's include or lib directories. This behavior could be changed if 377*0b57cec5SDimitry Andric // -Weverything or -Winvalid-or-nonexistent-directory options are passed. 378*0b57cec5SDimitry Andric // If -isysroot was passed, use that as the SDK base path. 379*0b57cec5SDimitry Andric std::string PrefixDir; 380*0b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 381*0b57cec5SDimitry Andric PrefixDir = A->getValue(); 382*0b57cec5SDimitry Andric if (!llvm::sys::fs::exists(PrefixDir)) 383*0b57cec5SDimitry Andric getDriver().Diag(clang::diag::warn_missing_sysroot) << PrefixDir; 384*0b57cec5SDimitry Andric } else 385*0b57cec5SDimitry Andric PrefixDir = PS4SDKDir.str(); 386*0b57cec5SDimitry Andric 387*0b57cec5SDimitry Andric SmallString<512> PS4SDKIncludeDir(PrefixDir); 388*0b57cec5SDimitry Andric llvm::sys::path::append(PS4SDKIncludeDir, "target/include"); 389*0b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdinc) && 390*0b57cec5SDimitry Andric !Args.hasArg(options::OPT_nostdlibinc) && 391*0b57cec5SDimitry Andric !Args.hasArg(options::OPT_isysroot) && 392*0b57cec5SDimitry Andric !Args.hasArg(options::OPT__sysroot_EQ) && 393*0b57cec5SDimitry Andric !llvm::sys::fs::exists(PS4SDKIncludeDir)) { 394*0b57cec5SDimitry Andric getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected) 395*0b57cec5SDimitry Andric << "PS4 system headers" << PS4SDKIncludeDir; 396*0b57cec5SDimitry Andric } 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric SmallString<512> PS4SDKLibDir(PS4SDKDir); 399*0b57cec5SDimitry Andric llvm::sys::path::append(PS4SDKLibDir, "target/lib"); 400*0b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib) && 401*0b57cec5SDimitry Andric !Args.hasArg(options::OPT_nodefaultlibs) && 402*0b57cec5SDimitry Andric !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) && 403*0b57cec5SDimitry Andric !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) && 404*0b57cec5SDimitry Andric !Args.hasArg(options::OPT_emit_ast) && 405*0b57cec5SDimitry Andric !llvm::sys::fs::exists(PS4SDKLibDir)) { 406*0b57cec5SDimitry Andric getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected) 407*0b57cec5SDimitry Andric << "PS4 system libraries" << PS4SDKLibDir; 408*0b57cec5SDimitry Andric return; 409*0b57cec5SDimitry Andric } 410*0b57cec5SDimitry Andric getFilePaths().push_back(PS4SDKLibDir.str()); 411*0b57cec5SDimitry Andric } 412*0b57cec5SDimitry Andric 413*0b57cec5SDimitry Andric Tool *toolchains::PS4CPU::buildAssembler() const { 414*0b57cec5SDimitry Andric return new tools::PS4cpu::Assemble(*this); 415*0b57cec5SDimitry Andric } 416*0b57cec5SDimitry Andric 417*0b57cec5SDimitry Andric Tool *toolchains::PS4CPU::buildLinker() const { 418*0b57cec5SDimitry Andric return new tools::PS4cpu::Link(*this); 419*0b57cec5SDimitry Andric } 420*0b57cec5SDimitry Andric 421*0b57cec5SDimitry Andric bool toolchains::PS4CPU::isPICDefault() const { return true; } 422*0b57cec5SDimitry Andric 423*0b57cec5SDimitry Andric bool toolchains::PS4CPU::HasNativeLLVMSupport() const { return true; } 424*0b57cec5SDimitry Andric 425*0b57cec5SDimitry Andric SanitizerMask toolchains::PS4CPU::getSupportedSanitizers() const { 426*0b57cec5SDimitry Andric SanitizerMask Res = ToolChain::getSupportedSanitizers(); 427*0b57cec5SDimitry Andric Res |= SanitizerKind::Address; 428*0b57cec5SDimitry Andric Res |= SanitizerKind::PointerCompare; 429*0b57cec5SDimitry Andric Res |= SanitizerKind::PointerSubtract; 430*0b57cec5SDimitry Andric Res |= SanitizerKind::Vptr; 431*0b57cec5SDimitry Andric return Res; 432*0b57cec5SDimitry Andric } 433