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 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 335 addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs); 336 addFortranRuntimeLibs(ToolChain, Args, CmdArgs); 337 CmdArgs.push_back("-lm"); 338 CmdArgs.push_back("-lpthread"); 339 } 340 const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 341 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 342 Exec, CmdArgs, Inputs, Output)); 343 } 344 345 /// AIX - AIX tool chain which can call as(1) and ld(1) directly. 346 AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 347 : ToolChain(D, Triple, Args) { 348 getProgramPaths().push_back(getDriver().Dir); 349 350 ParseInlineAsmUsingAsmParser = Args.hasFlag( 351 options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true); 352 getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib"); 353 } 354 355 // Returns the effective header sysroot path to use. 356 // This comes from either -isysroot or --sysroot. 357 llvm::StringRef 358 AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { 359 if (DriverArgs.hasArg(options::OPT_isysroot)) 360 return DriverArgs.getLastArgValue(options::OPT_isysroot); 361 if (!getDriver().SysRoot.empty()) 362 return getDriver().SysRoot; 363 return "/"; 364 } 365 366 void AIX::AddOpenMPIncludeArgs(const ArgList &DriverArgs, 367 ArgStringList &CC1Args) const { 368 // Add OpenMP include paths if -fopenmp is specified. 369 if (DriverArgs.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 370 options::OPT_fno_openmp, false)) { 371 SmallString<128> PathOpenMP; 372 switch (getDriver().getOpenMPRuntime(DriverArgs)) { 373 case Driver::OMPRT_OMP: 374 PathOpenMP = GetHeaderSysroot(DriverArgs); 375 llvm::sys::path::append(PathOpenMP, "opt/IBM/openxlCSDK", "include", 376 "openmp"); 377 addSystemInclude(DriverArgs, CC1Args, PathOpenMP.str()); 378 break; 379 case Driver::OMPRT_IOMP5: 380 case Driver::OMPRT_GOMP: 381 case Driver::OMPRT_Unknown: 382 // Unknown / unsupported include paths. 383 break; 384 } 385 } 386 } 387 388 void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 389 ArgStringList &CC1Args) const { 390 // Return if -nostdinc is specified as a driver option. 391 if (DriverArgs.hasArg(options::OPT_nostdinc)) 392 return; 393 394 llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); 395 const Driver &D = getDriver(); 396 397 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 398 SmallString<128> P(D.ResourceDir); 399 // Add the PowerPC intrinsic headers (<resource>/include/ppc_wrappers) 400 path::append(P, "include", "ppc_wrappers"); 401 addSystemInclude(DriverArgs, CC1Args, P); 402 // Add the Clang builtin headers (<resource>/include) 403 addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str())); 404 } 405 406 // Add the include directory containing omp.h. This needs to be before 407 // adding the system include directory because other compilers put their 408 // omp.h in /usr/include. 409 AddOpenMPIncludeArgs(DriverArgs, CC1Args); 410 411 // Return if -nostdlibinc is specified as a driver option. 412 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 413 return; 414 415 // Add <sysroot>/usr/include. 416 SmallString<128> UP(Sysroot); 417 path::append(UP, "/usr/include"); 418 addSystemInclude(DriverArgs, CC1Args, UP.str()); 419 } 420 421 void AIX::AddClangCXXStdlibIncludeArgs( 422 const llvm::opt::ArgList &DriverArgs, 423 llvm::opt::ArgStringList &CC1Args) const { 424 425 if (DriverArgs.hasArg(options::OPT_nostdinc) || 426 DriverArgs.hasArg(options::OPT_nostdincxx) || 427 DriverArgs.hasArg(options::OPT_nostdlibinc)) 428 return; 429 430 switch (GetCXXStdlibType(DriverArgs)) { 431 case ToolChain::CST_Libstdcxx: 432 llvm::report_fatal_error( 433 "picking up libstdc++ headers is unimplemented on AIX"); 434 case ToolChain::CST_Libcxx: { 435 llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); 436 SmallString<128> PathCPP(Sysroot); 437 llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++", 438 "v1"); 439 addSystemInclude(DriverArgs, CC1Args, PathCPP.str()); 440 // Required in order to suppress conflicting C++ overloads in the system 441 // libc headers that were used by XL C++. 442 CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__"); 443 return; 444 } 445 } 446 447 llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); 448 } 449 450 void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 451 llvm::opt::ArgStringList &CmdArgs) const { 452 switch (GetCXXStdlibType(Args)) { 453 case ToolChain::CST_Libstdcxx: 454 llvm::report_fatal_error("linking libstdc++ unimplemented on AIX"); 455 case ToolChain::CST_Libcxx: 456 CmdArgs.push_back("-lc++"); 457 if (Args.hasArg(options::OPT_fexperimental_library)) 458 CmdArgs.push_back("-lc++experimental"); 459 CmdArgs.push_back("-lc++abi"); 460 return; 461 } 462 463 llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); 464 } 465 466 // This function processes all the mtocdata options to build the final 467 // simplified toc data options to pass to CC1. 468 static void addTocDataOptions(const llvm::opt::ArgList &Args, 469 llvm::opt::ArgStringList &CC1Args, 470 const Driver &D) { 471 472 // Check the global toc-data setting. The default is -mno-tocdata. 473 // To enable toc-data globally, -mtocdata must be specified. 474 // Additionally, it must be last to take effect. 475 const bool TOCDataGloballyinEffect = [&Args]() { 476 if (const Arg *LastArg = 477 Args.getLastArg(options::OPT_mtocdata, options::OPT_mno_tocdata)) 478 return LastArg->getOption().matches(options::OPT_mtocdata); 479 else 480 return false; 481 }(); 482 483 enum TOCDataSetting { 484 AddressInTOC = 0, // Address of the symbol stored in the TOC. 485 DataInTOC = 1 // Symbol defined in the TOC. 486 }; 487 488 const TOCDataSetting DefaultTocDataSetting = 489 TOCDataGloballyinEffect ? DataInTOC : AddressInTOC; 490 491 // Process the list of variables in the explicitly specified options 492 // -mtocdata= and -mno-tocdata= to see which variables are opposite to 493 // the global setting of tocdata in TOCDataGloballyinEffect. 494 // Those that have the opposite setting to TOCDataGloballyinEffect, are added 495 // to ExplicitlySpecifiedGlobals. 496 std::set<llvm::StringRef> ExplicitlySpecifiedGlobals; 497 for (const auto Arg : 498 Args.filtered(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ)) { 499 TOCDataSetting ArgTocDataSetting = 500 Arg->getOption().matches(options::OPT_mtocdata_EQ) ? DataInTOC 501 : AddressInTOC; 502 503 if (ArgTocDataSetting != DefaultTocDataSetting) 504 for (const char *Val : Arg->getValues()) 505 ExplicitlySpecifiedGlobals.insert(Val); 506 else 507 for (const char *Val : Arg->getValues()) 508 ExplicitlySpecifiedGlobals.erase(Val); 509 } 510 511 auto buildExceptionList = [](const std::set<llvm::StringRef> &ExplicitValues, 512 const char *OptionSpelling) { 513 std::string Option(OptionSpelling); 514 bool IsFirst = true; 515 for (const auto &E : ExplicitValues) { 516 if (!IsFirst) 517 Option += ","; 518 519 IsFirst = false; 520 Option += E.str(); 521 } 522 return Option; 523 }; 524 525 // Pass the final tocdata options to CC1 consisting of the default 526 // tocdata option (-mtocdata/-mno-tocdata) along with the list 527 // option (-mno-tocdata=/-mtocdata=) if there are any explicitly specified 528 // variables which would be exceptions to the default setting. 529 const char *TocDataGlobalOption = 530 TOCDataGloballyinEffect ? "-mtocdata" : "-mno-tocdata"; 531 CC1Args.push_back(TocDataGlobalOption); 532 533 const char *TocDataListOption = 534 TOCDataGloballyinEffect ? "-mno-tocdata=" : "-mtocdata="; 535 if (!ExplicitlySpecifiedGlobals.empty()) 536 CC1Args.push_back(Args.MakeArgString(llvm::Twine( 537 buildExceptionList(ExplicitlySpecifiedGlobals, TocDataListOption)))); 538 } 539 540 void AIX::addClangTargetOptions( 541 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args, 542 Action::OffloadKind DeviceOffloadingKind) const { 543 Args.AddLastArg(CC1Args, options::OPT_mignore_xcoff_visibility); 544 Args.AddLastArg(CC1Args, options::OPT_mdefault_visibility_export_mapping_EQ); 545 Args.addOptInFlag(CC1Args, options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr); 546 547 // Forward last mtocdata/mno_tocdata options to -cc1. 548 if (Args.hasArg(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ, 549 options::OPT_mtocdata)) 550 addTocDataOptions(Args, CC1Args, getDriver()); 551 552 if (Args.hasArg(options::OPT_msave_reg_params)) 553 CC1Args.push_back("-msave-reg-params"); 554 555 if (Args.hasFlag(options::OPT_fxl_pragma_pack, 556 options::OPT_fno_xl_pragma_pack, true)) 557 CC1Args.push_back("-fxl-pragma-pack"); 558 559 // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled 560 // or disabled sized deallocations. 561 if (!Args.getLastArgNoClaim(options::OPT_fsized_deallocation, 562 options::OPT_fno_sized_deallocation)) 563 CC1Args.push_back("-fno-sized-deallocation"); 564 } 565 566 void AIX::addProfileRTLibs(const llvm::opt::ArgList &Args, 567 llvm::opt::ArgStringList &CmdArgs) const { 568 if (needsProfileRT(Args)) { 569 // Add linker option -u__llvm_profile_runtime to cause runtime 570 // initialization to occur. 571 CmdArgs.push_back(Args.MakeArgString( 572 Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); 573 574 if (const auto *A = 575 Args.getLastArgNoClaim(options::OPT_fprofile_update_EQ)) { 576 StringRef Val = A->getValue(); 577 if (Val == "atomic" || Val == "prefer-atomic") 578 CmdArgs.push_back("-latomic"); 579 } 580 } 581 582 ToolChain::addProfileRTLibs(Args, CmdArgs); 583 } 584 585 ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const { 586 return ToolChain::CST_Libcxx; 587 } 588 589 ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const { 590 return ToolChain::RLT_CompilerRT; 591 } 592 593 auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } 594 595 auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } 596