/src/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | //===----------------------------------------------------------------------===// |
8 | | |
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/ADT/StringExtras.h" |
16 | | #include "llvm/Option/ArgList.h" |
17 | | #include "llvm/ProfileData/InstrProf.h" |
18 | | #include "llvm/Support/Path.h" |
19 | | |
20 | | using AIX = clang::driver::toolchains::AIX; |
21 | | using namespace clang::driver; |
22 | | using namespace clang::driver::tools; |
23 | | using namespace clang::driver::toolchains; |
24 | | |
25 | | using namespace llvm::opt; |
26 | | using namespace llvm::sys; |
27 | | |
28 | | void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, |
29 | | const InputInfo &Output, |
30 | | const InputInfoList &Inputs, |
31 | | const ArgList &Args, |
32 | 0 | const char *LinkingOutput) const { |
33 | 0 | const Driver &D = getToolChain().getDriver(); |
34 | 0 | ArgStringList CmdArgs; |
35 | |
|
36 | 0 | const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit(); |
37 | 0 | const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit(); |
38 | | // Only support 32 and 64 bit. |
39 | 0 | if (!IsArch32Bit && !IsArch64Bit) |
40 | 0 | llvm_unreachable("Unsupported bit width value."); |
41 | |
|
42 | 0 | if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) { |
43 | 0 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
44 | 0 | << A->getSpelling() << D.getTargetTriple(); |
45 | 0 | } |
46 | | |
47 | | // Specify the mode in which the as(1) command operates. |
48 | 0 | if (IsArch32Bit) { |
49 | 0 | CmdArgs.push_back("-a32"); |
50 | 0 | } else { |
51 | | // Must be 64-bit, otherwise asserted already. |
52 | 0 | CmdArgs.push_back("-a64"); |
53 | 0 | } |
54 | | |
55 | | // Accept any mixture of instructions. |
56 | | // On Power for AIX and Linux, this behaviour matches that of GCC for both the |
57 | | // user-provided assembler source case and the compiler-produced assembler |
58 | | // source case. Yet XL with user-provided assembler source would not add this. |
59 | 0 | CmdArgs.push_back("-many"); |
60 | |
|
61 | 0 | Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); |
62 | | |
63 | | // Specify assembler output file. |
64 | 0 | assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); |
65 | 0 | if (Output.isFilename()) { |
66 | 0 | CmdArgs.push_back("-o"); |
67 | 0 | CmdArgs.push_back(Output.getFilename()); |
68 | 0 | } |
69 | | |
70 | | // Specify assembler input file. |
71 | | // The system assembler on AIX takes exactly one input file. The driver is |
72 | | // expected to invoke as(1) separately for each assembler source input file. |
73 | 0 | if (Inputs.size() != 1) |
74 | 0 | llvm_unreachable("Invalid number of input files."); |
75 | 0 | const InputInfo &II = Inputs[0]; |
76 | 0 | assert((II.isFilename() || II.isNothing()) && "Invalid input."); |
77 | 0 | if (II.isFilename()) |
78 | 0 | CmdArgs.push_back(II.getFilename()); |
79 | |
|
80 | 0 | const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); |
81 | 0 | C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), |
82 | 0 | Exec, CmdArgs, Inputs, Output)); |
83 | 0 | } |
84 | | |
85 | | // Determine whether there are any linker options that supply an export list |
86 | | // (or equivalent information about what to export) being sent to the linker. |
87 | 0 | static bool hasExportListLinkerOpts(const ArgStringList &CmdArgs) { |
88 | 0 | for (size_t i = 0, Size = CmdArgs.size(); i < Size; ++i) { |
89 | 0 | llvm::StringRef ArgString(CmdArgs[i]); |
90 | |
|
91 | 0 | if (ArgString.starts_with("-bE:") || ArgString.starts_with("-bexport:") || |
92 | 0 | ArgString == "-bexpall" || ArgString == "-bexpfull") |
93 | 0 | return true; |
94 | | |
95 | | // If we split -b option, check the next opt. |
96 | 0 | if (ArgString == "-b" && i + 1 < Size) { |
97 | 0 | ++i; |
98 | 0 | llvm::StringRef ArgNextString(CmdArgs[i]); |
99 | 0 | if (ArgNextString.starts_with("E:") || |
100 | 0 | ArgNextString.starts_with("export:") || ArgNextString == "expall" || |
101 | 0 | ArgNextString == "expfull") |
102 | 0 | return true; |
103 | 0 | } |
104 | 0 | } |
105 | 0 | return false; |
106 | 0 | } |
107 | | |
108 | | void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
109 | | const InputInfo &Output, |
110 | | const InputInfoList &Inputs, const ArgList &Args, |
111 | 0 | const char *LinkingOutput) const { |
112 | 0 | const AIX &ToolChain = static_cast<const AIX &>(getToolChain()); |
113 | 0 | const Driver &D = ToolChain.getDriver(); |
114 | 0 | ArgStringList CmdArgs; |
115 | |
|
116 | 0 | const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit(); |
117 | 0 | const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit(); |
118 | | // Only support 32 and 64 bit. |
119 | 0 | if (!(IsArch32Bit || IsArch64Bit)) |
120 | 0 | llvm_unreachable("Unsupported bit width value."); |
121 | |
|
122 | 0 | if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) { |
123 | 0 | D.Diag(diag::err_drv_unsupported_opt_for_target) |
124 | 0 | << A->getSpelling() << D.getTargetTriple(); |
125 | 0 | } |
126 | | |
127 | | // Force static linking when "-static" is present. |
128 | 0 | if (Args.hasArg(options::OPT_static)) |
129 | 0 | CmdArgs.push_back("-bnso"); |
130 | | |
131 | | // Add options for shared libraries. |
132 | 0 | if (Args.hasArg(options::OPT_shared)) { |
133 | 0 | CmdArgs.push_back("-bM:SRE"); |
134 | 0 | CmdArgs.push_back("-bnoentry"); |
135 | 0 | } |
136 | |
|
137 | 0 | if (Args.hasFlag(options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr, |
138 | 0 | false)) { |
139 | 0 | if (Args.hasArg(options::OPT_shared)) |
140 | 0 | D.Diag(diag::err_roptr_cannot_build_shared); |
141 | | |
142 | | // The `-mxcoff-roptr` option places constants in RO sections as much as |
143 | | // possible. Then `-bforceimprw` changes such sections to RW if they contain |
144 | | // imported symbols that need to be resolved. |
145 | 0 | CmdArgs.push_back("-bforceimprw"); |
146 | 0 | } |
147 | | |
148 | | // PGO instrumentation generates symbols belonging to special sections, and |
149 | | // the linker needs to place all symbols in a particular section together in |
150 | | // memory; the AIX linker does that under an option. |
151 | 0 | if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, |
152 | 0 | false) || |
153 | 0 | Args.hasFlag(options::OPT_fprofile_generate, |
154 | 0 | options::OPT_fno_profile_generate, false) || |
155 | 0 | Args.hasFlag(options::OPT_fprofile_generate_EQ, |
156 | 0 | options::OPT_fno_profile_generate, false) || |
157 | 0 | Args.hasFlag(options::OPT_fprofile_instr_generate, |
158 | 0 | options::OPT_fno_profile_instr_generate, false) || |
159 | 0 | Args.hasFlag(options::OPT_fprofile_instr_generate_EQ, |
160 | 0 | options::OPT_fno_profile_instr_generate, false) || |
161 | 0 | Args.hasFlag(options::OPT_fcs_profile_generate, |
162 | 0 | options::OPT_fno_profile_generate, false) || |
163 | 0 | Args.hasFlag(options::OPT_fcs_profile_generate_EQ, |
164 | 0 | options::OPT_fno_profile_generate, false) || |
165 | 0 | Args.hasArg(options::OPT_fcreate_profile) || |
166 | 0 | Args.hasArg(options::OPT_coverage)) |
167 | 0 | CmdArgs.push_back("-bdbg:namedsects:ss"); |
168 | |
|
169 | 0 | if (Arg *A = |
170 | 0 | Args.getLastArg(clang::driver::options::OPT_mxcoff_build_id_EQ)) { |
171 | 0 | StringRef BuildId = A->getValue(); |
172 | 0 | if (BuildId[0] != '0' || BuildId[1] != 'x' || |
173 | 0 | BuildId.find_if_not(llvm::isHexDigit, 2) != StringRef::npos) |
174 | 0 | ToolChain.getDriver().Diag(diag::err_drv_unsupported_option_argument) |
175 | 0 | << A->getSpelling() << BuildId; |
176 | 0 | else { |
177 | 0 | std::string LinkerFlag = "-bdbg:ldrinfo:xcoff_binary_id:0x"; |
178 | 0 | if (BuildId.size() % 2) // Prepend a 0 if odd number of digits. |
179 | 0 | LinkerFlag += "0"; |
180 | 0 | LinkerFlag += BuildId.drop_front(2).lower(); |
181 | 0 | CmdArgs.push_back(Args.MakeArgString(LinkerFlag)); |
182 | 0 | } |
183 | 0 | } |
184 | | |
185 | | // Specify linker output file. |
186 | 0 | assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); |
187 | 0 | if (Output.isFilename()) { |
188 | 0 | CmdArgs.push_back("-o"); |
189 | 0 | CmdArgs.push_back(Output.getFilename()); |
190 | 0 | } |
191 | | |
192 | | // Set linking mode (i.e., 32/64-bit) and the address of |
193 | | // text and data sections based on arch bit width. |
194 | 0 | if (IsArch32Bit) { |
195 | 0 | CmdArgs.push_back("-b32"); |
196 | 0 | CmdArgs.push_back("-bpT:0x10000000"); |
197 | 0 | CmdArgs.push_back("-bpD:0x20000000"); |
198 | 0 | } else { |
199 | | // Must be 64-bit, otherwise asserted already. |
200 | 0 | CmdArgs.push_back("-b64"); |
201 | 0 | CmdArgs.push_back("-bpT:0x100000000"); |
202 | 0 | CmdArgs.push_back("-bpD:0x110000000"); |
203 | 0 | } |
204 | |
|
205 | 0 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, |
206 | 0 | options::OPT_shared, options::OPT_r)) { |
207 | 0 | auto getCrt0Basename = [&Args, IsArch32Bit] { |
208 | 0 | if (Arg *A = Args.getLastArgNoClaim(options::OPT_p, options::OPT_pg)) { |
209 | | // Enable gprofiling when "-pg" is specified. |
210 | 0 | if (A->getOption().matches(options::OPT_pg)) |
211 | 0 | return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o"; |
212 | | // Enable profiling when "-p" is specified. |
213 | 0 | return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o"; |
214 | 0 | } |
215 | 0 | return IsArch32Bit ? "crt0.o" : "crt0_64.o"; |
216 | 0 | }; |
217 | |
|
218 | 0 | CmdArgs.push_back( |
219 | 0 | Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); |
220 | |
|
221 | 0 | CmdArgs.push_back(Args.MakeArgString( |
222 | 0 | ToolChain.GetFilePath(IsArch32Bit ? "crti.o" : "crti_64.o"))); |
223 | 0 | } |
224 | | |
225 | | // Collect all static constructor and destructor functions in both C and CXX |
226 | | // language link invocations. This has to come before AddLinkerInputs as the |
227 | | // implied option needs to precede any other '-bcdtors' settings or |
228 | | // '-bnocdtors' that '-Wl' might forward. |
229 | 0 | CmdArgs.push_back("-bcdtors:all:0:s"); |
230 | | |
231 | | // Specify linker input file(s). |
232 | 0 | AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); |
233 | |
|
234 | 0 | if (D.isUsingLTO()) { |
235 | 0 | assert(!Inputs.empty() && "Must have at least one input."); |
236 | | // Find the first filename InputInfo object. |
237 | 0 | auto Input = llvm::find_if( |
238 | 0 | Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); }); |
239 | 0 | if (Input == Inputs.end()) |
240 | | // For a very rare case, all of the inputs to the linker are |
241 | | // InputArg. If that happens, just use the first InputInfo. |
242 | 0 | Input = Inputs.begin(); |
243 | |
|
244 | 0 | addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input, |
245 | 0 | D.getLTOMode() == LTOK_Thin); |
246 | 0 | } |
247 | | |
248 | 0 | if (Args.hasArg(options::OPT_shared) && !hasExportListLinkerOpts(CmdArgs)) { |
249 | |
|
250 | 0 | const char *CreateExportListExec = Args.MakeArgString( |
251 | 0 | path::parent_path(ToolChain.getDriver().ClangExecutable) + |
252 | 0 | "/llvm-nm"); |
253 | 0 | ArgStringList CreateExportCmdArgs; |
254 | |
|
255 | 0 | std::string CreateExportListPath = |
256 | 0 | C.getDriver().GetTemporaryPath("CreateExportList", "exp"); |
257 | 0 | const char *ExportList = |
258 | 0 | C.addTempFile(C.getArgs().MakeArgString(CreateExportListPath)); |
259 | |
|
260 | 0 | for (const auto &II : Inputs) |
261 | 0 | if (II.isFilename()) |
262 | 0 | CreateExportCmdArgs.push_back(II.getFilename()); |
263 | |
|
264 | 0 | CreateExportCmdArgs.push_back("--export-symbols"); |
265 | 0 | CreateExportCmdArgs.push_back("-X"); |
266 | 0 | if (IsArch32Bit) { |
267 | 0 | CreateExportCmdArgs.push_back("32"); |
268 | 0 | } else { |
269 | | // Must be 64-bit, otherwise asserted already. |
270 | 0 | CreateExportCmdArgs.push_back("64"); |
271 | 0 | } |
272 | |
|
273 | 0 | auto ExpCommand = std::make_unique<Command>( |
274 | 0 | JA, *this, ResponseFileSupport::None(), CreateExportListExec, |
275 | 0 | CreateExportCmdArgs, Inputs, Output); |
276 | 0 | ExpCommand->setRedirectFiles( |
277 | 0 | {std::nullopt, std::string(ExportList), std::nullopt}); |
278 | 0 | C.addCommand(std::move(ExpCommand)); |
279 | 0 | CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-bE:") + ExportList)); |
280 | 0 | } |
281 | | |
282 | | // Add directory to library search path. |
283 | 0 | Args.AddAllArgs(CmdArgs, options::OPT_L); |
284 | 0 | if (!Args.hasArg(options::OPT_r)) { |
285 | 0 | ToolChain.AddFilePathLibArgs(Args, CmdArgs); |
286 | 0 | ToolChain.addProfileRTLibs(Args, CmdArgs); |
287 | |
|
288 | 0 | if (getToolChain().ShouldLinkCXXStdlib(Args)) |
289 | 0 | getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); |
290 | |
|
291 | 0 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { |
292 | 0 | AddRunTimeLibs(ToolChain, D, CmdArgs, Args); |
293 | | |
294 | | // Add OpenMP runtime if -fopenmp is specified. |
295 | 0 | if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, |
296 | 0 | options::OPT_fno_openmp, false)) { |
297 | 0 | switch (ToolChain.getDriver().getOpenMPRuntime(Args)) { |
298 | 0 | case Driver::OMPRT_OMP: |
299 | 0 | CmdArgs.push_back("-lomp"); |
300 | 0 | break; |
301 | 0 | case Driver::OMPRT_IOMP5: |
302 | 0 | CmdArgs.push_back("-liomp5"); |
303 | 0 | break; |
304 | 0 | case Driver::OMPRT_GOMP: |
305 | 0 | CmdArgs.push_back("-lgomp"); |
306 | 0 | break; |
307 | 0 | case Driver::OMPRT_Unknown: |
308 | | // Already diagnosed. |
309 | 0 | break; |
310 | 0 | } |
311 | 0 | } |
312 | | |
313 | | // Support POSIX threads if "-pthreads" or "-pthread" is present. |
314 | 0 | if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread)) |
315 | 0 | CmdArgs.push_back("-lpthreads"); |
316 | |
|
317 | 0 | if (D.CCCIsCXX()) |
318 | 0 | CmdArgs.push_back("-lm"); |
319 | |
|
320 | 0 | CmdArgs.push_back("-lc"); |
321 | |
|
322 | 0 | if (Args.hasArgNoClaim(options::OPT_p, options::OPT_pg)) { |
323 | 0 | CmdArgs.push_back(Args.MakeArgString((llvm::Twine("-L") + D.SysRoot) + |
324 | 0 | "/lib/profiled")); |
325 | 0 | CmdArgs.push_back(Args.MakeArgString((llvm::Twine("-L") + D.SysRoot) + |
326 | 0 | "/usr/lib/profiled")); |
327 | 0 | } |
328 | 0 | } |
329 | 0 | } |
330 | | |
331 | 0 | if (D.IsFlangMode()) { |
332 | 0 | addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs); |
333 | 0 | addFortranRuntimeLibs(ToolChain, Args, CmdArgs); |
334 | 0 | CmdArgs.push_back("-lm"); |
335 | 0 | CmdArgs.push_back("-lpthread"); |
336 | 0 | } |
337 | 0 | const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); |
338 | 0 | C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), |
339 | 0 | Exec, CmdArgs, Inputs, Output)); |
340 | 0 | } |
341 | | |
342 | | /// AIX - AIX tool chain which can call as(1) and ld(1) directly. |
343 | | AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) |
344 | 0 | : ToolChain(D, Triple, Args) { |
345 | 0 | getProgramPaths().push_back(getDriver().getInstalledDir()); |
346 | 0 | if (getDriver().getInstalledDir() != getDriver().Dir) |
347 | 0 | getProgramPaths().push_back(getDriver().Dir); |
348 | |
|
349 | 0 | ParseInlineAsmUsingAsmParser = Args.hasFlag( |
350 | 0 | options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true); |
351 | 0 | getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib"); |
352 | 0 | } |
353 | | |
354 | | // Returns the effective header sysroot path to use. |
355 | | // This comes from either -isysroot or --sysroot. |
356 | | llvm::StringRef |
357 | 0 | AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { |
358 | 0 | if (DriverArgs.hasArg(options::OPT_isysroot)) |
359 | 0 | return DriverArgs.getLastArgValue(options::OPT_isysroot); |
360 | 0 | if (!getDriver().SysRoot.empty()) |
361 | 0 | return getDriver().SysRoot; |
362 | 0 | return "/"; |
363 | 0 | } |
364 | | |
365 | | void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
366 | 0 | ArgStringList &CC1Args) const { |
367 | | // Return if -nostdinc is specified as a driver option. |
368 | 0 | if (DriverArgs.hasArg(options::OPT_nostdinc)) |
369 | 0 | return; |
370 | | |
371 | 0 | llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); |
372 | 0 | const Driver &D = getDriver(); |
373 | |
|
374 | 0 | if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
375 | 0 | SmallString<128> P(D.ResourceDir); |
376 | | // Add the PowerPC intrinsic headers (<resource>/include/ppc_wrappers) |
377 | 0 | path::append(P, "include", "ppc_wrappers"); |
378 | 0 | addSystemInclude(DriverArgs, CC1Args, P); |
379 | | // Add the Clang builtin headers (<resource>/include) |
380 | 0 | addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str())); |
381 | 0 | } |
382 | | |
383 | | // Return if -nostdlibinc is specified as a driver option. |
384 | 0 | if (DriverArgs.hasArg(options::OPT_nostdlibinc)) |
385 | 0 | return; |
386 | | |
387 | | // Add <sysroot>/usr/include. |
388 | 0 | SmallString<128> UP(Sysroot); |
389 | 0 | path::append(UP, "/usr/include"); |
390 | 0 | addSystemInclude(DriverArgs, CC1Args, UP.str()); |
391 | 0 | } |
392 | | |
393 | | void AIX::AddClangCXXStdlibIncludeArgs( |
394 | | const llvm::opt::ArgList &DriverArgs, |
395 | 0 | llvm::opt::ArgStringList &CC1Args) const { |
396 | |
|
397 | 0 | if (DriverArgs.hasArg(options::OPT_nostdinc) || |
398 | 0 | DriverArgs.hasArg(options::OPT_nostdincxx) || |
399 | 0 | DriverArgs.hasArg(options::OPT_nostdlibinc)) |
400 | 0 | return; |
401 | | |
402 | 0 | switch (GetCXXStdlibType(DriverArgs)) { |
403 | 0 | case ToolChain::CST_Libstdcxx: |
404 | 0 | llvm::report_fatal_error( |
405 | 0 | "picking up libstdc++ headers is unimplemented on AIX"); |
406 | 0 | case ToolChain::CST_Libcxx: { |
407 | 0 | llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); |
408 | 0 | SmallString<128> PathCPP(Sysroot); |
409 | 0 | llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++", |
410 | 0 | "v1"); |
411 | 0 | addSystemInclude(DriverArgs, CC1Args, PathCPP.str()); |
412 | | // Required in order to suppress conflicting C++ overloads in the system |
413 | | // libc headers that were used by XL C++. |
414 | 0 | CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__"); |
415 | 0 | return; |
416 | 0 | } |
417 | 0 | } |
418 | | |
419 | 0 | llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); |
420 | 0 | } |
421 | | |
422 | | void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, |
423 | 0 | llvm::opt::ArgStringList &CmdArgs) const { |
424 | 0 | switch (GetCXXStdlibType(Args)) { |
425 | 0 | case ToolChain::CST_Libstdcxx: |
426 | 0 | llvm::report_fatal_error("linking libstdc++ unimplemented on AIX"); |
427 | 0 | case ToolChain::CST_Libcxx: |
428 | 0 | CmdArgs.push_back("-lc++"); |
429 | 0 | if (Args.hasArg(options::OPT_fexperimental_library)) |
430 | 0 | CmdArgs.push_back("-lc++experimental"); |
431 | 0 | CmdArgs.push_back("-lc++abi"); |
432 | 0 | return; |
433 | 0 | } |
434 | | |
435 | 0 | llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); |
436 | 0 | } |
437 | | |
438 | | void AIX::addClangTargetOptions( |
439 | | const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args, |
440 | 0 | Action::OffloadKind DeviceOffloadingKind) const { |
441 | 0 | Args.AddLastArg(CC1Args, options::OPT_mignore_xcoff_visibility); |
442 | 0 | Args.AddLastArg(CC1Args, options::OPT_mdefault_visibility_export_mapping_EQ); |
443 | 0 | Args.addOptInFlag(CC1Args, options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr); |
444 | |
|
445 | 0 | if (Args.hasFlag(options::OPT_fxl_pragma_pack, |
446 | 0 | options::OPT_fno_xl_pragma_pack, true)) |
447 | 0 | CC1Args.push_back("-fxl-pragma-pack"); |
448 | 0 | } |
449 | | |
450 | | void AIX::addProfileRTLibs(const llvm::opt::ArgList &Args, |
451 | 0 | llvm::opt::ArgStringList &CmdArgs) const { |
452 | 0 | if (needsProfileRT(Args)) { |
453 | | // Add linker option -u__llvm_profile_runtime to cause runtime |
454 | | // initialization to occur. |
455 | 0 | CmdArgs.push_back(Args.MakeArgString( |
456 | 0 | Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); |
457 | |
|
458 | 0 | if (const auto *A = |
459 | 0 | Args.getLastArgNoClaim(options::OPT_fprofile_update_EQ)) { |
460 | 0 | StringRef Val = A->getValue(); |
461 | 0 | if (Val == "atomic" || Val == "prefer-atomic") |
462 | 0 | CmdArgs.push_back("-latomic"); |
463 | 0 | } |
464 | 0 | } |
465 | |
|
466 | 0 | ToolChain::addProfileRTLibs(Args, CmdArgs); |
467 | 0 | } |
468 | | |
469 | 0 | ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const { |
470 | 0 | return ToolChain::CST_Libcxx; |
471 | 0 | } |
472 | | |
473 | 0 | ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const { |
474 | 0 | return ToolChain::RLT_CompilerRT; |
475 | 0 | } |
476 | | |
477 | 0 | auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } |
478 | | |
479 | 0 | auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } |