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