xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- Mips.cpp - Tools Implementations -----------------------*- 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 "Mips.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"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric using namespace clang::driver;
180b57cec5SDimitry Andric using namespace clang::driver::tools;
190b57cec5SDimitry Andric using namespace clang;
200b57cec5SDimitry Andric using namespace llvm::opt;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric // Get CPU and ABI names. They are not independent
230b57cec5SDimitry Andric // so we have to calculate them together.
getMipsCPUAndABI(const ArgList & Args,const llvm::Triple & Triple,StringRef & CPUName,StringRef & ABIName)240b57cec5SDimitry Andric void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
250b57cec5SDimitry Andric                             StringRef &CPUName, StringRef &ABIName) {
260b57cec5SDimitry Andric   const char *DefMips32CPU = "mips32r2";
270b57cec5SDimitry Andric   const char *DefMips64CPU = "mips64r2";
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric   // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
300b57cec5SDimitry Andric   // default for mips64(el)?-img-linux-gnu.
310b57cec5SDimitry Andric   if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
320b57cec5SDimitry Andric       Triple.isGNUEnvironment()) {
330b57cec5SDimitry Andric     DefMips32CPU = "mips32r6";
340b57cec5SDimitry Andric     DefMips64CPU = "mips64r6";
350b57cec5SDimitry Andric   }
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric   if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) {
380b57cec5SDimitry Andric     DefMips32CPU = "mips32r6";
390b57cec5SDimitry Andric     DefMips64CPU = "mips64r6";
400b57cec5SDimitry Andric   }
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   // MIPS3 is the default for mips64*-unknown-openbsd.
430b57cec5SDimitry Andric   if (Triple.isOSOpenBSD())
440b57cec5SDimitry Andric     DefMips64CPU = "mips3";
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   // MIPS2 is the default for mips(el)?-unknown-freebsd.
470b57cec5SDimitry Andric   // MIPS3 is the default for mips64(el)?-unknown-freebsd.
480b57cec5SDimitry Andric   if (Triple.isOSFreeBSD()) {
490b57cec5SDimitry Andric     DefMips32CPU = "mips2";
500b57cec5SDimitry Andric     DefMips64CPU = "mips3";
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ,
540b57cec5SDimitry Andric                                options::OPT_mcpu_EQ))
550b57cec5SDimitry Andric     CPUName = A->getValue();
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
580b57cec5SDimitry Andric     ABIName = A->getValue();
590b57cec5SDimitry Andric     // Convert a GNU style Mips ABI name to the name
600b57cec5SDimitry Andric     // accepted by LLVM Mips backend.
610b57cec5SDimitry Andric     ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
620b57cec5SDimitry Andric                   .Case("32", "o32")
630b57cec5SDimitry Andric                   .Case("64", "n64")
640b57cec5SDimitry Andric                   .Default(ABIName);
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   // Setup default CPU and ABI names.
680b57cec5SDimitry Andric   if (CPUName.empty() && ABIName.empty()) {
690b57cec5SDimitry Andric     switch (Triple.getArch()) {
700b57cec5SDimitry Andric     default:
710b57cec5SDimitry Andric       llvm_unreachable("Unexpected triple arch name");
720b57cec5SDimitry Andric     case llvm::Triple::mips:
730b57cec5SDimitry Andric     case llvm::Triple::mipsel:
740b57cec5SDimitry Andric       CPUName = DefMips32CPU;
750b57cec5SDimitry Andric       break;
760b57cec5SDimitry Andric     case llvm::Triple::mips64:
770b57cec5SDimitry Andric     case llvm::Triple::mips64el:
780b57cec5SDimitry Andric       CPUName = DefMips64CPU;
790b57cec5SDimitry Andric       break;
800b57cec5SDimitry Andric     }
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32))
840b57cec5SDimitry Andric     ABIName = "n32";
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   if (ABIName.empty() &&
870b57cec5SDimitry Andric       (Triple.getVendor() == llvm::Triple::MipsTechnologies ||
880b57cec5SDimitry Andric        Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
890b57cec5SDimitry Andric     ABIName = llvm::StringSwitch<const char *>(CPUName)
900b57cec5SDimitry Andric                   .Case("mips1", "o32")
910b57cec5SDimitry Andric                   .Case("mips2", "o32")
920b57cec5SDimitry Andric                   .Case("mips3", "n64")
930b57cec5SDimitry Andric                   .Case("mips4", "n64")
940b57cec5SDimitry Andric                   .Case("mips5", "n64")
950b57cec5SDimitry Andric                   .Case("mips32", "o32")
960b57cec5SDimitry Andric                   .Case("mips32r2", "o32")
970b57cec5SDimitry Andric                   .Case("mips32r3", "o32")
980b57cec5SDimitry Andric                   .Case("mips32r5", "o32")
990b57cec5SDimitry Andric                   .Case("mips32r6", "o32")
1000b57cec5SDimitry Andric                   .Case("mips64", "n64")
1010b57cec5SDimitry Andric                   .Case("mips64r2", "n64")
1020b57cec5SDimitry Andric                   .Case("mips64r3", "n64")
1030b57cec5SDimitry Andric                   .Case("mips64r5", "n64")
1040b57cec5SDimitry Andric                   .Case("mips64r6", "n64")
1050b57cec5SDimitry Andric                   .Case("octeon", "n64")
1060b57cec5SDimitry Andric                   .Case("p5600", "o32")
1070b57cec5SDimitry Andric                   .Default("");
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   if (ABIName.empty()) {
1110b57cec5SDimitry Andric     // Deduce ABI name from the target triple.
1120b57cec5SDimitry Andric     ABIName = Triple.isMIPS32() ? "o32" : "n64";
1130b57cec5SDimitry Andric   }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   if (CPUName.empty()) {
1160b57cec5SDimitry Andric     // Deduce CPU name from ABI name.
1170b57cec5SDimitry Andric     CPUName = llvm::StringSwitch<const char *>(ABIName)
1180b57cec5SDimitry Andric                   .Case("o32", DefMips32CPU)
1190b57cec5SDimitry Andric                   .Cases("n32", "n64", DefMips64CPU)
1200b57cec5SDimitry Andric                   .Default("");
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   // FIXME: Warn on inconsistent use of -march and -mabi.
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
getMipsABILibSuffix(const ArgList & Args,const llvm::Triple & Triple)1260b57cec5SDimitry Andric std::string mips::getMipsABILibSuffix(const ArgList &Args,
1270b57cec5SDimitry Andric                                       const llvm::Triple &Triple) {
1280b57cec5SDimitry Andric   StringRef CPUName, ABIName;
1290b57cec5SDimitry Andric   tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
1300b57cec5SDimitry Andric   return llvm::StringSwitch<std::string>(ABIName)
1310b57cec5SDimitry Andric       .Case("o32", "")
1320b57cec5SDimitry Andric       .Case("n32", "32")
1330b57cec5SDimitry Andric       .Case("n64", "64");
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric // Convert ABI name to the GNU tools acceptable variant.
getGnuCompatibleMipsABIName(StringRef ABI)1370b57cec5SDimitry Andric StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) {
1380b57cec5SDimitry Andric   return llvm::StringSwitch<llvm::StringRef>(ABI)
1390b57cec5SDimitry Andric       .Case("o32", "32")
1400b57cec5SDimitry Andric       .Case("n64", "64")
1410b57cec5SDimitry Andric       .Default(ABI);
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric // Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
1450b57cec5SDimitry Andric // and -mfloat-abi=.
getMipsFloatABI(const Driver & D,const ArgList & Args,const llvm::Triple & Triple)1460b57cec5SDimitry Andric mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args,
1470b57cec5SDimitry Andric                                      const llvm::Triple &Triple) {
1480b57cec5SDimitry Andric   mips::FloatABI ABI = mips::FloatABI::Invalid;
1490b57cec5SDimitry Andric   if (Arg *A =
1500b57cec5SDimitry Andric           Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
1510b57cec5SDimitry Andric                           options::OPT_mfloat_abi_EQ)) {
1520b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_msoft_float))
1530b57cec5SDimitry Andric       ABI = mips::FloatABI::Soft;
1540b57cec5SDimitry Andric     else if (A->getOption().matches(options::OPT_mhard_float))
1550b57cec5SDimitry Andric       ABI = mips::FloatABI::Hard;
1560b57cec5SDimitry Andric     else {
1570b57cec5SDimitry Andric       ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())
1580b57cec5SDimitry Andric                 .Case("soft", mips::FloatABI::Soft)
1590b57cec5SDimitry Andric                 .Case("hard", mips::FloatABI::Hard)
1600b57cec5SDimitry Andric                 .Default(mips::FloatABI::Invalid);
1610b57cec5SDimitry Andric       if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
1620b57cec5SDimitry Andric         D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
1630b57cec5SDimitry Andric         ABI = mips::FloatABI::Hard;
1640b57cec5SDimitry Andric       }
1650b57cec5SDimitry Andric     }
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   // If unspecified, choose the default based on the platform.
1690b57cec5SDimitry Andric   if (ABI == mips::FloatABI::Invalid) {
1700b57cec5SDimitry Andric     if (Triple.isOSFreeBSD()) {
1710b57cec5SDimitry Andric       // For FreeBSD, assume "soft" on all flavors of MIPS.
1720b57cec5SDimitry Andric       ABI = mips::FloatABI::Soft;
1730b57cec5SDimitry Andric     } else {
1740b57cec5SDimitry Andric       // Assume "hard", because it's a default value used by gcc.
1750b57cec5SDimitry Andric       // When we start to recognize specific target MIPS processors,
1760b57cec5SDimitry Andric       // we will be able to select the default more correctly.
1770b57cec5SDimitry Andric       ABI = mips::FloatABI::Hard;
1780b57cec5SDimitry Andric     }
1790b57cec5SDimitry Andric   }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   assert(ABI != mips::FloatABI::Invalid && "must select an ABI");
1820b57cec5SDimitry Andric   return ABI;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
getMIPSTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features)1850b57cec5SDimitry Andric void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
1860b57cec5SDimitry Andric                                  const ArgList &Args,
1870b57cec5SDimitry Andric                                  std::vector<StringRef> &Features) {
1880b57cec5SDimitry Andric   StringRef CPUName;
1890b57cec5SDimitry Andric   StringRef ABIName;
1900b57cec5SDimitry Andric   getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
1910b57cec5SDimitry Andric   ABIName = getGnuCompatibleMipsABIName(ABIName);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a
1940b57cec5SDimitry Andric   // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI
1950b57cec5SDimitry Andric   // extension was developed by Richard Sandiford & Code Sourcery to support
1960b57cec5SDimitry Andric   // static code calling PIC code (CPIC). For O32 and N32 this means we have
1970b57cec5SDimitry Andric   // several combinations of PIC/static and abicalls. Pure static, static
1980b57cec5SDimitry Andric   // with the CPIC extension, and pure PIC code.
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   // At final link time, O32 and N32 with CPIC will have another section
2010b57cec5SDimitry Andric   // added to the binary which contains the stub functions to perform
2020b57cec5SDimitry Andric   // any fixups required for PIC code.
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   // For N64, the situation is more regular: code can either be static
2050b57cec5SDimitry Andric   // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code
2060b57cec5SDimitry Andric   // code for N64. Since Clang has already built the relocation model portion
2070b57cec5SDimitry Andric   // of the commandline, we pick add +noabicalls feature in the N64 static
2080b57cec5SDimitry Andric   // case.
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   // The is another case to be accounted for: -msym32, which enforces that all
2110b57cec5SDimitry Andric   // symbols have 32 bits in size. In this case, N64 can in theory use CPIC
2120b57cec5SDimitry Andric   // but it is unsupported.
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   // The combinations for N64 are:
2150b57cec5SDimitry Andric   // a) Static without abicalls and 64bit symbols.
2160b57cec5SDimitry Andric   // b) Static with abicalls and 32bit symbols.
2170b57cec5SDimitry Andric   // c) PIC with abicalls and 64bit symbols.
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   // For case (a) we need to add +noabicalls for N64.
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   bool IsN64 = ABIName == "64";
2220b57cec5SDimitry Andric   bool IsPIC = false;
2230b57cec5SDimitry Andric   bool NonPIC = false;
2241db9f3b2SDimitry Andric   bool HasNaN2008Opt = false;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
2270b57cec5SDimitry Andric                                     options::OPT_fpic, options::OPT_fno_pic,
2280b57cec5SDimitry Andric                                     options::OPT_fPIE, options::OPT_fno_PIE,
2290b57cec5SDimitry Andric                                     options::OPT_fpie, options::OPT_fno_pie);
2300b57cec5SDimitry Andric   if (LastPICArg) {
2310b57cec5SDimitry Andric     Option O = LastPICArg->getOption();
2320b57cec5SDimitry Andric     NonPIC =
2330b57cec5SDimitry Andric         (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||
2340b57cec5SDimitry Andric          O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
2350b57cec5SDimitry Andric     IsPIC =
2360b57cec5SDimitry Andric         (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
2370b57cec5SDimitry Andric          O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie));
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   bool UseAbiCalls = false;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   Arg *ABICallsArg =
2430b57cec5SDimitry Andric       Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls);
2440b57cec5SDimitry Andric   UseAbiCalls =
2450b57cec5SDimitry Andric       !ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls);
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {
2480b57cec5SDimitry Andric     D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls)
2490b57cec5SDimitry Andric         << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   if (ABICallsArg && !UseAbiCalls && IsPIC) {
2530b57cec5SDimitry Andric     D.Diag(diag::err_drv_unsupported_noabicalls_pic);
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   if (!UseAbiCalls)
2570b57cec5SDimitry Andric     Features.push_back("+noabicalls");
2580b57cec5SDimitry Andric   else
2590b57cec5SDimitry Andric     Features.push_back("-noabicalls");
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
2620b57cec5SDimitry Andric                                options::OPT_mno_long_calls)) {
2630b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_mno_long_calls))
2640b57cec5SDimitry Andric       Features.push_back("-long-calls");
2650b57cec5SDimitry Andric     else if (!UseAbiCalls)
2660b57cec5SDimitry Andric       Features.push_back("+long-calls");
2670b57cec5SDimitry Andric     else
2680b57cec5SDimitry Andric       D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1);
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric 
271a7dea167SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
272a7dea167SDimitry Andric     if (A->getOption().matches(options::OPT_mxgot))
273a7dea167SDimitry Andric       Features.push_back("+xgot");
274a7dea167SDimitry Andric     else
275a7dea167SDimitry Andric       Features.push_back("-xgot");
276a7dea167SDimitry Andric   }
277a7dea167SDimitry Andric 
2780b57cec5SDimitry Andric   mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple);
2790b57cec5SDimitry Andric   if (FloatABI == mips::FloatABI::Soft) {
2800b57cec5SDimitry Andric     // FIXME: Note, this is a hack. We need to pass the selected float
2810b57cec5SDimitry Andric     // mode to the MipsTargetInfoBase to define appropriate macros there.
2820b57cec5SDimitry Andric     // Now it is the only method.
2830b57cec5SDimitry Andric     Features.push_back("+soft-float");
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
2870b57cec5SDimitry Andric     StringRef Val = StringRef(A->getValue());
2880b57cec5SDimitry Andric     if (Val == "2008") {
2891db9f3b2SDimitry Andric       if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {
2900b57cec5SDimitry Andric         Features.push_back("+nan2008");
2911db9f3b2SDimitry Andric         HasNaN2008Opt = true;
2921db9f3b2SDimitry Andric       } else {
2930b57cec5SDimitry Andric         Features.push_back("-nan2008");
2940b57cec5SDimitry Andric         D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
2950b57cec5SDimitry Andric       }
2960b57cec5SDimitry Andric     } else if (Val == "legacy") {
2970b57cec5SDimitry Andric       if (mips::getIEEE754Standard(CPUName) & mips::Legacy)
2980b57cec5SDimitry Andric         Features.push_back("-nan2008");
2990b57cec5SDimitry Andric       else {
3000b57cec5SDimitry Andric         Features.push_back("+nan2008");
3010b57cec5SDimitry Andric         D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;
3020b57cec5SDimitry Andric       }
3030b57cec5SDimitry Andric     } else
3040b57cec5SDimitry Andric       D.Diag(diag::err_drv_unsupported_option_argument)
305bdd1243dSDimitry Andric           << A->getSpelling() << Val;
3060b57cec5SDimitry Andric   }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) {
3090b57cec5SDimitry Andric     StringRef Val = StringRef(A->getValue());
3100b57cec5SDimitry Andric     if (Val == "2008") {
3110b57cec5SDimitry Andric       if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {
3120b57cec5SDimitry Andric         Features.push_back("+abs2008");
3130b57cec5SDimitry Andric       } else {
3140b57cec5SDimitry Andric         Features.push_back("-abs2008");
3150b57cec5SDimitry Andric         D.Diag(diag::warn_target_unsupported_abs2008) << CPUName;
3160b57cec5SDimitry Andric       }
3170b57cec5SDimitry Andric     } else if (Val == "legacy") {
3180b57cec5SDimitry Andric       if (mips::getIEEE754Standard(CPUName) & mips::Legacy) {
3190b57cec5SDimitry Andric         Features.push_back("-abs2008");
3200b57cec5SDimitry Andric       } else {
3210b57cec5SDimitry Andric         Features.push_back("+abs2008");
3220b57cec5SDimitry Andric         D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName;
3230b57cec5SDimitry Andric       }
3240b57cec5SDimitry Andric     } else {
3250b57cec5SDimitry Andric       D.Diag(diag::err_drv_unsupported_option_argument)
326bdd1243dSDimitry Andric           << A->getSpelling() << Val;
3270b57cec5SDimitry Andric     }
3281db9f3b2SDimitry Andric   } else if (HasNaN2008Opt) {
3291db9f3b2SDimitry Andric     Features.push_back("+abs2008");
3300b57cec5SDimitry Andric   }
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_msingle_float,
3330b57cec5SDimitry Andric                    options::OPT_mdouble_float, "single-float");
3340b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
3350b57cec5SDimitry Andric                    "mips16");
3360b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mmicromips,
3370b57cec5SDimitry Andric                    options::OPT_mno_micromips, "micromips");
3380b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
3390b57cec5SDimitry Andric                    "dsp");
3400b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
3410b57cec5SDimitry Andric                    "dspr2");
3420b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
3430b57cec5SDimitry Andric                    "msa");
344*0fca6ea1SDimitry Andric   if (Arg *A = Args.getLastArg(
345*0fca6ea1SDimitry Andric           options::OPT_mstrict_align, options::OPT_mno_strict_align,
346*0fca6ea1SDimitry Andric           options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
347*0fca6ea1SDimitry Andric     if (A->getOption().matches(options::OPT_mstrict_align) ||
348*0fca6ea1SDimitry Andric         A->getOption().matches(options::OPT_mno_unaligned_access))
349*0fca6ea1SDimitry Andric       Features.push_back(Args.MakeArgString("+strict-align"));
350*0fca6ea1SDimitry Andric     else
351*0fca6ea1SDimitry Andric       Features.push_back(Args.MakeArgString("-strict-align"));
352*0fca6ea1SDimitry Andric   }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
3550b57cec5SDimitry Andric   // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
3560b57cec5SDimitry Andric   // nooddspreg.
3570b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
3580b57cec5SDimitry Andric                                options::OPT_mfp64)) {
3590b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_mfp32))
3600b57cec5SDimitry Andric       Features.push_back("-fp64");
3610b57cec5SDimitry Andric     else if (A->getOption().matches(options::OPT_mfpxx)) {
3620b57cec5SDimitry Andric       Features.push_back("+fpxx");
3630b57cec5SDimitry Andric       Features.push_back("+nooddspreg");
3640b57cec5SDimitry Andric     } else
3650b57cec5SDimitry Andric       Features.push_back("+fp64");
3660b57cec5SDimitry Andric   } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
3670b57cec5SDimitry Andric     Features.push_back("+fpxx");
3680b57cec5SDimitry Andric     Features.push_back("+nooddspreg");
3690b57cec5SDimitry Andric   } else if (mips::isFP64ADefault(Triple, CPUName)) {
3700b57cec5SDimitry Andric     Features.push_back("+fp64");
3710b57cec5SDimitry Andric     Features.push_back("+nooddspreg");
372*0fca6ea1SDimitry Andric   } else if (Arg *A = Args.getLastArg(options::OPT_mmsa)) {
373*0fca6ea1SDimitry Andric     if (A->getOption().matches(options::OPT_mmsa))
374*0fca6ea1SDimitry Andric       Features.push_back("+fp64");
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
3780b57cec5SDimitry Andric                    options::OPT_modd_spreg, "nooddspreg");
3790b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,
3800b57cec5SDimitry Andric                    "nomadd4");
3810b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");
3820b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,
3830b57cec5SDimitry Andric                    "crc");
3840b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,
3850b57cec5SDimitry Andric                    "virt");
3860b57cec5SDimitry Andric   AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,
3870b57cec5SDimitry Andric                    "ginv");
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {
3900b57cec5SDimitry Andric     StringRef Val = StringRef(A->getValue());
3910b57cec5SDimitry Andric     if (Val == "hazard") {
3920b57cec5SDimitry Andric       Arg *B =
3930b57cec5SDimitry Andric           Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
3940b57cec5SDimitry Andric       Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric       if (B && B->getOption().matches(options::OPT_mmicromips))
3970b57cec5SDimitry Andric         D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
3980b57cec5SDimitry Andric             << "hazard" << "micromips";
3990b57cec5SDimitry Andric       else if (C && C->getOption().matches(options::OPT_mips16))
4000b57cec5SDimitry Andric         D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
4010b57cec5SDimitry Andric             << "hazard" << "mips16";
4020b57cec5SDimitry Andric       else if (mips::supportsIndirectJumpHazardBarrier(CPUName))
4030b57cec5SDimitry Andric         Features.push_back("+use-indirect-jump-hazard");
4040b57cec5SDimitry Andric       else
4050b57cec5SDimitry Andric         D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
4060b57cec5SDimitry Andric             << "hazard" << CPUName;
4070b57cec5SDimitry Andric     } else
4080b57cec5SDimitry Andric       D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val;
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric 
getIEEE754Standard(StringRef & CPU)4120b57cec5SDimitry Andric mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {
4130b57cec5SDimitry Andric   // Strictly speaking, mips32r2 and mips64r2 do not conform to the
4140b57cec5SDimitry Andric   // IEEE754-2008 standard. Support for this standard was first introduced
4150b57cec5SDimitry Andric   // in Release 3. However, other compilers have traditionally allowed it
4160b57cec5SDimitry Andric   // for Release 2 so we should do the same.
4170b57cec5SDimitry Andric   return (IEEE754Standard)llvm::StringSwitch<int>(CPU)
4180b57cec5SDimitry Andric       .Case("mips1", Legacy)
4190b57cec5SDimitry Andric       .Case("mips2", Legacy)
4200b57cec5SDimitry Andric       .Case("mips3", Legacy)
4210b57cec5SDimitry Andric       .Case("mips4", Legacy)
4220b57cec5SDimitry Andric       .Case("mips5", Legacy)
4230b57cec5SDimitry Andric       .Case("mips32", Legacy)
4240b57cec5SDimitry Andric       .Case("mips32r2", Legacy | Std2008)
4250b57cec5SDimitry Andric       .Case("mips32r3", Legacy | Std2008)
4260b57cec5SDimitry Andric       .Case("mips32r5", Legacy | Std2008)
4270b57cec5SDimitry Andric       .Case("mips32r6", Std2008)
4280b57cec5SDimitry Andric       .Case("mips64", Legacy)
4290b57cec5SDimitry Andric       .Case("mips64r2", Legacy | Std2008)
4300b57cec5SDimitry Andric       .Case("mips64r3", Legacy | Std2008)
4310b57cec5SDimitry Andric       .Case("mips64r5", Legacy | Std2008)
4320b57cec5SDimitry Andric       .Case("mips64r6", Std2008)
4330b57cec5SDimitry Andric       .Default(Std2008);
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric 
hasCompactBranches(StringRef & CPU)4360b57cec5SDimitry Andric bool mips::hasCompactBranches(StringRef &CPU) {
4370b57cec5SDimitry Andric   // mips32r6 and mips64r6 have compact branches.
4380b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(CPU)
4390b57cec5SDimitry Andric       .Case("mips32r6", true)
4400b57cec5SDimitry Andric       .Case("mips64r6", true)
4410b57cec5SDimitry Andric       .Default(false);
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric 
hasMipsAbiArg(const ArgList & Args,const char * Value)4440b57cec5SDimitry Andric bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
4450b57cec5SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
4460b57cec5SDimitry Andric   return A && (A->getValue() == StringRef(Value));
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
isUCLibc(const ArgList & Args)4490b57cec5SDimitry Andric bool mips::isUCLibc(const ArgList &Args) {
4500b57cec5SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_m_libc_Group);
4510b57cec5SDimitry Andric   return A && A->getOption().matches(options::OPT_muclibc);
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric 
isNaN2008(const Driver & D,const ArgList & Args,const llvm::Triple & Triple)454349cc55cSDimitry Andric bool mips::isNaN2008(const Driver &D, const ArgList &Args,
455349cc55cSDimitry Andric                      const llvm::Triple &Triple) {
4560b57cec5SDimitry Andric   if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
4570b57cec5SDimitry Andric     return llvm::StringSwitch<bool>(NaNArg->getValue())
4580b57cec5SDimitry Andric         .Case("2008", true)
4590b57cec5SDimitry Andric         .Case("legacy", false)
4600b57cec5SDimitry Andric         .Default(false);
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   // NaN2008 is the default for MIPS32r6/MIPS64r6.
463349cc55cSDimitry Andric   return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple))
4640b57cec5SDimitry Andric       .Cases("mips32r6", "mips64r6", true)
4650b57cec5SDimitry Andric       .Default(false);
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric 
isFP64ADefault(const llvm::Triple & Triple,StringRef CPUName)4680b57cec5SDimitry Andric bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
4690b57cec5SDimitry Andric   if (!Triple.isAndroid())
4700b57cec5SDimitry Andric     return false;
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   // Android MIPS32R6 defaults to FP64A.
4730b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(CPUName)
4740b57cec5SDimitry Andric       .Case("mips32r6", true)
4750b57cec5SDimitry Andric       .Default(false);
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
isFPXXDefault(const llvm::Triple & Triple,StringRef CPUName,StringRef ABIName,mips::FloatABI FloatABI)4780b57cec5SDimitry Andric bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
4790b57cec5SDimitry Andric                          StringRef ABIName, mips::FloatABI FloatABI) {
4800b57cec5SDimitry Andric   if (ABIName != "32")
4810b57cec5SDimitry Andric     return false;
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
4840b57cec5SDimitry Andric   // present.
4850b57cec5SDimitry Andric   if (FloatABI == mips::FloatABI::Soft)
4860b57cec5SDimitry Andric     return false;
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(CPUName)
4890b57cec5SDimitry Andric       .Cases("mips2", "mips3", "mips4", "mips5", true)
4900b57cec5SDimitry Andric       .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
4910b57cec5SDimitry Andric       .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
4920b57cec5SDimitry Andric       .Default(false);
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric 
shouldUseFPXX(const ArgList & Args,const llvm::Triple & Triple,StringRef CPUName,StringRef ABIName,mips::FloatABI FloatABI)4950b57cec5SDimitry Andric bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
4960b57cec5SDimitry Andric                          StringRef CPUName, StringRef ABIName,
4970b57cec5SDimitry Andric                          mips::FloatABI FloatABI) {
4980b57cec5SDimitry Andric   bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   // FPXX shouldn't be used if -msingle-float is present.
5010b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
5020b57cec5SDimitry Andric                                options::OPT_mdouble_float))
5030b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_msingle_float))
5040b57cec5SDimitry Andric       UseFPXX = false;
505*0fca6ea1SDimitry Andric   // FP64 should be used for MSA.
506*0fca6ea1SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mmsa))
507*0fca6ea1SDimitry Andric     if (A->getOption().matches(options::OPT_mmsa))
508*0fca6ea1SDimitry Andric       UseFPXX = llvm::StringSwitch<bool>(CPUName)
509*0fca6ea1SDimitry Andric                     .Cases("mips32r2", "mips32r3", "mips32r5", false)
510*0fca6ea1SDimitry Andric                     .Cases("mips64r2", "mips64r3", "mips64r5", false)
511*0fca6ea1SDimitry Andric                     .Default(UseFPXX);
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   return UseFPXX;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric 
supportsIndirectJumpHazardBarrier(StringRef & CPU)5160b57cec5SDimitry Andric bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {
5170b57cec5SDimitry Andric   // Supporting the hazard barrier method of dealing with indirect
5180b57cec5SDimitry Andric   // jumps requires MIPSR2 support.
5190b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(CPU)
5200b57cec5SDimitry Andric       .Case("mips32r2", true)
5210b57cec5SDimitry Andric       .Case("mips32r3", true)
5220b57cec5SDimitry Andric       .Case("mips32r5", true)
5230b57cec5SDimitry Andric       .Case("mips32r6", true)
5240b57cec5SDimitry Andric       .Case("mips64r2", true)
5250b57cec5SDimitry Andric       .Case("mips64r3", true)
5260b57cec5SDimitry Andric       .Case("mips64r5", true)
5270b57cec5SDimitry Andric       .Case("mips64r6", true)
5280b57cec5SDimitry Andric       .Case("octeon", true)
5290b57cec5SDimitry Andric       .Case("p5600", true)
5300b57cec5SDimitry Andric       .Default(false);
5310b57cec5SDimitry Andric }
532