xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
10b57cec5SDimitry Andric //===--- PPC.cpp - PPC Helpers for Tools ------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "PPC.h"
100b57cec5SDimitry Andric #include "ToolChains/CommonArgs.h"
110b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
120b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
130b57cec5SDimitry Andric #include "clang/Driver/Options.h"
140b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
150b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
1606c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric using namespace clang::driver;
190b57cec5SDimitry Andric using namespace clang::driver::tools;
200b57cec5SDimitry Andric using namespace clang;
210b57cec5SDimitry Andric using namespace llvm::opt;
220b57cec5SDimitry Andric 
23bdd1243dSDimitry Andric static std::string getPPCGenericTargetCPU(const llvm::Triple &T) {
24bdd1243dSDimitry Andric   // LLVM may default to generating code for the native CPU,
25bdd1243dSDimitry Andric   // but, like gcc, we default to a more generic option for
26bdd1243dSDimitry Andric   // each architecture. (except on AIX)
27bdd1243dSDimitry Andric   if (T.isOSAIX())
28bdd1243dSDimitry Andric     return "pwr7";
29bdd1243dSDimitry Andric   else if (T.getArch() == llvm::Triple::ppc64le)
30bdd1243dSDimitry Andric     return "ppc64le";
31bdd1243dSDimitry Andric   else if (T.getArch() == llvm::Triple::ppc64)
32bdd1243dSDimitry Andric     return "ppc64";
33bdd1243dSDimitry Andric   else
34bdd1243dSDimitry Andric     return "ppc";
35bdd1243dSDimitry Andric }
36bdd1243dSDimitry Andric 
371ac55f4cSDimitry Andric static std::string normalizeCPUName(StringRef CPUName, const llvm::Triple &T) {
38bdd1243dSDimitry Andric   // Clang/LLVM does not actually support code generation
39bdd1243dSDimitry Andric   // for the 405 CPU. However, there are uses of this CPU ID
40bdd1243dSDimitry Andric   // in projects that previously used GCC and rely on Clang
41bdd1243dSDimitry Andric   // accepting it. Clang has always ignored it and passed the
42bdd1243dSDimitry Andric   // generic CPU ID to the back end.
43bdd1243dSDimitry Andric   if (CPUName == "generic" || CPUName == "405")
44bdd1243dSDimitry Andric     return getPPCGenericTargetCPU(T);
45bdd1243dSDimitry Andric 
460b57cec5SDimitry Andric   if (CPUName == "native") {
475ffd83dbSDimitry Andric     std::string CPU = std::string(llvm::sys::getHostCPUName());
480b57cec5SDimitry Andric     if (!CPU.empty() && CPU != "generic")
490b57cec5SDimitry Andric       return CPU;
500b57cec5SDimitry Andric     else
51bdd1243dSDimitry Andric       return getPPCGenericTargetCPU(T);
520b57cec5SDimitry Andric   }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   return llvm::StringSwitch<const char *>(CPUName)
550b57cec5SDimitry Andric       .Case("common", "generic")
560b57cec5SDimitry Andric       .Case("440fp", "440")
570b57cec5SDimitry Andric       .Case("630", "pwr3")
580b57cec5SDimitry Andric       .Case("G3", "g3")
590b57cec5SDimitry Andric       .Case("G4", "g4")
600b57cec5SDimitry Andric       .Case("G4+", "g4+")
61f8e1cfadSDimitry Andric       .Case("8548", "e500")
620b57cec5SDimitry Andric       .Case("G5", "g5")
630b57cec5SDimitry Andric       .Case("power3", "pwr3")
640b57cec5SDimitry Andric       .Case("power4", "pwr4")
650b57cec5SDimitry Andric       .Case("power5", "pwr5")
660b57cec5SDimitry Andric       .Case("power5x", "pwr5x")
670b57cec5SDimitry Andric       .Case("power6", "pwr6")
680b57cec5SDimitry Andric       .Case("power6x", "pwr6x")
690b57cec5SDimitry Andric       .Case("power7", "pwr7")
700b57cec5SDimitry Andric       .Case("power8", "pwr8")
710b57cec5SDimitry Andric       .Case("power9", "pwr9")
725ffd83dbSDimitry Andric       .Case("power10", "pwr10")
73*36b606aeSDimitry Andric       .Case("power11", "pwr11")
74480093f4SDimitry Andric       .Case("future", "future")
750b57cec5SDimitry Andric       .Case("powerpc", "ppc")
760b57cec5SDimitry Andric       .Case("powerpc64", "ppc64")
770b57cec5SDimitry Andric       .Case("powerpc64le", "ppc64le")
78bdd1243dSDimitry Andric       .Default(CPUName.data());
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
811ac55f4cSDimitry Andric /// Get the (LLVM) name of the PowerPC cpu we are tuning for.
821ac55f4cSDimitry Andric std::string ppc::getPPCTuneCPU(const ArgList &Args, const llvm::Triple &T) {
831ac55f4cSDimitry Andric   if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ))
841ac55f4cSDimitry Andric     return normalizeCPUName(A->getValue(), T);
851ac55f4cSDimitry Andric   return getPPCGenericTargetCPU(T);
861ac55f4cSDimitry Andric }
871ac55f4cSDimitry Andric 
881ac55f4cSDimitry Andric /// Get the (LLVM) name of the PowerPC cpu we are targeting.
8906c3fb27SDimitry Andric std::string ppc::getPPCTargetCPU(const Driver &D, const ArgList &Args,
9006c3fb27SDimitry Andric                                  const llvm::Triple &T) {
911ac55f4cSDimitry Andric   if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ))
921ac55f4cSDimitry Andric     return normalizeCPUName(A->getValue(), T);
93bdd1243dSDimitry Andric   return getPPCGenericTargetCPU(T);
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric const char *ppc::getPPCAsmModeForCPU(StringRef Name) {
970b57cec5SDimitry Andric   return llvm::StringSwitch<const char *>(Name)
980b57cec5SDimitry Andric       .Case("pwr7", "-mpower7")
990b57cec5SDimitry Andric       .Case("power7", "-mpower7")
1000b57cec5SDimitry Andric       .Case("pwr8", "-mpower8")
1010b57cec5SDimitry Andric       .Case("power8", "-mpower8")
1020b57cec5SDimitry Andric       .Case("ppc64le", "-mpower8")
1030b57cec5SDimitry Andric       .Case("pwr9", "-mpower9")
1040b57cec5SDimitry Andric       .Case("power9", "-mpower9")
1055ffd83dbSDimitry Andric       .Case("pwr10", "-mpower10")
1065ffd83dbSDimitry Andric       .Case("power10", "-mpower10")
107*36b606aeSDimitry Andric       .Case("pwr11", "-mpower11")
108*36b606aeSDimitry Andric       .Case("power11", "-mpower11")
1090b57cec5SDimitry Andric       .Default("-many");
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
1130b57cec5SDimitry Andric                                const ArgList &Args,
1140b57cec5SDimitry Andric                                std::vector<StringRef> &Features) {
115f8e1cfadSDimitry Andric   if (Triple.getSubArch() == llvm::Triple::PPCSubArch_spe)
116f8e1cfadSDimitry Andric     Features.push_back("+spe");
117f8e1cfadSDimitry Andric 
11806c3fb27SDimitry Andric   handleTargetFeaturesGroup(D, Triple, Args, Features,
11906c3fb27SDimitry Andric                             options::OPT_m_ppc_Features_Group);
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
1220b57cec5SDimitry Andric   if (FloatABI == ppc::FloatABI::Soft)
1230b57cec5SDimitry Andric     Features.push_back("-hard-float");
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Triple, Args);
1260b57cec5SDimitry Andric   if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt)
1270b57cec5SDimitry Andric     Features.push_back("+secure-plt");
1280fca6ea1SDimitry Andric 
1290fca6ea1SDimitry Andric   bool UseSeparateSections = isUseSeparateSections(Triple);
1300fca6ea1SDimitry Andric   bool HasDefaultDataSections = Triple.isOSBinFormatXCOFF();
1310fca6ea1SDimitry Andric   if (Args.hasArg(options::OPT_maix_small_local_exec_tls) ||
1320fca6ea1SDimitry Andric       Args.hasArg(options::OPT_maix_small_local_dynamic_tls)) {
1330fca6ea1SDimitry Andric     if (!Triple.isOSAIX() || !Triple.isArch64Bit())
1340fca6ea1SDimitry Andric       D.Diag(diag::err_opt_not_valid_on_target)
1350fca6ea1SDimitry Andric           << "-maix-small-local-[exec|dynamic]-tls";
1360fca6ea1SDimitry Andric 
1370fca6ea1SDimitry Andric     // The -maix-small-local-[exec|dynamic]-tls option should only be used with
1380fca6ea1SDimitry Andric     // -fdata-sections, as having data sections turned off with this option
1390fca6ea1SDimitry Andric     // is not ideal for performance. Moreover, the
1400fca6ea1SDimitry Andric     // small-local-[exec|dynamic]-tls region is a limited resource, and should
1410fca6ea1SDimitry Andric     // not be used for variables that may be replaced.
1420fca6ea1SDimitry Andric     if (!Args.hasFlag(options::OPT_fdata_sections,
1430fca6ea1SDimitry Andric                       options::OPT_fno_data_sections,
1440fca6ea1SDimitry Andric                       UseSeparateSections || HasDefaultDataSections))
1450fca6ea1SDimitry Andric       D.Diag(diag::err_drv_argument_only_allowed_with)
1460fca6ea1SDimitry Andric           << "-maix-small-local-[exec|dynamic]-tls" << "-fdata-sections";
1470fca6ea1SDimitry Andric   }
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
1510b57cec5SDimitry Andric                                               const ArgList &Args) {
1520b57cec5SDimitry Andric   if (Args.getLastArg(options::OPT_msecure_plt))
1530b57cec5SDimitry Andric     return ppc::ReadGOTPtrMode::SecurePlt;
15406c3fb27SDimitry Andric   if (Triple.isPPC32SecurePlt())
1550b57cec5SDimitry Andric     return ppc::ReadGOTPtrMode::SecurePlt;
1560b57cec5SDimitry Andric   else
1570b57cec5SDimitry Andric     return ppc::ReadGOTPtrMode::Bss;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
1610b57cec5SDimitry Andric   ppc::FloatABI ABI = ppc::FloatABI::Invalid;
1620b57cec5SDimitry Andric   if (Arg *A =
1630b57cec5SDimitry Andric           Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
1640b57cec5SDimitry Andric                           options::OPT_mfloat_abi_EQ)) {
1650b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_msoft_float))
1660b57cec5SDimitry Andric       ABI = ppc::FloatABI::Soft;
1670b57cec5SDimitry Andric     else if (A->getOption().matches(options::OPT_mhard_float))
1680b57cec5SDimitry Andric       ABI = ppc::FloatABI::Hard;
1690b57cec5SDimitry Andric     else {
1700b57cec5SDimitry Andric       ABI = llvm::StringSwitch<ppc::FloatABI>(A->getValue())
1710b57cec5SDimitry Andric                 .Case("soft", ppc::FloatABI::Soft)
1720b57cec5SDimitry Andric                 .Case("hard", ppc::FloatABI::Hard)
1730b57cec5SDimitry Andric                 .Default(ppc::FloatABI::Invalid);
1740b57cec5SDimitry Andric       if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
1750b57cec5SDimitry Andric         D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
1760b57cec5SDimitry Andric         ABI = ppc::FloatABI::Hard;
1770b57cec5SDimitry Andric       }
1780b57cec5SDimitry Andric     }
1790b57cec5SDimitry Andric   }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   // If unspecified, choose the default based on the platform.
1820b57cec5SDimitry Andric   if (ABI == ppc::FloatABI::Invalid) {
1830b57cec5SDimitry Andric     ABI = ppc::FloatABI::Hard;
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   return ABI;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) {
1900b57cec5SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
1910b57cec5SDimitry Andric   return A && (A->getValue() == StringRef(Value));
1920b57cec5SDimitry Andric }
193