| //===--- AIX.cpp - AIX ToolChain Implementations ----------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "AIX.h" |
| #include "Arch/PPC.h" |
| #include "CommonArgs.h" |
| #include "clang/Driver/Compilation.h" |
| #include "clang/Driver/Options.h" |
| #include "clang/Driver/SanitizerArgs.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include "llvm/Option/ArgList.h" |
| #include "llvm/ProfileData/InstrProf.h" |
| #include "llvm/Support/Path.h" |
| |
| #include <set> |
| |
| using AIX = clang::driver::toolchains::AIX; |
| using namespace clang::driver; |
| using namespace clang::driver::tools; |
| using namespace clang::driver::toolchains; |
| |
| using namespace llvm::opt; |
| using namespace llvm::sys; |
| |
| void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, |
| const InputInfo &Output, |
| const InputInfoList &Inputs, |
| const ArgList &Args, |
| const char *LinkingOutput) const { |
| const Driver &D = getToolChain().getDriver(); |
| ArgStringList CmdArgs; |
| |
| const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit(); |
| const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit(); |
| // Only support 32 and 64 bit. |
| if (!IsArch32Bit && !IsArch64Bit) |
| llvm_unreachable("Unsupported bit width value."); |
| |
| if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) { |
| D.Diag(diag::err_drv_unsupported_opt_for_target) |
| << A->getSpelling() << D.getTargetTriple(); |
| } |
| |
| // Specify the mode in which the as(1) command operates. |
| if (IsArch32Bit) { |
| CmdArgs.push_back("-a32"); |
| } else { |
| // Must be 64-bit, otherwise asserted already. |
| CmdArgs.push_back("-a64"); |
| } |
| |
| // Accept any mixture of instructions. |
| // On Power for AIX and Linux, this behaviour matches that of GCC for both the |
| // user-provided assembler source case and the compiler-produced assembler |
| // source case. Yet XL with user-provided assembler source would not add this. |
| CmdArgs.push_back("-many"); |
| |
| Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); |
| |
| // Specify assembler output file. |
| assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); |
| if (Output.isFilename()) { |
| CmdArgs.push_back("-o"); |
| CmdArgs.push_back(Output.getFilename()); |
| } |
| |
| // Specify assembler input file. |
| // The system assembler on AIX takes exactly one input file. The driver is |
| // expected to invoke as(1) separately for each assembler source input file. |
| if (Inputs.size() != 1) |
| llvm_unreachable("Invalid number of input files."); |
| const InputInfo &II = Inputs[0]; |
| assert((II.isFilename() || II.isNothing()) && "Invalid input."); |
| if (II.isFilename()) |
| CmdArgs.push_back(II.getFilename()); |
| |
| const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); |
| C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), |
| Exec, CmdArgs, Inputs, Output)); |
| } |
| |
| // Determine whether there are any linker options that supply an export list |
| // (or equivalent information about what to export) being sent to the linker. |
| static bool hasExportListLinkerOpts(const ArgStringList &CmdArgs) { |
| for (size_t i = 0, Size = CmdArgs.size(); i < Size; ++i) { |
| llvm::StringRef ArgString(CmdArgs[i]); |
| |
| if (ArgString.starts_with("-bE:") || ArgString.starts_with("-bexport:") || |
| ArgString == "-bexpall" || ArgString == "-bexpfull") |
| return true; |
| |
| // If we split -b option, check the next opt. |
| if (ArgString == "-b" && i + 1 < Size) { |
| ++i; |
| llvm::StringRef ArgNextString(CmdArgs[i]); |
| if (ArgNextString.starts_with("E:") || |
| ArgNextString.starts_with("export:") || ArgNextString == "expall" || |
| ArgNextString == "expfull") |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
| const InputInfo &Output, |
| const InputInfoList &Inputs, const ArgList &Args, |
| const char *LinkingOutput) const { |
| const AIX &ToolChain = static_cast<const AIX &>(getToolChain()); |
| const Driver &D = ToolChain.getDriver(); |
| ArgStringList CmdArgs; |
| |
| const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit(); |
| const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit(); |
| // Only support 32 and 64 bit. |
| if (!(IsArch32Bit || IsArch64Bit)) |
| llvm_unreachable("Unsupported bit width value."); |
| |
| if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) { |
| D.Diag(diag::err_drv_unsupported_opt_for_target) |
| << A->getSpelling() << D.getTargetTriple(); |
| } |
| |
| // Force static linking when "-static" is present. |
| if (Args.hasArg(options::OPT_static)) |
| CmdArgs.push_back("-bnso"); |
| |
| // Add options for shared libraries. |
| if (Args.hasArg(options::OPT_shared)) { |
| CmdArgs.push_back("-bM:SRE"); |
| CmdArgs.push_back("-bnoentry"); |
| } |
| |
| if (Args.hasFlag(options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr, |
| false)) { |
| if (Args.hasArg(options::OPT_shared)) |
| D.Diag(diag::err_roptr_cannot_build_shared); |
| |
| // The `-mxcoff-roptr` option places constants in RO sections as much as |
| // possible. Then `-bforceimprw` changes such sections to RW if they contain |
| // imported symbols that need to be resolved. |
| CmdArgs.push_back("-bforceimprw"); |
| } |
| |
| // PGO instrumentation generates symbols belonging to special sections, and |
| // the linker needs to place all symbols in a particular section together in |
| // memory; the AIX linker does that under an option. |
| if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, |
| false) || |
| Args.hasFlag(options::OPT_fprofile_generate, |
| options::OPT_fno_profile_generate, false) || |
| Args.hasFlag(options::OPT_fprofile_generate_EQ, |
| options::OPT_fno_profile_generate, false) || |
| Args.hasFlag(options::OPT_fprofile_instr_generate, |
| options::OPT_fno_profile_instr_generate, false) || |
| Args.hasFlag(options::OPT_fprofile_instr_generate_EQ, |
| options::OPT_fno_profile_instr_generate, false) || |
| Args.hasFlag(options::OPT_fcs_profile_generate, |
| options::OPT_fno_profile_generate, false) || |
| Args.hasFlag(options::OPT_fcs_profile_generate_EQ, |
| options::OPT_fno_profile_generate, false) || |
| Args.hasArg(options::OPT_fcreate_profile) || |
| Args.hasArg(options::OPT_coverage)) |
| CmdArgs.push_back("-bdbg:namedsects:ss"); |
| |
| if (Arg *A = |
| Args.getLastArg(clang::driver::options::OPT_mxcoff_build_id_EQ)) { |
| StringRef BuildId = A->getValue(); |
| if (BuildId[0] != '0' || BuildId[1] != 'x' || |
| BuildId.find_if_not(llvm::isHexDigit, 2) != StringRef::npos) |
| ToolChain.getDriver().Diag(diag::err_drv_unsupported_option_argument) |
| << A->getSpelling() << BuildId; |
| else { |
| std::string LinkerFlag = "-bdbg:ldrinfo:xcoff_binary_id:0x"; |
| if (BuildId.size() % 2) // Prepend a 0 if odd number of digits. |
| LinkerFlag += "0"; |
| LinkerFlag += BuildId.drop_front(2).lower(); |
| CmdArgs.push_back(Args.MakeArgString(LinkerFlag)); |
| } |
| } |
| |
| // Specify linker output file. |
| assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); |
| if (Output.isFilename()) { |
| CmdArgs.push_back("-o"); |
| CmdArgs.push_back(Output.getFilename()); |
| } |
| |
| // Set linking mode (i.e., 32/64-bit) and the address of |
| // text and data sections based on arch bit width. |
| if (IsArch32Bit) { |
| CmdArgs.push_back("-b32"); |
| CmdArgs.push_back("-bpT:0x10000000"); |
| CmdArgs.push_back("-bpD:0x20000000"); |
| } else { |
| // Must be 64-bit, otherwise asserted already. |
| CmdArgs.push_back("-b64"); |
| CmdArgs.push_back("-bpT:0x100000000"); |
| CmdArgs.push_back("-bpD:0x110000000"); |
| } |
| |
| if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, |
| options::OPT_shared, options::OPT_r)) { |
| auto getCrt0Basename = [&Args, IsArch32Bit] { |
| if (Arg *A = Args.getLastArgNoClaim(options::OPT_p, options::OPT_pg)) { |
| // Enable gprofiling when "-pg" is specified. |
| if (A->getOption().matches(options::OPT_pg)) |
| return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o"; |
| // Enable profiling when "-p" is specified. |
| return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o"; |
| } |
| return IsArch32Bit ? "crt0.o" : "crt0_64.o"; |
| }; |
| |
| CmdArgs.push_back( |
| Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); |
| |
| CmdArgs.push_back(Args.MakeArgString( |
| ToolChain.GetFilePath(IsArch32Bit ? "crti.o" : "crti_64.o"))); |
| } |
| |
| // Collect all static constructor and destructor functions in both C and CXX |
| // language link invocations. This has to come before AddLinkerInputs as the |
| // implied option needs to precede any other '-bcdtors' settings or |
| // '-bnocdtors' that '-Wl' might forward. |
| CmdArgs.push_back("-bcdtors:all:0:s"); |
| |
| // Specify linker input file(s). |
| AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); |
| |
| if (D.isUsingLTO()) { |
| assert(!Inputs.empty() && "Must have at least one input."); |
| // Find the first filename InputInfo object. |
| auto Input = llvm::find_if( |
| Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); }); |
| if (Input == Inputs.end()) |
| // For a very rare case, all of the inputs to the linker are |
| // InputArg. If that happens, just use the first InputInfo. |
| Input = Inputs.begin(); |
| |
| addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input, |
| D.getLTOMode() == LTOK_Thin); |
| } |
| |
| if (Args.hasArg(options::OPT_shared) && !hasExportListLinkerOpts(CmdArgs)) { |
| |
| const char *CreateExportListExec = Args.MakeArgString( |
| path::parent_path(ToolChain.getDriver().ClangExecutable) + |
| "/llvm-nm"); |
| ArgStringList CreateExportCmdArgs; |
| |
| std::string CreateExportListPath = |
| C.getDriver().GetTemporaryPath("CreateExportList", "exp"); |
| const char *ExportList = |
| C.addTempFile(C.getArgs().MakeArgString(CreateExportListPath)); |
| |
| for (const auto &II : Inputs) |
| if (II.isFilename()) |
| CreateExportCmdArgs.push_back(II.getFilename()); |
| |
| CreateExportCmdArgs.push_back("--export-symbols"); |
| CreateExportCmdArgs.push_back("-X"); |
| if (IsArch32Bit) { |
| CreateExportCmdArgs.push_back("32"); |
| } else { |
| // Must be 64-bit, otherwise asserted already. |
| CreateExportCmdArgs.push_back("64"); |
| } |
| |
| auto ExpCommand = std::make_unique<Command>( |
| JA, *this, ResponseFileSupport::None(), CreateExportListExec, |
| CreateExportCmdArgs, Inputs, Output); |
| ExpCommand->setRedirectFiles( |
| {std::nullopt, std::string(ExportList), std::nullopt}); |
| C.addCommand(std::move(ExpCommand)); |
| CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-bE:") + ExportList)); |
| } |
| |
| // Add directory to library search path. |
| Args.AddAllArgs(CmdArgs, options::OPT_L); |
| if (!Args.hasArg(options::OPT_r)) { |
| ToolChain.AddFilePathLibArgs(Args, CmdArgs); |
| ToolChain.addProfileRTLibs(Args, CmdArgs); |
| |
| if (getToolChain().ShouldLinkCXXStdlib(Args)) |
| getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); |
| |
| if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { |
| AddRunTimeLibs(ToolChain, D, CmdArgs, Args); |
| |
| // Add OpenMP runtime if -fopenmp is specified. |
| if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, |
| options::OPT_fno_openmp, false)) { |
| switch (ToolChain.getDriver().getOpenMPRuntime(Args)) { |
| case Driver::OMPRT_OMP: |
| CmdArgs.push_back("-lomp"); |
| break; |
| case Driver::OMPRT_IOMP5: |
| CmdArgs.push_back("-liomp5"); |
| break; |
| case Driver::OMPRT_GOMP: |
| CmdArgs.push_back("-lgomp"); |
| break; |
| case Driver::OMPRT_Unknown: |
| // Already diagnosed. |
| break; |
| } |
| } |
| |
| // Support POSIX threads if "-pthreads" or "-pthread" is present. |
| if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread)) |
| CmdArgs.push_back("-lpthreads"); |
| |
| if (D.CCCIsCXX()) |
| CmdArgs.push_back("-lm"); |
| |
| CmdArgs.push_back("-lc"); |
| |
| if (Args.hasArgNoClaim(options::OPT_p, options::OPT_pg)) { |
| CmdArgs.push_back(Args.MakeArgString((llvm::Twine("-L") + D.SysRoot) + |
| "/lib/profiled")); |
| CmdArgs.push_back(Args.MakeArgString((llvm::Twine("-L") + D.SysRoot) + |
| "/usr/lib/profiled")); |
| } |
| } |
| } |
| |
| if (D.IsFlangMode()) { |
| addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs); |
| addFortranRuntimeLibs(ToolChain, Args, CmdArgs); |
| CmdArgs.push_back("-lm"); |
| CmdArgs.push_back("-lpthread"); |
| } |
| const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); |
| C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), |
| Exec, CmdArgs, Inputs, Output)); |
| } |
| |
| /// AIX - AIX tool chain which can call as(1) and ld(1) directly. |
| AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) |
| : ToolChain(D, Triple, Args) { |
| getProgramPaths().push_back(getDriver().Dir); |
| |
| ParseInlineAsmUsingAsmParser = Args.hasFlag( |
| options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true); |
| getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib"); |
| } |
| |
| // Returns the effective header sysroot path to use. |
| // This comes from either -isysroot or --sysroot. |
| llvm::StringRef |
| AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const { |
| if (DriverArgs.hasArg(options::OPT_isysroot)) |
| return DriverArgs.getLastArgValue(options::OPT_isysroot); |
| if (!getDriver().SysRoot.empty()) |
| return getDriver().SysRoot; |
| return "/"; |
| } |
| |
| void AIX::AddOpenMPIncludeArgs(const ArgList &DriverArgs, |
| ArgStringList &CC1Args) const { |
| // Add OpenMP include paths if -fopenmp is specified. |
| if (DriverArgs.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, |
| options::OPT_fno_openmp, false)) { |
| SmallString<128> PathOpenMP; |
| switch (getDriver().getOpenMPRuntime(DriverArgs)) { |
| case Driver::OMPRT_OMP: |
| PathOpenMP = GetHeaderSysroot(DriverArgs); |
| llvm::sys::path::append(PathOpenMP, "opt/IBM/openxlCSDK", "include", |
| "openmp"); |
| addSystemInclude(DriverArgs, CC1Args, PathOpenMP.str()); |
| break; |
| case Driver::OMPRT_IOMP5: |
| case Driver::OMPRT_GOMP: |
| case Driver::OMPRT_Unknown: |
| // Unknown / unsupported include paths. |
| break; |
| } |
| } |
| } |
| |
| void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
| ArgStringList &CC1Args) const { |
| // Return if -nostdinc is specified as a driver option. |
| if (DriverArgs.hasArg(options::OPT_nostdinc)) |
| return; |
| |
| llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); |
| const Driver &D = getDriver(); |
| |
| if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
| SmallString<128> P(D.ResourceDir); |
| // Add the PowerPC intrinsic headers (<resource>/include/ppc_wrappers) |
| path::append(P, "include", "ppc_wrappers"); |
| addSystemInclude(DriverArgs, CC1Args, P); |
| // Add the Clang builtin headers (<resource>/include) |
| addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str())); |
| } |
| |
| // Add the include directory containing omp.h. This needs to be before |
| // adding the system include directory because other compilers put their |
| // omp.h in /usr/include. |
| AddOpenMPIncludeArgs(DriverArgs, CC1Args); |
| |
| // Return if -nostdlibinc is specified as a driver option. |
| if (DriverArgs.hasArg(options::OPT_nostdlibinc)) |
| return; |
| |
| // Add <sysroot>/usr/include. |
| SmallString<128> UP(Sysroot); |
| path::append(UP, "/usr/include"); |
| addSystemInclude(DriverArgs, CC1Args, UP.str()); |
| } |
| |
| void AIX::AddClangCXXStdlibIncludeArgs( |
| const llvm::opt::ArgList &DriverArgs, |
| llvm::opt::ArgStringList &CC1Args) const { |
| |
| if (DriverArgs.hasArg(options::OPT_nostdinc) || |
| DriverArgs.hasArg(options::OPT_nostdincxx) || |
| DriverArgs.hasArg(options::OPT_nostdlibinc)) |
| return; |
| |
| switch (GetCXXStdlibType(DriverArgs)) { |
| case ToolChain::CST_Libstdcxx: |
| llvm::report_fatal_error( |
| "picking up libstdc++ headers is unimplemented on AIX"); |
| case ToolChain::CST_Libcxx: { |
| llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); |
| SmallString<128> PathCPP(Sysroot); |
| llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++", |
| "v1"); |
| addSystemInclude(DriverArgs, CC1Args, PathCPP.str()); |
| // Required in order to suppress conflicting C++ overloads in the system |
| // libc headers that were used by XL C++. |
| CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__"); |
| return; |
| } |
| } |
| |
| llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); |
| } |
| |
| void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, |
| llvm::opt::ArgStringList &CmdArgs) const { |
| switch (GetCXXStdlibType(Args)) { |
| case ToolChain::CST_Libstdcxx: |
| llvm::report_fatal_error("linking libstdc++ unimplemented on AIX"); |
| case ToolChain::CST_Libcxx: |
| CmdArgs.push_back("-lc++"); |
| if (Args.hasArg(options::OPT_fexperimental_library)) |
| CmdArgs.push_back("-lc++experimental"); |
| CmdArgs.push_back("-lc++abi"); |
| return; |
| } |
| |
| llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); |
| } |
| |
| // This function processes all the mtocdata options to build the final |
| // simplified toc data options to pass to CC1. |
| static void addTocDataOptions(const llvm::opt::ArgList &Args, |
| llvm::opt::ArgStringList &CC1Args, |
| const Driver &D) { |
| |
| // Check the global toc-data setting. The default is -mno-tocdata. |
| // To enable toc-data globally, -mtocdata must be specified. |
| // Additionally, it must be last to take effect. |
| const bool TOCDataGloballyinEffect = [&Args]() { |
| if (const Arg *LastArg = |
| Args.getLastArg(options::OPT_mtocdata, options::OPT_mno_tocdata)) |
| return LastArg->getOption().matches(options::OPT_mtocdata); |
| else |
| return false; |
| }(); |
| |
| // Currently only supported for small code model. |
| if (TOCDataGloballyinEffect && |
| (Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("large") || |
| Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("medium"))) { |
| D.Diag(clang::diag::warn_drv_unsupported_tocdata); |
| return; |
| } |
| |
| enum TOCDataSetting { |
| AddressInTOC = 0, // Address of the symbol stored in the TOC. |
| DataInTOC = 1 // Symbol defined in the TOC. |
| }; |
| |
| const TOCDataSetting DefaultTocDataSetting = |
| TOCDataGloballyinEffect ? DataInTOC : AddressInTOC; |
| |
| // Process the list of variables in the explicitly specified options |
| // -mtocdata= and -mno-tocdata= to see which variables are opposite to |
| // the global setting of tocdata in TOCDataGloballyinEffect. |
| // Those that have the opposite setting to TOCDataGloballyinEffect, are added |
| // to ExplicitlySpecifiedGlobals. |
| std::set<llvm::StringRef> ExplicitlySpecifiedGlobals; |
| for (const auto Arg : |
| Args.filtered(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ)) { |
| TOCDataSetting ArgTocDataSetting = |
| Arg->getOption().matches(options::OPT_mtocdata_EQ) ? DataInTOC |
| : AddressInTOC; |
| |
| if (ArgTocDataSetting != DefaultTocDataSetting) |
| for (const char *Val : Arg->getValues()) |
| ExplicitlySpecifiedGlobals.insert(Val); |
| else |
| for (const char *Val : Arg->getValues()) |
| ExplicitlySpecifiedGlobals.erase(Val); |
| } |
| |
| auto buildExceptionList = [](const std::set<llvm::StringRef> &ExplicitValues, |
| const char *OptionSpelling) { |
| std::string Option(OptionSpelling); |
| bool IsFirst = true; |
| for (const auto &E : ExplicitValues) { |
| if (!IsFirst) |
| Option += ","; |
| |
| IsFirst = false; |
| Option += E.str(); |
| } |
| return Option; |
| }; |
| |
| // Pass the final tocdata options to CC1 consisting of the default |
| // tocdata option (-mtocdata/-mno-tocdata) along with the list |
| // option (-mno-tocdata=/-mtocdata=) if there are any explicitly specified |
| // variables which would be exceptions to the default setting. |
| const char *TocDataGlobalOption = |
| TOCDataGloballyinEffect ? "-mtocdata" : "-mno-tocdata"; |
| CC1Args.push_back(TocDataGlobalOption); |
| |
| const char *TocDataListOption = |
| TOCDataGloballyinEffect ? "-mno-tocdata=" : "-mtocdata="; |
| if (!ExplicitlySpecifiedGlobals.empty()) |
| CC1Args.push_back(Args.MakeArgString(llvm::Twine( |
| buildExceptionList(ExplicitlySpecifiedGlobals, TocDataListOption)))); |
| } |
| |
| void AIX::addClangTargetOptions( |
| const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args, |
| Action::OffloadKind DeviceOffloadingKind) const { |
| Args.AddLastArg(CC1Args, options::OPT_mignore_xcoff_visibility); |
| Args.AddLastArg(CC1Args, options::OPT_mdefault_visibility_export_mapping_EQ); |
| Args.addOptInFlag(CC1Args, options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr); |
| |
| // Forward last mtocdata/mno_tocdata options to -cc1. |
| if (Args.hasArg(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ, |
| options::OPT_mtocdata)) |
| addTocDataOptions(Args, CC1Args, getDriver()); |
| |
| if (Args.hasFlag(options::OPT_fxl_pragma_pack, |
| options::OPT_fno_xl_pragma_pack, true)) |
| CC1Args.push_back("-fxl-pragma-pack"); |
| } |
| |
| void AIX::addProfileRTLibs(const llvm::opt::ArgList &Args, |
| llvm::opt::ArgStringList &CmdArgs) const { |
| if (needsProfileRT(Args)) { |
| // Add linker option -u__llvm_profile_runtime to cause runtime |
| // initialization to occur. |
| CmdArgs.push_back(Args.MakeArgString( |
| Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); |
| |
| if (const auto *A = |
| Args.getLastArgNoClaim(options::OPT_fprofile_update_EQ)) { |
| StringRef Val = A->getValue(); |
| if (Val == "atomic" || Val == "prefer-atomic") |
| CmdArgs.push_back("-latomic"); |
| } |
| } |
| |
| ToolChain::addProfileRTLibs(Args, CmdArgs); |
| } |
| |
| ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const { |
| return ToolChain::CST_Libcxx; |
| } |
| |
| ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const { |
| return ToolChain::RLT_CompilerRT; |
| } |
| |
| auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); } |
| |
| auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); } |