1e5dd7070Spatrick //===--- AIX.cpp - AIX ToolChain Implementations ----------------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick 9e5dd7070Spatrick #include "AIX.h" 10e5dd7070Spatrick #include "Arch/PPC.h" 11e5dd7070Spatrick #include "CommonArgs.h" 12e5dd7070Spatrick #include "clang/Driver/Compilation.h" 13e5dd7070Spatrick #include "clang/Driver/Options.h" 14e5dd7070Spatrick #include "clang/Driver/SanitizerArgs.h" 15e5dd7070Spatrick #include "llvm/Option/ArgList.h" 16*ec727ea7Spatrick #include "llvm/Support/Path.h" 17e5dd7070Spatrick 18e5dd7070Spatrick using AIX = clang::driver::toolchains::AIX; 19e5dd7070Spatrick using namespace clang::driver; 20e5dd7070Spatrick using namespace clang::driver::tools; 21*ec727ea7Spatrick using namespace clang::driver::toolchains; 22e5dd7070Spatrick 23e5dd7070Spatrick using namespace llvm::opt; 24*ec727ea7Spatrick using namespace llvm::sys; 25e5dd7070Spatrick 26e5dd7070Spatrick void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 27e5dd7070Spatrick const InputInfo &Output, 28e5dd7070Spatrick const InputInfoList &Inputs, 29e5dd7070Spatrick const ArgList &Args, 30e5dd7070Spatrick const char *LinkingOutput) const { 31e5dd7070Spatrick ArgStringList CmdArgs; 32e5dd7070Spatrick 33e5dd7070Spatrick const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit(); 34e5dd7070Spatrick const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit(); 35e5dd7070Spatrick // Only support 32 and 64 bit. 36e5dd7070Spatrick if (!IsArch32Bit && !IsArch64Bit) 37e5dd7070Spatrick llvm_unreachable("Unsupported bit width value."); 38e5dd7070Spatrick 39e5dd7070Spatrick // Specify the mode in which the as(1) command operates. 40e5dd7070Spatrick if (IsArch32Bit) { 41e5dd7070Spatrick CmdArgs.push_back("-a32"); 42e5dd7070Spatrick } else { 43e5dd7070Spatrick // Must be 64-bit, otherwise asserted already. 44e5dd7070Spatrick CmdArgs.push_back("-a64"); 45e5dd7070Spatrick } 46e5dd7070Spatrick 47e5dd7070Spatrick // Accept an undefined symbol as an extern so that an error message is not 48e5dd7070Spatrick // displayed. Otherwise, undefined symbols are flagged with error messages. 49e5dd7070Spatrick // FIXME: This should be removed when the assembly generation from the 50e5dd7070Spatrick // compiler is able to write externs properly. 51e5dd7070Spatrick CmdArgs.push_back("-u"); 52e5dd7070Spatrick 53e5dd7070Spatrick // Accept any mixture of instructions. 54e5dd7070Spatrick // On Power for AIX and Linux, this behaviour matches that of GCC for both the 55e5dd7070Spatrick // user-provided assembler source case and the compiler-produced assembler 56e5dd7070Spatrick // source case. Yet XL with user-provided assembler source would not add this. 57e5dd7070Spatrick CmdArgs.push_back("-many"); 58e5dd7070Spatrick 59e5dd7070Spatrick Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 60e5dd7070Spatrick 61e5dd7070Spatrick // Specify assembler output file. 62e5dd7070Spatrick assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 63e5dd7070Spatrick if (Output.isFilename()) { 64e5dd7070Spatrick CmdArgs.push_back("-o"); 65e5dd7070Spatrick CmdArgs.push_back(Output.getFilename()); 66e5dd7070Spatrick } 67e5dd7070Spatrick 68e5dd7070Spatrick // Specify assembler input file. 69e5dd7070Spatrick // The system assembler on AIX takes exactly one input file. The driver is 70e5dd7070Spatrick // expected to invoke as(1) separately for each assembler source input file. 71e5dd7070Spatrick if (Inputs.size() != 1) 72e5dd7070Spatrick llvm_unreachable("Invalid number of input files."); 73e5dd7070Spatrick const InputInfo &II = Inputs[0]; 74e5dd7070Spatrick assert((II.isFilename() || II.isNothing()) && "Invalid input."); 75e5dd7070Spatrick if (II.isFilename()) 76e5dd7070Spatrick CmdArgs.push_back(II.getFilename()); 77e5dd7070Spatrick 78e5dd7070Spatrick const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 79*ec727ea7Spatrick C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 80*ec727ea7Spatrick Exec, CmdArgs, Inputs)); 81e5dd7070Spatrick } 82e5dd7070Spatrick 83e5dd7070Spatrick void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, 84e5dd7070Spatrick const InputInfo &Output, 85e5dd7070Spatrick const InputInfoList &Inputs, const ArgList &Args, 86e5dd7070Spatrick const char *LinkingOutput) const { 87e5dd7070Spatrick const AIX &ToolChain = static_cast<const AIX &>(getToolChain()); 88*ec727ea7Spatrick const Driver &D = ToolChain.getDriver(); 89e5dd7070Spatrick ArgStringList CmdArgs; 90e5dd7070Spatrick 91e5dd7070Spatrick const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit(); 92e5dd7070Spatrick const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit(); 93e5dd7070Spatrick // Only support 32 and 64 bit. 94e5dd7070Spatrick if (!(IsArch32Bit || IsArch64Bit)) 95e5dd7070Spatrick llvm_unreachable("Unsupported bit width value."); 96e5dd7070Spatrick 97e5dd7070Spatrick // Force static linking when "-static" is present. 98e5dd7070Spatrick if (Args.hasArg(options::OPT_static)) 99e5dd7070Spatrick CmdArgs.push_back("-bnso"); 100e5dd7070Spatrick 101e5dd7070Spatrick // Specify linker output file. 102e5dd7070Spatrick assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 103e5dd7070Spatrick if (Output.isFilename()) { 104e5dd7070Spatrick CmdArgs.push_back("-o"); 105e5dd7070Spatrick CmdArgs.push_back(Output.getFilename()); 106e5dd7070Spatrick } 107e5dd7070Spatrick 108e5dd7070Spatrick // Set linking mode (i.e., 32/64-bit) and the address of 109e5dd7070Spatrick // text and data sections based on arch bit width. 110e5dd7070Spatrick if (IsArch32Bit) { 111e5dd7070Spatrick CmdArgs.push_back("-b32"); 112e5dd7070Spatrick CmdArgs.push_back("-bpT:0x10000000"); 113e5dd7070Spatrick CmdArgs.push_back("-bpD:0x20000000"); 114e5dd7070Spatrick } else { 115e5dd7070Spatrick // Must be 64-bit, otherwise asserted already. 116e5dd7070Spatrick CmdArgs.push_back("-b64"); 117e5dd7070Spatrick CmdArgs.push_back("-bpT:0x100000000"); 118e5dd7070Spatrick CmdArgs.push_back("-bpD:0x110000000"); 119e5dd7070Spatrick } 120e5dd7070Spatrick 121e5dd7070Spatrick auto getCrt0Basename = [&Args, IsArch32Bit] { 122e5dd7070Spatrick // Enable gprofiling when "-pg" is specified. 123e5dd7070Spatrick if (Args.hasArg(options::OPT_pg)) 124e5dd7070Spatrick return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o"; 125e5dd7070Spatrick // Enable profiling when "-p" is specified. 126e5dd7070Spatrick else if (Args.hasArg(options::OPT_p)) 127e5dd7070Spatrick return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o"; 128e5dd7070Spatrick else 129e5dd7070Spatrick return IsArch32Bit ? "crt0.o" : "crt0_64.o"; 130e5dd7070Spatrick }; 131e5dd7070Spatrick 132e5dd7070Spatrick if (!Args.hasArg(options::OPT_nostdlib)) { 133e5dd7070Spatrick CmdArgs.push_back( 134e5dd7070Spatrick Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); 135e5dd7070Spatrick } 136e5dd7070Spatrick 137*ec727ea7Spatrick // Collect all static constructor and destructor functions in CXX mode. This 138*ec727ea7Spatrick // has to come before AddLinkerInputs as the implied option needs to precede 139*ec727ea7Spatrick // any other '-bcdtors' settings or '-bnocdtors' that '-Wl' might forward. 140*ec727ea7Spatrick if (D.CCCIsCXX()) 141*ec727ea7Spatrick CmdArgs.push_back("-bcdtors:all:0:s"); 142*ec727ea7Spatrick 143e5dd7070Spatrick // Specify linker input file(s). 144e5dd7070Spatrick AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 145e5dd7070Spatrick 146e5dd7070Spatrick // Add directory to library search path. 147e5dd7070Spatrick Args.AddAllArgs(CmdArgs, options::OPT_L); 148e5dd7070Spatrick ToolChain.AddFilePathLibArgs(Args, CmdArgs); 149e5dd7070Spatrick 150e5dd7070Spatrick if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 151e5dd7070Spatrick // Support POSIX threads if "-pthreads" or "-pthread" is present. 152e5dd7070Spatrick if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread)) 153e5dd7070Spatrick CmdArgs.push_back("-lpthreads"); 154e5dd7070Spatrick 155e5dd7070Spatrick CmdArgs.push_back("-lc"); 156e5dd7070Spatrick } 157e5dd7070Spatrick 158e5dd7070Spatrick const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 159*ec727ea7Spatrick C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 160*ec727ea7Spatrick Exec, CmdArgs, Inputs)); 161e5dd7070Spatrick } 162e5dd7070Spatrick 163e5dd7070Spatrick /// AIX - AIX tool chain which can call as(1) and ld(1) directly. 164e5dd7070Spatrick AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 165e5dd7070Spatrick : ToolChain(D, Triple, Args) { 166e5dd7070Spatrick getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); 167e5dd7070Spatrick } 168e5dd7070Spatrick 169*ec727ea7Spatrick // Returns the effective header sysroot path to use. 170*ec727ea7Spatrick // This comes from either -isysroot or --sysroot. 171*ec727ea7Spatrick llvm::StringRef 172*ec727ea7Spatrick AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { 173*ec727ea7Spatrick if (DriverArgs.hasArg(options::OPT_isysroot)) 174*ec727ea7Spatrick return DriverArgs.getLastArgValue(options::OPT_isysroot); 175*ec727ea7Spatrick if (!getDriver().SysRoot.empty()) 176*ec727ea7Spatrick return getDriver().SysRoot; 177*ec727ea7Spatrick return "/"; 178*ec727ea7Spatrick } 179*ec727ea7Spatrick 180*ec727ea7Spatrick void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 181*ec727ea7Spatrick ArgStringList &CC1Args) const { 182*ec727ea7Spatrick // Return if -nostdinc is specified as a driver option. 183*ec727ea7Spatrick if (DriverArgs.hasArg(options::OPT_nostdinc)) 184*ec727ea7Spatrick return; 185*ec727ea7Spatrick 186*ec727ea7Spatrick llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); 187*ec727ea7Spatrick const Driver &D = getDriver(); 188*ec727ea7Spatrick 189*ec727ea7Spatrick // Add the Clang builtin headers (<resource>/include). 190*ec727ea7Spatrick if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 191*ec727ea7Spatrick SmallString<128> P(D.ResourceDir); 192*ec727ea7Spatrick path::append(P, "/include"); 193*ec727ea7Spatrick addSystemInclude(DriverArgs, CC1Args, P.str()); 194*ec727ea7Spatrick } 195*ec727ea7Spatrick 196*ec727ea7Spatrick // Return if -nostdlibinc is specified as a driver option. 197*ec727ea7Spatrick if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 198*ec727ea7Spatrick return; 199*ec727ea7Spatrick 200*ec727ea7Spatrick // Add <sysroot>/usr/include. 201*ec727ea7Spatrick SmallString<128> UP(Sysroot); 202*ec727ea7Spatrick path::append(UP, "/usr/include"); 203*ec727ea7Spatrick addSystemInclude(DriverArgs, CC1Args, UP.str()); 204*ec727ea7Spatrick } 205*ec727ea7Spatrick 206e5dd7070Spatrick auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } 207e5dd7070Spatrick 208e5dd7070Spatrick auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } 209