[docs] Fix build-docs.sh
[llvm-project.git] / clang / lib / Driver / ToolChains / AIX.cpp
blob653fbeaffbd4ec2f5c72dc7e51b8f5d5a285a863
1 //===--- AIX.cpp - AIX ToolChain Implementations ----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "AIX.h"
10 #include "Arch/PPC.h"
11 #include "CommonArgs.h"
12 #include "clang/Driver/Compilation.h"
13 #include "clang/Driver/Options.h"
14 #include "clang/Driver/SanitizerArgs.h"
15 #include "llvm/Option/ArgList.h"
16 #include "llvm/Support/Path.h"
18 using AIX = clang::driver::toolchains::AIX;
19 using namespace clang::driver;
20 using namespace clang::driver::tools;
21 using namespace clang::driver::toolchains;
23 using namespace llvm::opt;
24 using namespace llvm::sys;
26 void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
27 const InputInfo &Output,
28 const InputInfoList &Inputs,
29 const ArgList &Args,
30 const char *LinkingOutput) const {
31 ArgStringList CmdArgs;
33 const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit();
34 const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit();
35 // Only support 32 and 64 bit.
36 if (!IsArch32Bit && !IsArch64Bit)
37 llvm_unreachable("Unsupported bit width value.");
39 // Specify the mode in which the as(1) command operates.
40 if (IsArch32Bit) {
41 CmdArgs.push_back("-a32");
42 } else {
43 // Must be 64-bit, otherwise asserted already.
44 CmdArgs.push_back("-a64");
47 // Accept any mixture of instructions.
48 // On Power for AIX and Linux, this behaviour matches that of GCC for both the
49 // user-provided assembler source case and the compiler-produced assembler
50 // source case. Yet XL with user-provided assembler source would not add this.
51 CmdArgs.push_back("-many");
53 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
55 // Specify assembler output file.
56 assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
57 if (Output.isFilename()) {
58 CmdArgs.push_back("-o");
59 CmdArgs.push_back(Output.getFilename());
62 // Specify assembler input file.
63 // The system assembler on AIX takes exactly one input file. The driver is
64 // expected to invoke as(1) separately for each assembler source input file.
65 if (Inputs.size() != 1)
66 llvm_unreachable("Invalid number of input files.");
67 const InputInfo &II = Inputs[0];
68 assert((II.isFilename() || II.isNothing()) && "Invalid input.");
69 if (II.isFilename())
70 CmdArgs.push_back(II.getFilename());
72 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
73 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
74 Exec, CmdArgs, Inputs, Output));
77 // Determine whether there are any linker options that supply an export list
78 // (or equivalent information about what to export) being sent to the linker.
79 static bool hasExportListLinkerOpts(const ArgStringList &CmdArgs) {
80 for (size_t i = 0, Size = CmdArgs.size(); i < Size; ++i) {
81 llvm::StringRef ArgString(CmdArgs[i]);
83 if (ArgString.startswith("-bE:") || ArgString.startswith("-bexport:") ||
84 ArgString == "-bexpall" || ArgString == "-bexpfull")
85 return true;
87 // If we split -b option, check the next opt.
88 if (ArgString == "-b" && i + 1 < Size) {
89 ++i;
90 llvm::StringRef ArgNextString(CmdArgs[i]);
91 if (ArgNextString.startswith("E:") ||
92 ArgNextString.startswith("export:") || ArgNextString == "expall" ||
93 ArgNextString == "expfull")
94 return true;
97 return false;
100 void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
101 const InputInfo &Output,
102 const InputInfoList &Inputs, const ArgList &Args,
103 const char *LinkingOutput) const {
104 const AIX &ToolChain = static_cast<const AIX &>(getToolChain());
105 const Driver &D = ToolChain.getDriver();
106 ArgStringList CmdArgs;
108 const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit();
109 const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit();
110 // Only support 32 and 64 bit.
111 if (!(IsArch32Bit || IsArch64Bit))
112 llvm_unreachable("Unsupported bit width value.");
114 // Force static linking when "-static" is present.
115 if (Args.hasArg(options::OPT_static))
116 CmdArgs.push_back("-bnso");
118 // Add options for shared libraries.
119 if (Args.hasArg(options::OPT_shared)) {
120 CmdArgs.push_back("-bM:SRE");
121 CmdArgs.push_back("-bnoentry");
124 // PGO instrumentation generates symbols belonging to special sections, and
125 // the linker needs to place all symbols in a particular section together in
126 // memory; the AIX linker does that under an option.
127 if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
128 false) ||
129 Args.hasFlag(options::OPT_fprofile_generate,
130 options::OPT_fno_profile_generate, false) ||
131 Args.hasFlag(options::OPT_fprofile_generate_EQ,
132 options::OPT_fno_profile_generate, false) ||
133 Args.hasFlag(options::OPT_fprofile_instr_generate,
134 options::OPT_fno_profile_instr_generate, false) ||
135 Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
136 options::OPT_fno_profile_instr_generate, false) ||
137 Args.hasFlag(options::OPT_fcs_profile_generate,
138 options::OPT_fno_profile_generate, false) ||
139 Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
140 options::OPT_fno_profile_generate, false) ||
141 Args.hasArg(options::OPT_fcreate_profile) ||
142 Args.hasArg(options::OPT_coverage))
143 CmdArgs.push_back("-bdbg:namedsects:ss");
145 // Specify linker output file.
146 assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
147 if (Output.isFilename()) {
148 CmdArgs.push_back("-o");
149 CmdArgs.push_back(Output.getFilename());
152 // Set linking mode (i.e., 32/64-bit) and the address of
153 // text and data sections based on arch bit width.
154 if (IsArch32Bit) {
155 CmdArgs.push_back("-b32");
156 CmdArgs.push_back("-bpT:0x10000000");
157 CmdArgs.push_back("-bpD:0x20000000");
158 } else {
159 // Must be 64-bit, otherwise asserted already.
160 CmdArgs.push_back("-b64");
161 CmdArgs.push_back("-bpT:0x100000000");
162 CmdArgs.push_back("-bpD:0x110000000");
165 auto getCrt0Basename = [&Args, IsArch32Bit] {
166 // Enable gprofiling when "-pg" is specified.
167 if (Args.hasArg(options::OPT_pg))
168 return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o";
169 // Enable profiling when "-p" is specified.
170 else if (Args.hasArg(options::OPT_p))
171 return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o";
172 else
173 return IsArch32Bit ? "crt0.o" : "crt0_64.o";
176 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
177 options::OPT_shared)) {
178 CmdArgs.push_back(
179 Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename())));
181 CmdArgs.push_back(Args.MakeArgString(
182 ToolChain.GetFilePath(IsArch32Bit ? "crti.o" : "crti_64.o")));
185 // Collect all static constructor and destructor functions in both C and CXX
186 // language link invocations. This has to come before AddLinkerInputs as the
187 // implied option needs to precede any other '-bcdtors' settings or
188 // '-bnocdtors' that '-Wl' might forward.
189 CmdArgs.push_back("-bcdtors:all:0:s");
191 // Specify linker input file(s).
192 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
194 if (Args.hasArg(options::OPT_shared) && !hasExportListLinkerOpts(CmdArgs)) {
196 const char *CreateExportListExec = Args.MakeArgString(
197 path::parent_path(ToolChain.getDriver().ClangExecutable) +
198 "/llvm-nm");
199 ArgStringList CreateExportCmdArgs;
201 std::string CreateExportListPath =
202 C.getDriver().GetTemporaryPath("CreateExportList", "exp");
203 const char *ExportList =
204 C.addTempFile(C.getArgs().MakeArgString(CreateExportListPath));
206 for (const auto &II : Inputs)
207 if (II.isFilename())
208 CreateExportCmdArgs.push_back(II.getFilename());
210 CreateExportCmdArgs.push_back("--export-symbols");
211 CreateExportCmdArgs.push_back("-X");
212 if (IsArch32Bit) {
213 CreateExportCmdArgs.push_back("32");
214 } else {
215 // Must be 64-bit, otherwise asserted already.
216 CreateExportCmdArgs.push_back("64");
219 auto ExpCommand = std::make_unique<Command>(
220 JA, *this, ResponseFileSupport::None(), CreateExportListExec,
221 CreateExportCmdArgs, Inputs, Output);
222 ExpCommand->setRedirectFiles({None, std::string(ExportList), None});
223 C.addCommand(std::move(ExpCommand));
224 CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-bE:") + ExportList));
227 // Add directory to library search path.
228 Args.AddAllArgs(CmdArgs, options::OPT_L);
229 ToolChain.AddFilePathLibArgs(Args, CmdArgs);
230 ToolChain.addProfileRTLibs(Args, CmdArgs);
232 if (getToolChain().ShouldLinkCXXStdlib(Args))
233 getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
235 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
236 AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
238 // Support POSIX threads if "-pthreads" or "-pthread" is present.
239 if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread))
240 CmdArgs.push_back("-lpthreads");
242 if (D.CCCIsCXX())
243 CmdArgs.push_back("-lm");
245 CmdArgs.push_back("-lc");
248 const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
249 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
250 Exec, CmdArgs, Inputs, Output));
253 /// AIX - AIX tool chain which can call as(1) and ld(1) directly.
254 AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
255 : ToolChain(D, Triple, Args) {
256 ParseInlineAsmUsingAsmParser = Args.hasFlag(
257 options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true);
258 getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib");
261 // Returns the effective header sysroot path to use.
262 // This comes from either -isysroot or --sysroot.
263 llvm::StringRef
264 AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const {
265 if (DriverArgs.hasArg(options::OPT_isysroot))
266 return DriverArgs.getLastArgValue(options::OPT_isysroot);
267 if (!getDriver().SysRoot.empty())
268 return getDriver().SysRoot;
269 return "/";
272 void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
273 ArgStringList &CC1Args) const {
274 // Return if -nostdinc is specified as a driver option.
275 if (DriverArgs.hasArg(options::OPT_nostdinc))
276 return;
278 llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
279 const Driver &D = getDriver();
281 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
282 SmallString<128> P(D.ResourceDir);
283 // Add the PowerPC intrinsic headers (<resource>/include/ppc_wrappers)
284 path::append(P, "include", "ppc_wrappers");
285 addSystemInclude(DriverArgs, CC1Args, P);
286 // Add the Clang builtin headers (<resource>/include)
287 addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str()));
290 // Return if -nostdlibinc is specified as a driver option.
291 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
292 return;
294 // Add <sysroot>/usr/include.
295 SmallString<128> UP(Sysroot);
296 path::append(UP, "/usr/include");
297 addSystemInclude(DriverArgs, CC1Args, UP.str());
300 void AIX::AddClangCXXStdlibIncludeArgs(
301 const llvm::opt::ArgList &DriverArgs,
302 llvm::opt::ArgStringList &CC1Args) const {
304 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
305 DriverArgs.hasArg(options::OPT_nostdincxx) ||
306 DriverArgs.hasArg(options::OPT_nostdlibinc))
307 return;
309 switch (GetCXXStdlibType(DriverArgs)) {
310 case ToolChain::CST_Libstdcxx:
311 llvm::report_fatal_error(
312 "picking up libstdc++ headers is unimplemented on AIX");
313 case ToolChain::CST_Libcxx: {
314 llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
315 SmallString<128> PathCPP(Sysroot);
316 llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++",
317 "v1");
318 addSystemInclude(DriverArgs, CC1Args, PathCPP.str());
319 // Required in order to suppress conflicting C++ overloads in the system
320 // libc headers that were used by XL C++.
321 CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__");
322 return;
326 llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
329 void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
330 llvm::opt::ArgStringList &CmdArgs) const {
331 switch (GetCXXStdlibType(Args)) {
332 case ToolChain::CST_Libstdcxx:
333 llvm::report_fatal_error("linking libstdc++ unimplemented on AIX");
334 case ToolChain::CST_Libcxx:
335 CmdArgs.push_back("-lc++");
336 if (Args.hasArg(options::OPT_fexperimental_library))
337 CmdArgs.push_back("-lc++experimental");
338 CmdArgs.push_back("-lc++abi");
339 return;
342 llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
345 ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const {
346 return ToolChain::CST_Libcxx;
349 ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const {
350 return ToolChain::RLT_CompilerRT;
353 auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); }
355 auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); }