diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp | 300 |
1 files changed, 267 insertions, 33 deletions
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp index 3000b8416adf..e6126ff62db3 100644 --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp @@ -12,7 +12,9 @@ #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" using AIX = clang::driver::toolchains::AIX; @@ -28,6 +30,7 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { + const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit(); @@ -36,6 +39,11 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 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"); @@ -74,6 +82,29 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 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, @@ -88,6 +119,11 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, 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"); @@ -98,6 +134,54 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, 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()) { @@ -118,19 +202,19 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-bpD:0x110000000"); } - auto getCrt0Basename = [&Args, IsArch32Bit] { - // Enable gprofiling when "-pg" is specified. - if (Args.hasArg(options::OPT_pg)) - return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o"; - // Enable profiling when "-p" is specified. - else if (Args.hasArg(options::OPT_p)) - return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o"; - else + 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"; - }; + }; - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, - options::OPT_shared)) { CmdArgs.push_back( Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename()))); @@ -147,27 +231,109 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Specify linker input file(s). AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); - // Add directory to library search path. - Args.AddAllArgs(CmdArgs, options::OPT_L); - 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); - - // Support POSIX threads if "-pthreads" or "-pthread" is present. - if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread)) - CmdArgs.push_back("-lpthreads"); + 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 (D.CCCIsCXX()) - CmdArgs.push_back("-lm"); + 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)); + } - CmdArgs.push_back("-lc"); + // 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)); @@ -176,6 +342,10 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, /// 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().getInstalledDir()); + if (getDriver().getInstalledDir() != getDriver().Dir) + 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"); @@ -201,11 +371,13 @@ void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs); const Driver &D = getDriver(); - // Add the Clang builtin headers (<resource>/include). if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { SmallString<128> P(D.ResourceDir); - path::append(P, "/include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); + // 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())); } // Return if -nostdlibinc is specified as a driver option. @@ -218,20 +390,82 @@ void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 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; - case ToolChain::CST_Libstdcxx: - llvm::report_fatal_error("linking libstdc++ unimplemented on AIX"); } llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); } +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); + + 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; } |