Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp
35294 views
//===--- Mips.cpp - Tools Implementations -----------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Mips.h"9#include "ToolChains/CommonArgs.h"10#include "clang/Driver/Driver.h"11#include "clang/Driver/DriverDiagnostic.h"12#include "clang/Driver/Options.h"13#include "llvm/ADT/StringSwitch.h"14#include "llvm/Option/ArgList.h"1516using namespace clang::driver;17using namespace clang::driver::tools;18using namespace clang;19using namespace llvm::opt;2021// Get CPU and ABI names. They are not independent22// so we have to calculate them together.23void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,24StringRef &CPUName, StringRef &ABIName) {25const char *DefMips32CPU = "mips32r2";26const char *DefMips64CPU = "mips64r2";2728// MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the29// default for mips64(el)?-img-linux-gnu.30if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&31Triple.isGNUEnvironment()) {32DefMips32CPU = "mips32r6";33DefMips64CPU = "mips64r6";34}3536if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) {37DefMips32CPU = "mips32r6";38DefMips64CPU = "mips64r6";39}4041// MIPS3 is the default for mips64*-unknown-openbsd.42if (Triple.isOSOpenBSD())43DefMips64CPU = "mips3";4445// MIPS2 is the default for mips(el)?-unknown-freebsd.46// MIPS3 is the default for mips64(el)?-unknown-freebsd.47if (Triple.isOSFreeBSD()) {48DefMips32CPU = "mips2";49DefMips64CPU = "mips3";50}5152if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ,53options::OPT_mcpu_EQ))54CPUName = A->getValue();5556if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {57ABIName = A->getValue();58// Convert a GNU style Mips ABI name to the name59// accepted by LLVM Mips backend.60ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)61.Case("32", "o32")62.Case("64", "n64")63.Default(ABIName);64}6566// Setup default CPU and ABI names.67if (CPUName.empty() && ABIName.empty()) {68switch (Triple.getArch()) {69default:70llvm_unreachable("Unexpected triple arch name");71case llvm::Triple::mips:72case llvm::Triple::mipsel:73CPUName = DefMips32CPU;74break;75case llvm::Triple::mips64:76case llvm::Triple::mips64el:77CPUName = DefMips64CPU;78break;79}80}8182if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32))83ABIName = "n32";8485if (ABIName.empty() &&86(Triple.getVendor() == llvm::Triple::MipsTechnologies ||87Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {88ABIName = llvm::StringSwitch<const char *>(CPUName)89.Case("mips1", "o32")90.Case("mips2", "o32")91.Case("mips3", "n64")92.Case("mips4", "n64")93.Case("mips5", "n64")94.Case("mips32", "o32")95.Case("mips32r2", "o32")96.Case("mips32r3", "o32")97.Case("mips32r5", "o32")98.Case("mips32r6", "o32")99.Case("mips64", "n64")100.Case("mips64r2", "n64")101.Case("mips64r3", "n64")102.Case("mips64r5", "n64")103.Case("mips64r6", "n64")104.Case("octeon", "n64")105.Case("p5600", "o32")106.Default("");107}108109if (ABIName.empty()) {110// Deduce ABI name from the target triple.111ABIName = Triple.isMIPS32() ? "o32" : "n64";112}113114if (CPUName.empty()) {115// Deduce CPU name from ABI name.116CPUName = llvm::StringSwitch<const char *>(ABIName)117.Case("o32", DefMips32CPU)118.Cases("n32", "n64", DefMips64CPU)119.Default("");120}121122// FIXME: Warn on inconsistent use of -march and -mabi.123}124125std::string mips::getMipsABILibSuffix(const ArgList &Args,126const llvm::Triple &Triple) {127StringRef CPUName, ABIName;128tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);129return llvm::StringSwitch<std::string>(ABIName)130.Case("o32", "")131.Case("n32", "32")132.Case("n64", "64");133}134135// Convert ABI name to the GNU tools acceptable variant.136StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) {137return llvm::StringSwitch<llvm::StringRef>(ABI)138.Case("o32", "32")139.Case("n64", "64")140.Default(ABI);141}142143// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,144// and -mfloat-abi=.145mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args,146const llvm::Triple &Triple) {147mips::FloatABI ABI = mips::FloatABI::Invalid;148if (Arg *A =149Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,150options::OPT_mfloat_abi_EQ)) {151if (A->getOption().matches(options::OPT_msoft_float))152ABI = mips::FloatABI::Soft;153else if (A->getOption().matches(options::OPT_mhard_float))154ABI = mips::FloatABI::Hard;155else {156ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())157.Case("soft", mips::FloatABI::Soft)158.Case("hard", mips::FloatABI::Hard)159.Default(mips::FloatABI::Invalid);160if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {161D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);162ABI = mips::FloatABI::Hard;163}164}165}166167// If unspecified, choose the default based on the platform.168if (ABI == mips::FloatABI::Invalid) {169if (Triple.isOSFreeBSD()) {170// For FreeBSD, assume "soft" on all flavors of MIPS.171ABI = mips::FloatABI::Soft;172} else {173// Assume "hard", because it's a default value used by gcc.174// When we start to recognize specific target MIPS processors,175// we will be able to select the default more correctly.176ABI = mips::FloatABI::Hard;177}178}179180assert(ABI != mips::FloatABI::Invalid && "must select an ABI");181return ABI;182}183184void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,185const ArgList &Args,186std::vector<StringRef> &Features) {187StringRef CPUName;188StringRef ABIName;189getMipsCPUAndABI(Args, Triple, CPUName, ABIName);190ABIName = getGnuCompatibleMipsABIName(ABIName);191192// Historically, PIC code for MIPS was associated with -mabicalls, a.k.a193// SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI194// extension was developed by Richard Sandiford & Code Sourcery to support195// static code calling PIC code (CPIC). For O32 and N32 this means we have196// several combinations of PIC/static and abicalls. Pure static, static197// with the CPIC extension, and pure PIC code.198199// At final link time, O32 and N32 with CPIC will have another section200// added to the binary which contains the stub functions to perform201// any fixups required for PIC code.202203// For N64, the situation is more regular: code can either be static204// (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code205// code for N64. Since Clang has already built the relocation model portion206// of the commandline, we pick add +noabicalls feature in the N64 static207// case.208209// The is another case to be accounted for: -msym32, which enforces that all210// symbols have 32 bits in size. In this case, N64 can in theory use CPIC211// but it is unsupported.212213// The combinations for N64 are:214// a) Static without abicalls and 64bit symbols.215// b) Static with abicalls and 32bit symbols.216// c) PIC with abicalls and 64bit symbols.217218// For case (a) we need to add +noabicalls for N64.219220bool IsN64 = ABIName == "64";221bool IsPIC = false;222bool NonPIC = false;223bool HasNaN2008Opt = false;224225Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,226options::OPT_fpic, options::OPT_fno_pic,227options::OPT_fPIE, options::OPT_fno_PIE,228options::OPT_fpie, options::OPT_fno_pie);229if (LastPICArg) {230Option O = LastPICArg->getOption();231NonPIC =232(O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||233O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));234IsPIC =235(O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||236O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie));237}238239bool UseAbiCalls = false;240241Arg *ABICallsArg =242Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls);243UseAbiCalls =244!ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls);245246if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {247D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls)248<< LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);249}250251if (ABICallsArg && !UseAbiCalls && IsPIC) {252D.Diag(diag::err_drv_unsupported_noabicalls_pic);253}254255if (!UseAbiCalls)256Features.push_back("+noabicalls");257else258Features.push_back("-noabicalls");259260if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,261options::OPT_mno_long_calls)) {262if (A->getOption().matches(options::OPT_mno_long_calls))263Features.push_back("-long-calls");264else if (!UseAbiCalls)265Features.push_back("+long-calls");266else267D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1);268}269270if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {271if (A->getOption().matches(options::OPT_mxgot))272Features.push_back("+xgot");273else274Features.push_back("-xgot");275}276277mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple);278if (FloatABI == mips::FloatABI::Soft) {279// FIXME: Note, this is a hack. We need to pass the selected float280// mode to the MipsTargetInfoBase to define appropriate macros there.281// Now it is the only method.282Features.push_back("+soft-float");283}284285if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {286StringRef Val = StringRef(A->getValue());287if (Val == "2008") {288if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {289Features.push_back("+nan2008");290HasNaN2008Opt = true;291} else {292Features.push_back("-nan2008");293D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;294}295} else if (Val == "legacy") {296if (mips::getIEEE754Standard(CPUName) & mips::Legacy)297Features.push_back("-nan2008");298else {299Features.push_back("+nan2008");300D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;301}302} else303D.Diag(diag::err_drv_unsupported_option_argument)304<< A->getSpelling() << Val;305}306307if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) {308StringRef Val = StringRef(A->getValue());309if (Val == "2008") {310if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {311Features.push_back("+abs2008");312} else {313Features.push_back("-abs2008");314D.Diag(diag::warn_target_unsupported_abs2008) << CPUName;315}316} else if (Val == "legacy") {317if (mips::getIEEE754Standard(CPUName) & mips::Legacy) {318Features.push_back("-abs2008");319} else {320Features.push_back("+abs2008");321D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName;322}323} else {324D.Diag(diag::err_drv_unsupported_option_argument)325<< A->getSpelling() << Val;326}327} else if (HasNaN2008Opt) {328Features.push_back("+abs2008");329}330331AddTargetFeature(Args, Features, options::OPT_msingle_float,332options::OPT_mdouble_float, "single-float");333AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,334"mips16");335AddTargetFeature(Args, Features, options::OPT_mmicromips,336options::OPT_mno_micromips, "micromips");337AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,338"dsp");339AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,340"dspr2");341AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,342"msa");343if (Arg *A = Args.getLastArg(344options::OPT_mstrict_align, options::OPT_mno_strict_align,345options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {346if (A->getOption().matches(options::OPT_mstrict_align) ||347A->getOption().matches(options::OPT_mno_unaligned_access))348Features.push_back(Args.MakeArgString("+strict-align"));349else350Features.push_back(Args.MakeArgString("-strict-align"));351}352353// Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32354// pass -mfpxx, or if none are given and fp64a is default, pass fp64 and355// nooddspreg.356if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,357options::OPT_mfp64)) {358if (A->getOption().matches(options::OPT_mfp32))359Features.push_back("-fp64");360else if (A->getOption().matches(options::OPT_mfpxx)) {361Features.push_back("+fpxx");362Features.push_back("+nooddspreg");363} else364Features.push_back("+fp64");365} else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {366Features.push_back("+fpxx");367Features.push_back("+nooddspreg");368} else if (mips::isFP64ADefault(Triple, CPUName)) {369Features.push_back("+fp64");370Features.push_back("+nooddspreg");371} else if (Arg *A = Args.getLastArg(options::OPT_mmsa)) {372if (A->getOption().matches(options::OPT_mmsa))373Features.push_back("+fp64");374}375376AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,377options::OPT_modd_spreg, "nooddspreg");378AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,379"nomadd4");380AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");381AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,382"crc");383AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,384"virt");385AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,386"ginv");387388if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {389StringRef Val = StringRef(A->getValue());390if (Val == "hazard") {391Arg *B =392Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);393Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);394395if (B && B->getOption().matches(options::OPT_mmicromips))396D.Diag(diag::err_drv_unsupported_indirect_jump_opt)397<< "hazard" << "micromips";398else if (C && C->getOption().matches(options::OPT_mips16))399D.Diag(diag::err_drv_unsupported_indirect_jump_opt)400<< "hazard" << "mips16";401else if (mips::supportsIndirectJumpHazardBarrier(CPUName))402Features.push_back("+use-indirect-jump-hazard");403else404D.Diag(diag::err_drv_unsupported_indirect_jump_opt)405<< "hazard" << CPUName;406} else407D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val;408}409}410411mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {412// Strictly speaking, mips32r2 and mips64r2 do not conform to the413// IEEE754-2008 standard. Support for this standard was first introduced414// in Release 3. However, other compilers have traditionally allowed it415// for Release 2 so we should do the same.416return (IEEE754Standard)llvm::StringSwitch<int>(CPU)417.Case("mips1", Legacy)418.Case("mips2", Legacy)419.Case("mips3", Legacy)420.Case("mips4", Legacy)421.Case("mips5", Legacy)422.Case("mips32", Legacy)423.Case("mips32r2", Legacy | Std2008)424.Case("mips32r3", Legacy | Std2008)425.Case("mips32r5", Legacy | Std2008)426.Case("mips32r6", Std2008)427.Case("mips64", Legacy)428.Case("mips64r2", Legacy | Std2008)429.Case("mips64r3", Legacy | Std2008)430.Case("mips64r5", Legacy | Std2008)431.Case("mips64r6", Std2008)432.Default(Std2008);433}434435bool mips::hasCompactBranches(StringRef &CPU) {436// mips32r6 and mips64r6 have compact branches.437return llvm::StringSwitch<bool>(CPU)438.Case("mips32r6", true)439.Case("mips64r6", true)440.Default(false);441}442443bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {444Arg *A = Args.getLastArg(options::OPT_mabi_EQ);445return A && (A->getValue() == StringRef(Value));446}447448bool mips::isUCLibc(const ArgList &Args) {449Arg *A = Args.getLastArg(options::OPT_m_libc_Group);450return A && A->getOption().matches(options::OPT_muclibc);451}452453bool mips::isNaN2008(const Driver &D, const ArgList &Args,454const llvm::Triple &Triple) {455if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))456return llvm::StringSwitch<bool>(NaNArg->getValue())457.Case("2008", true)458.Case("legacy", false)459.Default(false);460461// NaN2008 is the default for MIPS32r6/MIPS64r6.462return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple))463.Cases("mips32r6", "mips64r6", true)464.Default(false);465}466467bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {468if (!Triple.isAndroid())469return false;470471// Android MIPS32R6 defaults to FP64A.472return llvm::StringSwitch<bool>(CPUName)473.Case("mips32r6", true)474.Default(false);475}476477bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,478StringRef ABIName, mips::FloatABI FloatABI) {479if (ABIName != "32")480return false;481482// FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is483// present.484if (FloatABI == mips::FloatABI::Soft)485return false;486487return llvm::StringSwitch<bool>(CPUName)488.Cases("mips2", "mips3", "mips4", "mips5", true)489.Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)490.Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)491.Default(false);492}493494bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,495StringRef CPUName, StringRef ABIName,496mips::FloatABI FloatABI) {497bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);498499// FPXX shouldn't be used if -msingle-float is present.500if (Arg *A = Args.getLastArg(options::OPT_msingle_float,501options::OPT_mdouble_float))502if (A->getOption().matches(options::OPT_msingle_float))503UseFPXX = false;504// FP64 should be used for MSA.505if (Arg *A = Args.getLastArg(options::OPT_mmsa))506if (A->getOption().matches(options::OPT_mmsa))507UseFPXX = llvm::StringSwitch<bool>(CPUName)508.Cases("mips32r2", "mips32r3", "mips32r5", false)509.Cases("mips64r2", "mips64r3", "mips64r5", false)510.Default(UseFPXX);511512return UseFPXX;513}514515bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {516// Supporting the hazard barrier method of dealing with indirect517// jumps requires MIPSR2 support.518return llvm::StringSwitch<bool>(CPU)519.Case("mips32r2", true)520.Case("mips32r3", true)521.Case("mips32r5", true)522.Case("mips32r6", true)523.Case("mips64r2", true)524.Case("mips64r3", true)525.Case("mips64r5", true)526.Case("mips64r6", true)527.Case("octeon", true)528.Case("p5600", true)529.Default(false);530}531532533