1480093f4SDimitry Andric //===--- AIX.cpp - AIX ToolChain Implementations ----------------*- C++ -*-===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric 9480093f4SDimitry Andric #include "AIX.h" 10480093f4SDimitry Andric #include "Arch/PPC.h" 11480093f4SDimitry Andric #include "CommonArgs.h" 12480093f4SDimitry Andric #include "clang/Driver/Compilation.h" 13480093f4SDimitry Andric #include "clang/Driver/Options.h" 14480093f4SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 15480093f4SDimitry Andric #include "llvm/Option/ArgList.h" 165ffd83dbSDimitry Andric #include "llvm/Support/Path.h" 17480093f4SDimitry Andric 18480093f4SDimitry Andric using AIX = clang::driver::toolchains::AIX; 19480093f4SDimitry Andric using namespace clang::driver; 20480093f4SDimitry Andric using namespace clang::driver::tools; 215ffd83dbSDimitry Andric using namespace clang::driver::toolchains; 22480093f4SDimitry Andric 23480093f4SDimitry Andric using namespace llvm::opt; 245ffd83dbSDimitry Andric using namespace llvm::sys; 25480093f4SDimitry Andric 26480093f4SDimitry Andric void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 27480093f4SDimitry Andric const InputInfo &Output, 28480093f4SDimitry Andric const InputInfoList &Inputs, 29480093f4SDimitry Andric const ArgList &Args, 30480093f4SDimitry Andric const char *LinkingOutput) const { 31480093f4SDimitry Andric ArgStringList CmdArgs; 32480093f4SDimitry Andric 33480093f4SDimitry Andric const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit(); 34480093f4SDimitry Andric const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit(); 35480093f4SDimitry Andric // Only support 32 and 64 bit. 36480093f4SDimitry Andric if (!IsArch32Bit && !IsArch64Bit) 37480093f4SDimitry Andric llvm_unreachable("Unsupported bit width value."); 38480093f4SDimitry Andric 39480093f4SDimitry Andric // Specify the mode in which the as(1) command operates. 40480093f4SDimitry Andric if (IsArch32Bit) { 41480093f4SDimitry Andric CmdArgs.push_back("-a32"); 42480093f4SDimitry Andric } else { 43480093f4SDimitry Andric // Must be 64-bit, otherwise asserted already. 44480093f4SDimitry Andric CmdArgs.push_back("-a64"); 45480093f4SDimitry Andric } 46480093f4SDimitry Andric 47480093f4SDimitry Andric // Accept any mixture of instructions. 48480093f4SDimitry Andric // On Power for AIX and Linux, this behaviour matches that of GCC for both the 49480093f4SDimitry Andric // user-provided assembler source case and the compiler-produced assembler 50480093f4SDimitry Andric // source case. Yet XL with user-provided assembler source would not add this. 51480093f4SDimitry Andric CmdArgs.push_back("-many"); 52480093f4SDimitry Andric 53480093f4SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 54480093f4SDimitry Andric 55480093f4SDimitry Andric // Specify assembler output file. 56480093f4SDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 57480093f4SDimitry Andric if (Output.isFilename()) { 58480093f4SDimitry Andric CmdArgs.push_back("-o"); 59480093f4SDimitry Andric CmdArgs.push_back(Output.getFilename()); 60480093f4SDimitry Andric } 61480093f4SDimitry Andric 62480093f4SDimitry Andric // Specify assembler input file. 63480093f4SDimitry Andric // The system assembler on AIX takes exactly one input file. The driver is 64480093f4SDimitry Andric // expected to invoke as(1) separately for each assembler source input file. 65480093f4SDimitry Andric if (Inputs.size() != 1) 66480093f4SDimitry Andric llvm_unreachable("Invalid number of input files."); 67480093f4SDimitry Andric const InputInfo &II = Inputs[0]; 68480093f4SDimitry Andric assert((II.isFilename() || II.isNothing()) && "Invalid input."); 69480093f4SDimitry Andric if (II.isFilename()) 70480093f4SDimitry Andric CmdArgs.push_back(II.getFilename()); 71480093f4SDimitry Andric 72480093f4SDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 735ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 74*e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 75480093f4SDimitry Andric } 76480093f4SDimitry Andric 77480093f4SDimitry Andric void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, 78480093f4SDimitry Andric const InputInfo &Output, 79480093f4SDimitry Andric const InputInfoList &Inputs, const ArgList &Args, 80480093f4SDimitry Andric const char *LinkingOutput) const { 81480093f4SDimitry Andric const AIX &ToolChain = static_cast<const AIX &>(getToolChain()); 825ffd83dbSDimitry Andric const Driver &D = ToolChain.getDriver(); 83480093f4SDimitry Andric ArgStringList CmdArgs; 84480093f4SDimitry Andric 85480093f4SDimitry Andric const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit(); 86480093f4SDimitry Andric const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit(); 87480093f4SDimitry Andric // Only support 32 and 64 bit. 88480093f4SDimitry Andric if (!(IsArch32Bit || IsArch64Bit)) 89480093f4SDimitry Andric llvm_unreachable("Unsupported bit width value."); 90480093f4SDimitry Andric 91480093f4SDimitry Andric // Force static linking when "-static" is present. 92480093f4SDimitry Andric if (Args.hasArg(options::OPT_static)) 93480093f4SDimitry Andric CmdArgs.push_back("-bnso"); 94480093f4SDimitry Andric 95*e8d8bef9SDimitry Andric // Add options for shared libraries. 96*e8d8bef9SDimitry Andric if (Args.hasArg(options::OPT_shared)) { 97*e8d8bef9SDimitry Andric CmdArgs.push_back("-bM:SRE"); 98*e8d8bef9SDimitry Andric CmdArgs.push_back("-bnoentry"); 99*e8d8bef9SDimitry Andric } 100*e8d8bef9SDimitry Andric 101480093f4SDimitry Andric // Specify linker output file. 102480093f4SDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 103480093f4SDimitry Andric if (Output.isFilename()) { 104480093f4SDimitry Andric CmdArgs.push_back("-o"); 105480093f4SDimitry Andric CmdArgs.push_back(Output.getFilename()); 106480093f4SDimitry Andric } 107480093f4SDimitry Andric 108480093f4SDimitry Andric // Set linking mode (i.e., 32/64-bit) and the address of 109480093f4SDimitry Andric // text and data sections based on arch bit width. 110480093f4SDimitry Andric if (IsArch32Bit) { 111480093f4SDimitry Andric CmdArgs.push_back("-b32"); 112480093f4SDimitry Andric CmdArgs.push_back("-bpT:0x10000000"); 113480093f4SDimitry Andric CmdArgs.push_back("-bpD:0x20000000"); 114480093f4SDimitry Andric } else { 115480093f4SDimitry Andric // Must be 64-bit, otherwise asserted already. 116480093f4SDimitry Andric CmdArgs.push_back("-b64"); 117480093f4SDimitry Andric CmdArgs.push_back("-bpT:0x100000000"); 118480093f4SDimitry Andric CmdArgs.push_back("-bpD:0x110000000"); 119480093f4SDimitry Andric } 120480093f4SDimitry Andric 121480093f4SDimitry Andric auto getCrt0Basename = [&Args, IsArch32Bit] { 122480093f4SDimitry Andric // Enable gprofiling when "-pg" is specified. 123480093f4SDimitry Andric if (Args.hasArg(options::OPT_pg)) 124480093f4SDimitry Andric return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o"; 125480093f4SDimitry Andric // Enable profiling when "-p" is specified. 126480093f4SDimitry Andric else if (Args.hasArg(options::OPT_p)) 127480093f4SDimitry Andric return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o"; 128480093f4SDimitry Andric else 129480093f4SDimitry Andric return IsArch32Bit ? "crt0.o" : "crt0_64.o"; 130480093f4SDimitry Andric }; 131480093f4SDimitry Andric 132*e8d8bef9SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 133*e8d8bef9SDimitry Andric options::OPT_shared)) { 134480093f4SDimitry Andric CmdArgs.push_back( 135480093f4SDimitry Andric Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); 136*e8d8bef9SDimitry Andric 137*e8d8bef9SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 138*e8d8bef9SDimitry Andric ToolChain.GetFilePath(IsArch32Bit ? "crti.o" : "crti_64.o"))); 139480093f4SDimitry Andric } 140480093f4SDimitry Andric 141*e8d8bef9SDimitry Andric // Collect all static constructor and destructor functions in both C and CXX 142*e8d8bef9SDimitry Andric // language link invocations. This has to come before AddLinkerInputs as the 143*e8d8bef9SDimitry Andric // implied option needs to precede any other '-bcdtors' settings or 144*e8d8bef9SDimitry Andric // '-bnocdtors' that '-Wl' might forward. 1455ffd83dbSDimitry Andric CmdArgs.push_back("-bcdtors:all:0:s"); 1465ffd83dbSDimitry Andric 147480093f4SDimitry Andric // Specify linker input file(s). 148480093f4SDimitry Andric AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 149480093f4SDimitry Andric 150480093f4SDimitry Andric // Add directory to library search path. 151480093f4SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 152480093f4SDimitry Andric ToolChain.AddFilePathLibArgs(Args, CmdArgs); 153*e8d8bef9SDimitry Andric ToolChain.addProfileRTLibs(Args, CmdArgs); 154*e8d8bef9SDimitry Andric 155*e8d8bef9SDimitry Andric if (getToolChain().ShouldLinkCXXStdlib(Args)) 156*e8d8bef9SDimitry Andric getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); 157480093f4SDimitry Andric 158480093f4SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 159*e8d8bef9SDimitry Andric AddRunTimeLibs(ToolChain, D, CmdArgs, Args); 160*e8d8bef9SDimitry Andric 161480093f4SDimitry Andric // Support POSIX threads if "-pthreads" or "-pthread" is present. 162480093f4SDimitry Andric if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread)) 163480093f4SDimitry Andric CmdArgs.push_back("-lpthreads"); 164480093f4SDimitry Andric 165*e8d8bef9SDimitry Andric if (D.CCCIsCXX()) 166*e8d8bef9SDimitry Andric CmdArgs.push_back("-lm"); 167*e8d8bef9SDimitry Andric 168480093f4SDimitry Andric CmdArgs.push_back("-lc"); 169480093f4SDimitry Andric } 170480093f4SDimitry Andric 171480093f4SDimitry Andric const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 1725ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 173*e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 174480093f4SDimitry Andric } 175480093f4SDimitry Andric 176480093f4SDimitry Andric /// AIX - AIX tool chain which can call as(1) and ld(1) directly. 177480093f4SDimitry Andric AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 178480093f4SDimitry Andric : ToolChain(D, Triple, Args) { 179480093f4SDimitry Andric getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); 180480093f4SDimitry Andric } 181480093f4SDimitry Andric 1825ffd83dbSDimitry Andric // Returns the effective header sysroot path to use. 1835ffd83dbSDimitry Andric // This comes from either -isysroot or --sysroot. 1845ffd83dbSDimitry Andric llvm::StringRef 1855ffd83dbSDimitry Andric AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { 1865ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_isysroot)) 1875ffd83dbSDimitry Andric return DriverArgs.getLastArgValue(options::OPT_isysroot); 1885ffd83dbSDimitry Andric if (!getDriver().SysRoot.empty()) 1895ffd83dbSDimitry Andric return getDriver().SysRoot; 1905ffd83dbSDimitry Andric return "/"; 1915ffd83dbSDimitry Andric } 1925ffd83dbSDimitry Andric 1935ffd83dbSDimitry Andric void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 1945ffd83dbSDimitry Andric ArgStringList &CC1Args) const { 1955ffd83dbSDimitry Andric // Return if -nostdinc is specified as a driver option. 1965ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 1975ffd83dbSDimitry Andric return; 1985ffd83dbSDimitry Andric 1995ffd83dbSDimitry Andric llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); 2005ffd83dbSDimitry Andric const Driver &D = getDriver(); 2015ffd83dbSDimitry Andric 2025ffd83dbSDimitry Andric // Add the Clang builtin headers (<resource>/include). 2035ffd83dbSDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 2045ffd83dbSDimitry Andric SmallString<128> P(D.ResourceDir); 2055ffd83dbSDimitry Andric path::append(P, "/include"); 2065ffd83dbSDimitry Andric addSystemInclude(DriverArgs, CC1Args, P.str()); 2075ffd83dbSDimitry Andric } 2085ffd83dbSDimitry Andric 2095ffd83dbSDimitry Andric // Return if -nostdlibinc is specified as a driver option. 2105ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 2115ffd83dbSDimitry Andric return; 2125ffd83dbSDimitry Andric 2135ffd83dbSDimitry Andric // Add <sysroot>/usr/include. 2145ffd83dbSDimitry Andric SmallString<128> UP(Sysroot); 2155ffd83dbSDimitry Andric path::append(UP, "/usr/include"); 2165ffd83dbSDimitry Andric addSystemInclude(DriverArgs, CC1Args, UP.str()); 2175ffd83dbSDimitry Andric } 2185ffd83dbSDimitry Andric 219*e8d8bef9SDimitry Andric void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 220*e8d8bef9SDimitry Andric llvm::opt::ArgStringList &CmdArgs) const { 221*e8d8bef9SDimitry Andric switch (GetCXXStdlibType(Args)) { 222*e8d8bef9SDimitry Andric case ToolChain::CST_Libcxx: 223*e8d8bef9SDimitry Andric CmdArgs.push_back("-lc++"); 224*e8d8bef9SDimitry Andric return; 225*e8d8bef9SDimitry Andric case ToolChain::CST_Libstdcxx: 226*e8d8bef9SDimitry Andric llvm::report_fatal_error("linking libstdc++ unimplemented on AIX"); 227*e8d8bef9SDimitry Andric } 228*e8d8bef9SDimitry Andric 229*e8d8bef9SDimitry Andric llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); 230*e8d8bef9SDimitry Andric } 231*e8d8bef9SDimitry Andric 232*e8d8bef9SDimitry Andric ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const { 233*e8d8bef9SDimitry Andric return ToolChain::CST_Libcxx; 234*e8d8bef9SDimitry Andric } 235*e8d8bef9SDimitry Andric 236*e8d8bef9SDimitry Andric ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const { 237*e8d8bef9SDimitry Andric return ToolChain::RLT_CompilerRT; 238*e8d8bef9SDimitry Andric } 239*e8d8bef9SDimitry Andric 240480093f4SDimitry Andric auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } 241480093f4SDimitry Andric 242480093f4SDimitry Andric auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } 243