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