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(), 74e8d8bef9SDimitry 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 95e8d8bef9SDimitry Andric // Add options for shared libraries. 96e8d8bef9SDimitry Andric if (Args.hasArg(options::OPT_shared)) { 97e8d8bef9SDimitry Andric CmdArgs.push_back("-bM:SRE"); 98e8d8bef9SDimitry Andric CmdArgs.push_back("-bnoentry"); 99e8d8bef9SDimitry Andric } 100e8d8bef9SDimitry 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 132e8d8bef9SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 133e8d8bef9SDimitry Andric options::OPT_shared)) { 134480093f4SDimitry Andric CmdArgs.push_back( 135480093f4SDimitry Andric Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); 136e8d8bef9SDimitry Andric 137e8d8bef9SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 138e8d8bef9SDimitry Andric ToolChain.GetFilePath(IsArch32Bit ? "crti.o" : "crti_64.o"))); 139480093f4SDimitry Andric } 140480093f4SDimitry Andric 141e8d8bef9SDimitry Andric // Collect all static constructor and destructor functions in both C and CXX 142e8d8bef9SDimitry Andric // language link invocations. This has to come before AddLinkerInputs as the 143e8d8bef9SDimitry Andric // implied option needs to precede any other '-bcdtors' settings or 144e8d8bef9SDimitry 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); 153e8d8bef9SDimitry Andric ToolChain.addProfileRTLibs(Args, CmdArgs); 154e8d8bef9SDimitry Andric 155e8d8bef9SDimitry Andric if (getToolChain().ShouldLinkCXXStdlib(Args)) 156e8d8bef9SDimitry Andric getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); 157480093f4SDimitry Andric 158480093f4SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 159e8d8bef9SDimitry Andric AddRunTimeLibs(ToolChain, D, CmdArgs, Args); 160e8d8bef9SDimitry 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 165e8d8bef9SDimitry Andric if (D.CCCIsCXX()) 166e8d8bef9SDimitry Andric CmdArgs.push_back("-lm"); 167e8d8bef9SDimitry 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(), 173e8d8bef9SDimitry 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) { 179*fe6060f1SDimitry Andric ParseInlineAsmUsingAsmParser = Args.hasFlag( 180*fe6060f1SDimitry Andric options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true); 181*fe6060f1SDimitry Andric getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib"); 182480093f4SDimitry Andric } 183480093f4SDimitry Andric 1845ffd83dbSDimitry Andric // Returns the effective header sysroot path to use. 1855ffd83dbSDimitry Andric // This comes from either -isysroot or --sysroot. 1865ffd83dbSDimitry Andric llvm::StringRef 1875ffd83dbSDimitry Andric AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { 1885ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_isysroot)) 1895ffd83dbSDimitry Andric return DriverArgs.getLastArgValue(options::OPT_isysroot); 1905ffd83dbSDimitry Andric if (!getDriver().SysRoot.empty()) 1915ffd83dbSDimitry Andric return getDriver().SysRoot; 1925ffd83dbSDimitry Andric return "/"; 1935ffd83dbSDimitry Andric } 1945ffd83dbSDimitry Andric 1955ffd83dbSDimitry Andric void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 1965ffd83dbSDimitry Andric ArgStringList &CC1Args) const { 1975ffd83dbSDimitry Andric // Return if -nostdinc is specified as a driver option. 1985ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 1995ffd83dbSDimitry Andric return; 2005ffd83dbSDimitry Andric 2015ffd83dbSDimitry Andric llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); 2025ffd83dbSDimitry Andric const Driver &D = getDriver(); 2035ffd83dbSDimitry Andric 2045ffd83dbSDimitry Andric // Add the Clang builtin headers (<resource>/include). 2055ffd83dbSDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 2065ffd83dbSDimitry Andric SmallString<128> P(D.ResourceDir); 2075ffd83dbSDimitry Andric path::append(P, "/include"); 2085ffd83dbSDimitry Andric addSystemInclude(DriverArgs, CC1Args, P.str()); 2095ffd83dbSDimitry Andric } 2105ffd83dbSDimitry Andric 2115ffd83dbSDimitry Andric // Return if -nostdlibinc is specified as a driver option. 2125ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 2135ffd83dbSDimitry Andric return; 2145ffd83dbSDimitry Andric 2155ffd83dbSDimitry Andric // Add <sysroot>/usr/include. 2165ffd83dbSDimitry Andric SmallString<128> UP(Sysroot); 2175ffd83dbSDimitry Andric path::append(UP, "/usr/include"); 2185ffd83dbSDimitry Andric addSystemInclude(DriverArgs, CC1Args, UP.str()); 2195ffd83dbSDimitry Andric } 2205ffd83dbSDimitry Andric 221e8d8bef9SDimitry Andric void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 222e8d8bef9SDimitry Andric llvm::opt::ArgStringList &CmdArgs) const { 223e8d8bef9SDimitry Andric switch (GetCXXStdlibType(Args)) { 224e8d8bef9SDimitry Andric case ToolChain::CST_Libcxx: 225e8d8bef9SDimitry Andric CmdArgs.push_back("-lc++"); 226*fe6060f1SDimitry Andric CmdArgs.push_back("-lc++abi"); 227e8d8bef9SDimitry Andric return; 228e8d8bef9SDimitry Andric case ToolChain::CST_Libstdcxx: 229e8d8bef9SDimitry Andric llvm::report_fatal_error("linking libstdc++ unimplemented on AIX"); 230e8d8bef9SDimitry Andric } 231e8d8bef9SDimitry Andric 232e8d8bef9SDimitry Andric llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); 233e8d8bef9SDimitry Andric } 234e8d8bef9SDimitry Andric 235e8d8bef9SDimitry Andric ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const { 236e8d8bef9SDimitry Andric return ToolChain::CST_Libcxx; 237e8d8bef9SDimitry Andric } 238e8d8bef9SDimitry Andric 239e8d8bef9SDimitry Andric ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const { 240e8d8bef9SDimitry Andric return ToolChain::RLT_CompilerRT; 241e8d8bef9SDimitry Andric } 242e8d8bef9SDimitry Andric 243480093f4SDimitry Andric auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } 244480093f4SDimitry Andric 245480093f4SDimitry Andric auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } 246