xref: /openbsd-src/gnu/llvm/clang/lib/Driver/ToolChains/AIX.cpp (revision ec727ea710c91afd8ce4f788c5aaa8482b7b69b2)
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