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" 16*5ffd83dbSDimitry 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; 21*5ffd83dbSDimitry Andric using namespace clang::driver::toolchains; 22480093f4SDimitry Andric 23480093f4SDimitry Andric using namespace llvm::opt; 24*5ffd83dbSDimitry 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 an undefined symbol as an extern so that an error message is not 48480093f4SDimitry Andric // displayed. Otherwise, undefined symbols are flagged with error messages. 49480093f4SDimitry Andric // FIXME: This should be removed when the assembly generation from the 50480093f4SDimitry Andric // compiler is able to write externs properly. 51480093f4SDimitry Andric CmdArgs.push_back("-u"); 52480093f4SDimitry Andric 53480093f4SDimitry Andric // Accept any mixture of instructions. 54480093f4SDimitry Andric // On Power for AIX and Linux, this behaviour matches that of GCC for both the 55480093f4SDimitry Andric // user-provided assembler source case and the compiler-produced assembler 56480093f4SDimitry Andric // source case. Yet XL with user-provided assembler source would not add this. 57480093f4SDimitry Andric CmdArgs.push_back("-many"); 58480093f4SDimitry Andric 59480093f4SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 60480093f4SDimitry Andric 61480093f4SDimitry Andric // Specify assembler output file. 62480093f4SDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 63480093f4SDimitry Andric if (Output.isFilename()) { 64480093f4SDimitry Andric CmdArgs.push_back("-o"); 65480093f4SDimitry Andric CmdArgs.push_back(Output.getFilename()); 66480093f4SDimitry Andric } 67480093f4SDimitry Andric 68480093f4SDimitry Andric // Specify assembler input file. 69480093f4SDimitry Andric // The system assembler on AIX takes exactly one input file. The driver is 70480093f4SDimitry Andric // expected to invoke as(1) separately for each assembler source input file. 71480093f4SDimitry Andric if (Inputs.size() != 1) 72480093f4SDimitry Andric llvm_unreachable("Invalid number of input files."); 73480093f4SDimitry Andric const InputInfo &II = Inputs[0]; 74480093f4SDimitry Andric assert((II.isFilename() || II.isNothing()) && "Invalid input."); 75480093f4SDimitry Andric if (II.isFilename()) 76480093f4SDimitry Andric CmdArgs.push_back(II.getFilename()); 77480093f4SDimitry Andric 78480093f4SDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 79*5ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 80*5ffd83dbSDimitry Andric Exec, CmdArgs, Inputs)); 81480093f4SDimitry Andric } 82480093f4SDimitry Andric 83480093f4SDimitry Andric void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, 84480093f4SDimitry Andric const InputInfo &Output, 85480093f4SDimitry Andric const InputInfoList &Inputs, const ArgList &Args, 86480093f4SDimitry Andric const char *LinkingOutput) const { 87480093f4SDimitry Andric const AIX &ToolChain = static_cast<const AIX &>(getToolChain()); 88*5ffd83dbSDimitry Andric const Driver &D = ToolChain.getDriver(); 89480093f4SDimitry Andric ArgStringList CmdArgs; 90480093f4SDimitry Andric 91480093f4SDimitry Andric const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit(); 92480093f4SDimitry Andric const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit(); 93480093f4SDimitry Andric // Only support 32 and 64 bit. 94480093f4SDimitry Andric if (!(IsArch32Bit || IsArch64Bit)) 95480093f4SDimitry Andric llvm_unreachable("Unsupported bit width value."); 96480093f4SDimitry Andric 97480093f4SDimitry Andric // Force static linking when "-static" is present. 98480093f4SDimitry Andric if (Args.hasArg(options::OPT_static)) 99480093f4SDimitry Andric CmdArgs.push_back("-bnso"); 100480093f4SDimitry 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 132480093f4SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib)) { 133480093f4SDimitry Andric CmdArgs.push_back( 134480093f4SDimitry Andric Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); 135480093f4SDimitry Andric } 136480093f4SDimitry Andric 137*5ffd83dbSDimitry Andric // Collect all static constructor and destructor functions in CXX mode. This 138*5ffd83dbSDimitry Andric // has to come before AddLinkerInputs as the implied option needs to precede 139*5ffd83dbSDimitry Andric // any other '-bcdtors' settings or '-bnocdtors' that '-Wl' might forward. 140*5ffd83dbSDimitry Andric if (D.CCCIsCXX()) 141*5ffd83dbSDimitry Andric CmdArgs.push_back("-bcdtors:all:0:s"); 142*5ffd83dbSDimitry Andric 143480093f4SDimitry Andric // Specify linker input file(s). 144480093f4SDimitry Andric AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 145480093f4SDimitry Andric 146480093f4SDimitry Andric // Add directory to library search path. 147480093f4SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 148480093f4SDimitry Andric ToolChain.AddFilePathLibArgs(Args, CmdArgs); 149480093f4SDimitry Andric 150480093f4SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 151480093f4SDimitry Andric // Support POSIX threads if "-pthreads" or "-pthread" is present. 152480093f4SDimitry Andric if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread)) 153480093f4SDimitry Andric CmdArgs.push_back("-lpthreads"); 154480093f4SDimitry Andric 155480093f4SDimitry Andric CmdArgs.push_back("-lc"); 156480093f4SDimitry Andric } 157480093f4SDimitry Andric 158480093f4SDimitry Andric const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 159*5ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 160*5ffd83dbSDimitry Andric Exec, CmdArgs, Inputs)); 161480093f4SDimitry Andric } 162480093f4SDimitry Andric 163480093f4SDimitry Andric /// AIX - AIX tool chain which can call as(1) and ld(1) directly. 164480093f4SDimitry Andric AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 165480093f4SDimitry Andric : ToolChain(D, Triple, Args) { 166480093f4SDimitry Andric getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); 167480093f4SDimitry Andric } 168480093f4SDimitry Andric 169*5ffd83dbSDimitry Andric // Returns the effective header sysroot path to use. 170*5ffd83dbSDimitry Andric // This comes from either -isysroot or --sysroot. 171*5ffd83dbSDimitry Andric llvm::StringRef 172*5ffd83dbSDimitry Andric AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { 173*5ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_isysroot)) 174*5ffd83dbSDimitry Andric return DriverArgs.getLastArgValue(options::OPT_isysroot); 175*5ffd83dbSDimitry Andric if (!getDriver().SysRoot.empty()) 176*5ffd83dbSDimitry Andric return getDriver().SysRoot; 177*5ffd83dbSDimitry Andric return "/"; 178*5ffd83dbSDimitry Andric } 179*5ffd83dbSDimitry Andric 180*5ffd83dbSDimitry Andric void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 181*5ffd83dbSDimitry Andric ArgStringList &CC1Args) const { 182*5ffd83dbSDimitry Andric // Return if -nostdinc is specified as a driver option. 183*5ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 184*5ffd83dbSDimitry Andric return; 185*5ffd83dbSDimitry Andric 186*5ffd83dbSDimitry Andric llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); 187*5ffd83dbSDimitry Andric const Driver &D = getDriver(); 188*5ffd83dbSDimitry Andric 189*5ffd83dbSDimitry Andric // Add the Clang builtin headers (<resource>/include). 190*5ffd83dbSDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 191*5ffd83dbSDimitry Andric SmallString<128> P(D.ResourceDir); 192*5ffd83dbSDimitry Andric path::append(P, "/include"); 193*5ffd83dbSDimitry Andric addSystemInclude(DriverArgs, CC1Args, P.str()); 194*5ffd83dbSDimitry Andric } 195*5ffd83dbSDimitry Andric 196*5ffd83dbSDimitry Andric // Return if -nostdlibinc is specified as a driver option. 197*5ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 198*5ffd83dbSDimitry Andric return; 199*5ffd83dbSDimitry Andric 200*5ffd83dbSDimitry Andric // Add <sysroot>/usr/include. 201*5ffd83dbSDimitry Andric SmallString<128> UP(Sysroot); 202*5ffd83dbSDimitry Andric path::append(UP, "/usr/include"); 203*5ffd83dbSDimitry Andric addSystemInclude(DriverArgs, CC1Args, UP.str()); 204*5ffd83dbSDimitry Andric } 205*5ffd83dbSDimitry Andric 206480093f4SDimitry Andric auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } 207480093f4SDimitry Andric 208480093f4SDimitry Andric auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } 209