1 //===--- AIX.cpp - AIX ToolChain Implementations ----------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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
,
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.
41 CmdArgs
.push_back("-a32");
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.");
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")
87 // If we split -b option, check the next opt.
88 if (ArgString
== "-b" && i
+ 1 < Size
) {
90 llvm::StringRef
ArgNextString(CmdArgs
[i
]);
91 if (ArgNextString
.startswith("E:") ||
92 ArgNextString
.startswith("export:") || ArgNextString
== "expall" ||
93 ArgNextString
== "expfull")
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
,
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.
155 CmdArgs
.push_back("-b32");
156 CmdArgs
.push_back("-bpT:0x10000000");
157 CmdArgs
.push_back("-bpD:0x20000000");
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";
173 return IsArch32Bit
? "crt0.o" : "crt0_64.o";
176 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
177 options::OPT_shared
)) {
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
) +
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
)
208 CreateExportCmdArgs
.push_back(II
.getFilename());
210 CreateExportCmdArgs
.push_back("--export-symbols");
211 CreateExportCmdArgs
.push_back("-X");
213 CreateExportCmdArgs
.push_back("32");
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");
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.
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
;
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
))
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
))
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
))
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++",
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__");
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");
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); }