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 101*349cc55cSDimitry Andric // Specify PGO linker option without LTO 102*349cc55cSDimitry Andric if (!D.isUsingLTO() && 103*349cc55cSDimitry Andric (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, 104*349cc55cSDimitry Andric false) || 105*349cc55cSDimitry Andric Args.hasFlag(options::OPT_fprofile_generate, 106*349cc55cSDimitry Andric options::OPT_fno_profile_generate, false) || 107*349cc55cSDimitry Andric Args.hasFlag(options::OPT_fprofile_generate_EQ, 108*349cc55cSDimitry Andric options::OPT_fno_profile_generate, false) || 109*349cc55cSDimitry Andric Args.hasFlag(options::OPT_fprofile_instr_generate, 110*349cc55cSDimitry Andric options::OPT_fno_profile_instr_generate, false) || 111*349cc55cSDimitry Andric Args.hasFlag(options::OPT_fprofile_instr_generate_EQ, 112*349cc55cSDimitry Andric options::OPT_fno_profile_instr_generate, false) || 113*349cc55cSDimitry Andric Args.hasFlag(options::OPT_fcs_profile_generate, 114*349cc55cSDimitry Andric options::OPT_fno_profile_generate, false) || 115*349cc55cSDimitry Andric Args.hasFlag(options::OPT_fcs_profile_generate_EQ, 116*349cc55cSDimitry Andric options::OPT_fno_profile_generate, false) || 117*349cc55cSDimitry Andric Args.hasArg(options::OPT_fcreate_profile) || 118*349cc55cSDimitry Andric Args.hasArg(options::OPT_coverage))) 119*349cc55cSDimitry Andric CmdArgs.push_back("-bdbg:namedsects"); 120*349cc55cSDimitry Andric 121480093f4SDimitry Andric // Specify linker output file. 122480093f4SDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 123480093f4SDimitry Andric if (Output.isFilename()) { 124480093f4SDimitry Andric CmdArgs.push_back("-o"); 125480093f4SDimitry Andric CmdArgs.push_back(Output.getFilename()); 126480093f4SDimitry Andric } 127480093f4SDimitry Andric 128480093f4SDimitry Andric // Set linking mode (i.e., 32/64-bit) and the address of 129480093f4SDimitry Andric // text and data sections based on arch bit width. 130480093f4SDimitry Andric if (IsArch32Bit) { 131480093f4SDimitry Andric CmdArgs.push_back("-b32"); 132480093f4SDimitry Andric CmdArgs.push_back("-bpT:0x10000000"); 133480093f4SDimitry Andric CmdArgs.push_back("-bpD:0x20000000"); 134480093f4SDimitry Andric } else { 135480093f4SDimitry Andric // Must be 64-bit, otherwise asserted already. 136480093f4SDimitry Andric CmdArgs.push_back("-b64"); 137480093f4SDimitry Andric CmdArgs.push_back("-bpT:0x100000000"); 138480093f4SDimitry Andric CmdArgs.push_back("-bpD:0x110000000"); 139480093f4SDimitry Andric } 140480093f4SDimitry Andric 141480093f4SDimitry Andric auto getCrt0Basename = [&Args, IsArch32Bit] { 142480093f4SDimitry Andric // Enable gprofiling when "-pg" is specified. 143480093f4SDimitry Andric if (Args.hasArg(options::OPT_pg)) 144480093f4SDimitry Andric return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o"; 145480093f4SDimitry Andric // Enable profiling when "-p" is specified. 146480093f4SDimitry Andric else if (Args.hasArg(options::OPT_p)) 147480093f4SDimitry Andric return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o"; 148480093f4SDimitry Andric else 149480093f4SDimitry Andric return IsArch32Bit ? "crt0.o" : "crt0_64.o"; 150480093f4SDimitry Andric }; 151480093f4SDimitry Andric 152e8d8bef9SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 153e8d8bef9SDimitry Andric options::OPT_shared)) { 154480093f4SDimitry Andric CmdArgs.push_back( 155480093f4SDimitry Andric Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); 156e8d8bef9SDimitry Andric 157e8d8bef9SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 158e8d8bef9SDimitry Andric ToolChain.GetFilePath(IsArch32Bit ? "crti.o" : "crti_64.o"))); 159480093f4SDimitry Andric } 160480093f4SDimitry Andric 161e8d8bef9SDimitry Andric // Collect all static constructor and destructor functions in both C and CXX 162e8d8bef9SDimitry Andric // language link invocations. This has to come before AddLinkerInputs as the 163e8d8bef9SDimitry Andric // implied option needs to precede any other '-bcdtors' settings or 164e8d8bef9SDimitry Andric // '-bnocdtors' that '-Wl' might forward. 1655ffd83dbSDimitry Andric CmdArgs.push_back("-bcdtors:all:0:s"); 1665ffd83dbSDimitry Andric 167480093f4SDimitry Andric // Specify linker input file(s). 168480093f4SDimitry Andric AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 169480093f4SDimitry Andric 170480093f4SDimitry Andric // Add directory to library search path. 171480093f4SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 172480093f4SDimitry Andric ToolChain.AddFilePathLibArgs(Args, CmdArgs); 173e8d8bef9SDimitry Andric ToolChain.addProfileRTLibs(Args, CmdArgs); 174e8d8bef9SDimitry Andric 175e8d8bef9SDimitry Andric if (getToolChain().ShouldLinkCXXStdlib(Args)) 176e8d8bef9SDimitry Andric getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); 177480093f4SDimitry Andric 178480093f4SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 179e8d8bef9SDimitry Andric AddRunTimeLibs(ToolChain, D, CmdArgs, Args); 180e8d8bef9SDimitry Andric 181480093f4SDimitry Andric // Support POSIX threads if "-pthreads" or "-pthread" is present. 182480093f4SDimitry Andric if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread)) 183480093f4SDimitry Andric CmdArgs.push_back("-lpthreads"); 184480093f4SDimitry Andric 185e8d8bef9SDimitry Andric if (D.CCCIsCXX()) 186e8d8bef9SDimitry Andric CmdArgs.push_back("-lm"); 187e8d8bef9SDimitry Andric 188480093f4SDimitry Andric CmdArgs.push_back("-lc"); 189480093f4SDimitry Andric } 190480093f4SDimitry Andric 191480093f4SDimitry Andric const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 1925ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 193e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 194480093f4SDimitry Andric } 195480093f4SDimitry Andric 196480093f4SDimitry Andric /// AIX - AIX tool chain which can call as(1) and ld(1) directly. 197480093f4SDimitry Andric AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 198480093f4SDimitry Andric : ToolChain(D, Triple, Args) { 199fe6060f1SDimitry Andric ParseInlineAsmUsingAsmParser = Args.hasFlag( 200fe6060f1SDimitry Andric options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true); 201fe6060f1SDimitry Andric getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib"); 202480093f4SDimitry Andric } 203480093f4SDimitry Andric 2045ffd83dbSDimitry Andric // Returns the effective header sysroot path to use. 2055ffd83dbSDimitry Andric // This comes from either -isysroot or --sysroot. 2065ffd83dbSDimitry Andric llvm::StringRef 2075ffd83dbSDimitry Andric AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { 2085ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_isysroot)) 2095ffd83dbSDimitry Andric return DriverArgs.getLastArgValue(options::OPT_isysroot); 2105ffd83dbSDimitry Andric if (!getDriver().SysRoot.empty()) 2115ffd83dbSDimitry Andric return getDriver().SysRoot; 2125ffd83dbSDimitry Andric return "/"; 2135ffd83dbSDimitry Andric } 2145ffd83dbSDimitry Andric 2155ffd83dbSDimitry Andric void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 2165ffd83dbSDimitry Andric ArgStringList &CC1Args) const { 2175ffd83dbSDimitry Andric // Return if -nostdinc is specified as a driver option. 2185ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) 2195ffd83dbSDimitry Andric return; 2205ffd83dbSDimitry Andric 2215ffd83dbSDimitry Andric llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); 2225ffd83dbSDimitry Andric const Driver &D = getDriver(); 2235ffd83dbSDimitry Andric 2245ffd83dbSDimitry Andric // Add the Clang builtin headers (<resource>/include). 2255ffd83dbSDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 2265ffd83dbSDimitry Andric SmallString<128> P(D.ResourceDir); 2275ffd83dbSDimitry Andric path::append(P, "/include"); 2285ffd83dbSDimitry Andric addSystemInclude(DriverArgs, CC1Args, P.str()); 2295ffd83dbSDimitry Andric } 2305ffd83dbSDimitry Andric 2315ffd83dbSDimitry Andric // Return if -nostdlibinc is specified as a driver option. 2325ffd83dbSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 2335ffd83dbSDimitry Andric return; 2345ffd83dbSDimitry Andric 2355ffd83dbSDimitry Andric // Add <sysroot>/usr/include. 2365ffd83dbSDimitry Andric SmallString<128> UP(Sysroot); 2375ffd83dbSDimitry Andric path::append(UP, "/usr/include"); 2385ffd83dbSDimitry Andric addSystemInclude(DriverArgs, CC1Args, UP.str()); 2395ffd83dbSDimitry Andric } 2405ffd83dbSDimitry Andric 241*349cc55cSDimitry Andric void AIX::AddClangCXXStdlibIncludeArgs( 242*349cc55cSDimitry Andric const llvm::opt::ArgList &DriverArgs, 243*349cc55cSDimitry Andric llvm::opt::ArgStringList &CC1Args) const { 244*349cc55cSDimitry Andric 245*349cc55cSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc) || 246*349cc55cSDimitry Andric DriverArgs.hasArg(options::OPT_nostdincxx) || 247*349cc55cSDimitry Andric DriverArgs.hasArg(options::OPT_nostdlibinc)) 248*349cc55cSDimitry Andric return; 249*349cc55cSDimitry Andric 250*349cc55cSDimitry Andric switch (GetCXXStdlibType(DriverArgs)) { 251*349cc55cSDimitry Andric case ToolChain::CST_Libstdcxx: 252*349cc55cSDimitry Andric llvm::report_fatal_error( 253*349cc55cSDimitry Andric "picking up libstdc++ headers is unimplemented on AIX"); 254*349cc55cSDimitry Andric case ToolChain::CST_Libcxx: { 255*349cc55cSDimitry Andric llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); 256*349cc55cSDimitry Andric SmallString<128> PathCPP(Sysroot); 257*349cc55cSDimitry Andric llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++", 258*349cc55cSDimitry Andric "v1"); 259*349cc55cSDimitry Andric addSystemInclude(DriverArgs, CC1Args, PathCPP.str()); 260*349cc55cSDimitry Andric // Required in order to suppress conflicting C++ overloads in the system 261*349cc55cSDimitry Andric // libc headers that were used by XL C++. 262*349cc55cSDimitry Andric CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__"); 263*349cc55cSDimitry Andric return; 264*349cc55cSDimitry Andric } 265*349cc55cSDimitry Andric } 266*349cc55cSDimitry Andric 267*349cc55cSDimitry Andric llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); 268*349cc55cSDimitry Andric } 269*349cc55cSDimitry Andric 270e8d8bef9SDimitry Andric void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 271e8d8bef9SDimitry Andric llvm::opt::ArgStringList &CmdArgs) const { 272e8d8bef9SDimitry Andric switch (GetCXXStdlibType(Args)) { 273*349cc55cSDimitry Andric case ToolChain::CST_Libstdcxx: 274*349cc55cSDimitry Andric llvm::report_fatal_error("linking libstdc++ unimplemented on AIX"); 275e8d8bef9SDimitry Andric case ToolChain::CST_Libcxx: 276e8d8bef9SDimitry Andric CmdArgs.push_back("-lc++"); 277fe6060f1SDimitry Andric CmdArgs.push_back("-lc++abi"); 278e8d8bef9SDimitry Andric return; 279e8d8bef9SDimitry Andric } 280e8d8bef9SDimitry Andric 281e8d8bef9SDimitry Andric llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); 282e8d8bef9SDimitry Andric } 283e8d8bef9SDimitry Andric 284e8d8bef9SDimitry Andric ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const { 285e8d8bef9SDimitry Andric return ToolChain::CST_Libcxx; 286e8d8bef9SDimitry Andric } 287e8d8bef9SDimitry Andric 288e8d8bef9SDimitry Andric ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const { 289e8d8bef9SDimitry Andric return ToolChain::RLT_CompilerRT; 290e8d8bef9SDimitry Andric } 291e8d8bef9SDimitry Andric 292480093f4SDimitry Andric auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } 293480093f4SDimitry Andric 294480093f4SDimitry Andric auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } 295