1*480093f4SDimitry Andric //===--- AIX.cpp - AIX ToolChain Implementations ----------------*- C++ -*-===// 2*480093f4SDimitry Andric // 3*480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*480093f4SDimitry Andric // 7*480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8*480093f4SDimitry Andric 9*480093f4SDimitry Andric #include "AIX.h" 10*480093f4SDimitry Andric #include "Arch/PPC.h" 11*480093f4SDimitry Andric #include "CommonArgs.h" 12*480093f4SDimitry Andric #include "clang/Driver/Compilation.h" 13*480093f4SDimitry Andric #include "clang/Driver/Options.h" 14*480093f4SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 15*480093f4SDimitry Andric #include "llvm/Option/ArgList.h" 16*480093f4SDimitry Andric 17*480093f4SDimitry Andric using AIX = clang::driver::toolchains::AIX; 18*480093f4SDimitry Andric using namespace clang::driver; 19*480093f4SDimitry Andric using namespace clang::driver::tools; 20*480093f4SDimitry Andric 21*480093f4SDimitry Andric using namespace llvm::opt; 22*480093f4SDimitry Andric 23*480093f4SDimitry Andric void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 24*480093f4SDimitry Andric const InputInfo &Output, 25*480093f4SDimitry Andric const InputInfoList &Inputs, 26*480093f4SDimitry Andric const ArgList &Args, 27*480093f4SDimitry Andric const char *LinkingOutput) const { 28*480093f4SDimitry Andric ArgStringList CmdArgs; 29*480093f4SDimitry Andric 30*480093f4SDimitry Andric const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit(); 31*480093f4SDimitry Andric const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit(); 32*480093f4SDimitry Andric // Only support 32 and 64 bit. 33*480093f4SDimitry Andric if (!IsArch32Bit && !IsArch64Bit) 34*480093f4SDimitry Andric llvm_unreachable("Unsupported bit width value."); 35*480093f4SDimitry Andric 36*480093f4SDimitry Andric // Specify the mode in which the as(1) command operates. 37*480093f4SDimitry Andric if (IsArch32Bit) { 38*480093f4SDimitry Andric CmdArgs.push_back("-a32"); 39*480093f4SDimitry Andric } else { 40*480093f4SDimitry Andric // Must be 64-bit, otherwise asserted already. 41*480093f4SDimitry Andric CmdArgs.push_back("-a64"); 42*480093f4SDimitry Andric } 43*480093f4SDimitry Andric 44*480093f4SDimitry Andric // Accept an undefined symbol as an extern so that an error message is not 45*480093f4SDimitry Andric // displayed. Otherwise, undefined symbols are flagged with error messages. 46*480093f4SDimitry Andric // FIXME: This should be removed when the assembly generation from the 47*480093f4SDimitry Andric // compiler is able to write externs properly. 48*480093f4SDimitry Andric CmdArgs.push_back("-u"); 49*480093f4SDimitry Andric 50*480093f4SDimitry Andric // Accept any mixture of instructions. 51*480093f4SDimitry Andric // On Power for AIX and Linux, this behaviour matches that of GCC for both the 52*480093f4SDimitry Andric // user-provided assembler source case and the compiler-produced assembler 53*480093f4SDimitry Andric // source case. Yet XL with user-provided assembler source would not add this. 54*480093f4SDimitry Andric CmdArgs.push_back("-many"); 55*480093f4SDimitry Andric 56*480093f4SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 57*480093f4SDimitry Andric 58*480093f4SDimitry Andric // Specify assembler output file. 59*480093f4SDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 60*480093f4SDimitry Andric if (Output.isFilename()) { 61*480093f4SDimitry Andric CmdArgs.push_back("-o"); 62*480093f4SDimitry Andric CmdArgs.push_back(Output.getFilename()); 63*480093f4SDimitry Andric } 64*480093f4SDimitry Andric 65*480093f4SDimitry Andric // Specify assembler input file. 66*480093f4SDimitry Andric // The system assembler on AIX takes exactly one input file. The driver is 67*480093f4SDimitry Andric // expected to invoke as(1) separately for each assembler source input file. 68*480093f4SDimitry Andric if (Inputs.size() != 1) 69*480093f4SDimitry Andric llvm_unreachable("Invalid number of input files."); 70*480093f4SDimitry Andric const InputInfo &II = Inputs[0]; 71*480093f4SDimitry Andric assert((II.isFilename() || II.isNothing()) && "Invalid input."); 72*480093f4SDimitry Andric if (II.isFilename()) 73*480093f4SDimitry Andric CmdArgs.push_back(II.getFilename()); 74*480093f4SDimitry Andric 75*480093f4SDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 76*480093f4SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 77*480093f4SDimitry Andric } 78*480093f4SDimitry Andric 79*480093f4SDimitry Andric void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, 80*480093f4SDimitry Andric const InputInfo &Output, 81*480093f4SDimitry Andric const InputInfoList &Inputs, const ArgList &Args, 82*480093f4SDimitry Andric const char *LinkingOutput) const { 83*480093f4SDimitry Andric const AIX &ToolChain = static_cast<const AIX &>(getToolChain()); 84*480093f4SDimitry Andric ArgStringList CmdArgs; 85*480093f4SDimitry Andric 86*480093f4SDimitry Andric const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit(); 87*480093f4SDimitry Andric const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit(); 88*480093f4SDimitry Andric // Only support 32 and 64 bit. 89*480093f4SDimitry Andric if (!(IsArch32Bit || IsArch64Bit)) 90*480093f4SDimitry Andric llvm_unreachable("Unsupported bit width value."); 91*480093f4SDimitry Andric 92*480093f4SDimitry Andric // Force static linking when "-static" is present. 93*480093f4SDimitry Andric if (Args.hasArg(options::OPT_static)) 94*480093f4SDimitry Andric CmdArgs.push_back("-bnso"); 95*480093f4SDimitry Andric 96*480093f4SDimitry Andric // Specify linker output file. 97*480093f4SDimitry Andric assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); 98*480093f4SDimitry Andric if (Output.isFilename()) { 99*480093f4SDimitry Andric CmdArgs.push_back("-o"); 100*480093f4SDimitry Andric CmdArgs.push_back(Output.getFilename()); 101*480093f4SDimitry Andric } 102*480093f4SDimitry Andric 103*480093f4SDimitry Andric // Set linking mode (i.e., 32/64-bit) and the address of 104*480093f4SDimitry Andric // text and data sections based on arch bit width. 105*480093f4SDimitry Andric if (IsArch32Bit) { 106*480093f4SDimitry Andric CmdArgs.push_back("-b32"); 107*480093f4SDimitry Andric CmdArgs.push_back("-bpT:0x10000000"); 108*480093f4SDimitry Andric CmdArgs.push_back("-bpD:0x20000000"); 109*480093f4SDimitry Andric } else { 110*480093f4SDimitry Andric // Must be 64-bit, otherwise asserted already. 111*480093f4SDimitry Andric CmdArgs.push_back("-b64"); 112*480093f4SDimitry Andric CmdArgs.push_back("-bpT:0x100000000"); 113*480093f4SDimitry Andric CmdArgs.push_back("-bpD:0x110000000"); 114*480093f4SDimitry Andric } 115*480093f4SDimitry Andric 116*480093f4SDimitry Andric auto getCrt0Basename = [&Args, IsArch32Bit] { 117*480093f4SDimitry Andric // Enable gprofiling when "-pg" is specified. 118*480093f4SDimitry Andric if (Args.hasArg(options::OPT_pg)) 119*480093f4SDimitry Andric return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o"; 120*480093f4SDimitry Andric // Enable profiling when "-p" is specified. 121*480093f4SDimitry Andric else if (Args.hasArg(options::OPT_p)) 122*480093f4SDimitry Andric return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o"; 123*480093f4SDimitry Andric else 124*480093f4SDimitry Andric return IsArch32Bit ? "crt0.o" : "crt0_64.o"; 125*480093f4SDimitry Andric }; 126*480093f4SDimitry Andric 127*480093f4SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib)) { 128*480093f4SDimitry Andric CmdArgs.push_back( 129*480093f4SDimitry Andric Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); 130*480093f4SDimitry Andric } 131*480093f4SDimitry Andric 132*480093f4SDimitry Andric // Specify linker input file(s). 133*480093f4SDimitry Andric AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 134*480093f4SDimitry Andric 135*480093f4SDimitry Andric // Add directory to library search path. 136*480093f4SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 137*480093f4SDimitry Andric ToolChain.AddFilePathLibArgs(Args, CmdArgs); 138*480093f4SDimitry Andric 139*480093f4SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 140*480093f4SDimitry Andric // Support POSIX threads if "-pthreads" or "-pthread" is present. 141*480093f4SDimitry Andric if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread)) 142*480093f4SDimitry Andric CmdArgs.push_back("-lpthreads"); 143*480093f4SDimitry Andric 144*480093f4SDimitry Andric CmdArgs.push_back("-lc"); 145*480093f4SDimitry Andric } 146*480093f4SDimitry Andric 147*480093f4SDimitry Andric const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 148*480093f4SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 149*480093f4SDimitry Andric } 150*480093f4SDimitry Andric 151*480093f4SDimitry Andric /// AIX - AIX tool chain which can call as(1) and ld(1) directly. 152*480093f4SDimitry Andric AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 153*480093f4SDimitry Andric : ToolChain(D, Triple, Args) { 154*480093f4SDimitry Andric getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); 155*480093f4SDimitry Andric } 156*480093f4SDimitry Andric 157*480093f4SDimitry Andric auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } 158*480093f4SDimitry Andric 159*480093f4SDimitry Andric auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } 160