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