xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
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