brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.4 KiB · 103aae7 Raw
529 lines · cpp
1//===--- Mips.cpp - Tools Implementations -----------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Mips.h"10#include "clang/Driver/CommonArgs.h"11#include "clang/Driver/Driver.h"12#include "clang/Options/Options.h"13#include "llvm/ADT/StringSwitch.h"14#include "llvm/Option/ArgList.h"15 16using namespace clang::driver;17using namespace clang::driver::tools;18using namespace clang;19using namespace llvm::opt;20 21// 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,24                            StringRef &CPUName, StringRef &ABIName) {25  const char *DefMips32CPU = "mips32r2";26  const char *DefMips64CPU = "mips64r2";27 28  // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the29  // default for mips64(el)?-img-linux-gnu.30  if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&31      Triple.isGNUEnvironment()) {32    DefMips32CPU = "mips32r6";33    DefMips64CPU = "mips64r6";34  }35 36  if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) {37    DefMips32CPU = "mips32r6";38    DefMips64CPU = "mips64r6";39  }40 41  // MIPS3 is the default for mips64*-unknown-openbsd.42  if (Triple.isOSOpenBSD())43    DefMips64CPU = "mips3";44 45  // MIPS2 is the default for mips(el)?-unknown-freebsd.46  // MIPS3 is the default for mips64(el)?-unknown-freebsd.47  if (Triple.isOSFreeBSD()) {48    DefMips32CPU = "mips2";49    DefMips64CPU = "mips3";50  }51 52  if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ))53    CPUName = A->getValue();54 55  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {56    ABIName = A->getValue();57    // Convert a GNU style Mips ABI name to the name58    // accepted by LLVM Mips backend.59    ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)60                  .Case("32", "o32")61                  .Case("64", "n64")62                  .Default(ABIName);63  }64 65  // Setup default CPU and ABI names.66  if (CPUName.empty() && ABIName.empty()) {67    switch (Triple.getArch()) {68    default:69      llvm_unreachable("Unexpected triple arch name");70    case llvm::Triple::mips:71    case llvm::Triple::mipsel:72      CPUName = DefMips32CPU;73      break;74    case llvm::Triple::mips64:75    case llvm::Triple::mips64el:76      CPUName = DefMips64CPU;77      break;78    }79  }80 81  if (ABIName.empty() && Triple.isABIN32())82    ABIName = "n32";83 84  if (ABIName.empty() &&85      (Triple.getVendor() == llvm::Triple::MipsTechnologies ||86       Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {87    ABIName = llvm::StringSwitch<const char *>(CPUName)88                  .Case("mips1", "o32")89                  .Case("mips2", "o32")90                  .Case("mips3", "n64")91                  .Case("mips4", "n64")92                  .Case("mips5", "n64")93                  .Case("mips32", "o32")94                  .Case("mips32r2", "o32")95                  .Case("mips32r3", "o32")96                  .Case("mips32r5", "o32")97                  .Case("mips32r6", "o32")98                  .Case("mips64", "n64")99                  .Case("mips64r2", "n64")100                  .Case("mips64r3", "n64")101                  .Case("mips64r5", "n64")102                  .Case("mips64r6", "n64")103                  .Case("octeon", "n64")104                  .Case("p5600", "o32")105                  .Case("i6400", "n64")106                  .Case("i6500", "n64")107                  .Default("");108  }109 110  if (ABIName.empty()) {111    // Deduce ABI name from the target triple.112    ABIName = Triple.isMIPS32() ? "o32" : "n64";113  }114 115  if (CPUName.empty()) {116    // Deduce CPU name from ABI name.117    CPUName = llvm::StringSwitch<const char *>(ABIName)118                  .Case("o32", DefMips32CPU)119                  .Cases({"n32", "n64"}, DefMips64CPU)120                  .Default("");121  }122 123  // FIXME: Warn on inconsistent use of -march and -mabi.124}125 126std::string mips::getMipsABILibSuffix(const ArgList &Args,127                                      const llvm::Triple &Triple) {128  StringRef CPUName, ABIName;129  tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);130  return llvm::StringSwitch<std::string>(ABIName)131      .Case("o32", "")132      .Case("n32", "32")133      .Case("n64", "64");134}135 136// Convert ABI name to the GNU tools acceptable variant.137StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) {138  return llvm::StringSwitch<llvm::StringRef>(ABI)139      .Case("o32", "32")140      .Case("n64", "64")141      .Default(ABI);142}143 144// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,145// and -mfloat-abi=.146mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args,147                                     const llvm::Triple &Triple) {148  mips::FloatABI ABI = mips::FloatABI::Invalid;149  if (Arg *A =150          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,151                          options::OPT_mfloat_abi_EQ)) {152    if (A->getOption().matches(options::OPT_msoft_float))153      ABI = mips::FloatABI::Soft;154    else if (A->getOption().matches(options::OPT_mhard_float))155      ABI = mips::FloatABI::Hard;156    else {157      ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())158                .Case("soft", mips::FloatABI::Soft)159                .Case("hard", mips::FloatABI::Hard)160                .Default(mips::FloatABI::Invalid);161      if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {162        D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);163        ABI = mips::FloatABI::Hard;164      }165    }166  }167 168  // If unspecified, choose the default based on the platform.169  if (ABI == mips::FloatABI::Invalid) {170    if (Triple.isOSFreeBSD()) {171      // For FreeBSD, assume "soft" on all flavors of MIPS.172      ABI = mips::FloatABI::Soft;173    } else {174      // Assume "hard", because it's a default value used by gcc.175      // When we start to recognize specific target MIPS processors,176      // we will be able to select the default more correctly.177      ABI = mips::FloatABI::Hard;178    }179  }180 181  assert(ABI != mips::FloatABI::Invalid && "must select an ABI");182  return ABI;183}184 185void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,186                                 const ArgList &Args,187                                 std::vector<StringRef> &Features) {188  StringRef CPUName;189  StringRef ABIName;190  getMipsCPUAndABI(Args, Triple, CPUName, ABIName);191  ABIName = getGnuCompatibleMipsABIName(ABIName);192 193  // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a194  // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI195  // extension was developed by Richard Sandiford & Code Sourcery to support196  // static code calling PIC code (CPIC). For O32 and N32 this means we have197  // several combinations of PIC/static and abicalls. Pure static, static198  // with the CPIC extension, and pure PIC code.199 200  // At final link time, O32 and N32 with CPIC will have another section201  // added to the binary which contains the stub functions to perform202  // any fixups required for PIC code.203 204  // For N64, the situation is more regular: code can either be static205  // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code206  // code for N64. Since Clang has already built the relocation model portion207  // of the commandline, we pick add +noabicalls feature in the N64 static208  // case.209 210  // The is another case to be accounted for: -msym32, which enforces that all211  // symbols have 32 bits in size. In this case, N64 can in theory use CPIC212  // but it is unsupported.213 214  // The combinations for N64 are:215  // a) Static without abicalls and 64bit symbols.216  // b) Static with abicalls and 32bit symbols.217  // c) PIC with abicalls and 64bit symbols.218 219  // For case (a) we need to add +noabicalls for N64.220 221  bool IsN64 = ABIName == "64";222  bool IsPIC = false;223  bool NonPIC = false;224  bool HasNaN2008Opt = false;225 226  Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,227                                    options::OPT_fpic, options::OPT_fno_pic,228                                    options::OPT_fPIE, options::OPT_fno_PIE,229                                    options::OPT_fpie, options::OPT_fno_pie);230  if (LastPICArg) {231    Option O = LastPICArg->getOption();232    NonPIC =233        (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||234         O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));235    IsPIC =236        (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||237         O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie));238  }239 240  bool UseAbiCalls = false;241 242  Arg *ABICallsArg =243      Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls);244  UseAbiCalls =245      !ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls);246 247  if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {248    D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls)249        << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);250  }251 252  if (ABICallsArg && !UseAbiCalls && IsPIC) {253    D.Diag(diag::err_drv_unsupported_noabicalls_pic);254  }255 256  if (CPUName == "i6500" || CPUName == "i6400") {257    // MIPS cpu i6400 and i6500 support MSA (Mips SIMD Architecture)258    // by default.259    Features.push_back("+msa");260  }261 262  if (!UseAbiCalls)263    Features.push_back("+noabicalls");264  else265    Features.push_back("-noabicalls");266 267  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,268                               options::OPT_mno_long_calls)) {269    if (A->getOption().matches(options::OPT_mno_long_calls))270      Features.push_back("-long-calls");271    else if (!UseAbiCalls)272      Features.push_back("+long-calls");273    else274      D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1);275  }276 277  if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {278    if (A->getOption().matches(options::OPT_mxgot))279      Features.push_back("+xgot");280    else281      Features.push_back("-xgot");282  }283 284  mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple);285  if (FloatABI == mips::FloatABI::Soft) {286    // FIXME: Note, this is a hack. We need to pass the selected float287    // mode to the MipsTargetInfoBase to define appropriate macros there.288    // Now it is the only method.289    Features.push_back("+soft-float");290  }291 292  if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {293    StringRef Val = StringRef(A->getValue());294    if (Val == "2008") {295      if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {296        Features.push_back("+nan2008");297        HasNaN2008Opt = true;298      } else {299        Features.push_back("-nan2008");300        D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;301      }302    } else if (Val == "legacy") {303      if (mips::getIEEE754Standard(CPUName) & mips::Legacy)304        Features.push_back("-nan2008");305      else {306        Features.push_back("+nan2008");307        D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;308      }309    } else310      D.Diag(diag::err_drv_unsupported_option_argument)311          << A->getSpelling() << Val;312  }313 314  if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) {315    StringRef Val = StringRef(A->getValue());316    if (Val == "2008") {317      if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {318        Features.push_back("+abs2008");319      } else {320        Features.push_back("-abs2008");321        D.Diag(diag::warn_target_unsupported_abs2008) << CPUName;322      }323    } else if (Val == "legacy") {324      if (mips::getIEEE754Standard(CPUName) & mips::Legacy) {325        Features.push_back("-abs2008");326      } else {327        Features.push_back("+abs2008");328        D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName;329      }330    } else {331      D.Diag(diag::err_drv_unsupported_option_argument)332          << A->getSpelling() << Val;333    }334  } else if (HasNaN2008Opt) {335    Features.push_back("+abs2008");336  }337 338  AddTargetFeature(Args, Features, options::OPT_msingle_float,339                   options::OPT_mdouble_float, "single-float");340  AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,341                   "mips16");342  AddTargetFeature(Args, Features, options::OPT_mmicromips,343                   options::OPT_mno_micromips, "micromips");344  AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,345                   "dsp");346  AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,347                   "dspr2");348  AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,349                   "msa");350  if (Arg *A = Args.getLastArg(351          options::OPT_mstrict_align, options::OPT_mno_strict_align,352          options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {353    if (A->getOption().matches(options::OPT_mstrict_align) ||354        A->getOption().matches(options::OPT_mno_unaligned_access))355      Features.push_back(Args.MakeArgString("+strict-align"));356    else357      Features.push_back(Args.MakeArgString("-strict-align"));358  }359 360  // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32361  // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and362  // nooddspreg.363  if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,364                               options::OPT_mfp64)) {365    if (A->getOption().matches(options::OPT_mfp32))366      Features.push_back("-fp64");367    else if (A->getOption().matches(options::OPT_mfpxx)) {368      Features.push_back("+fpxx");369      Features.push_back("+nooddspreg");370    } else371      Features.push_back("+fp64");372  } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {373    Features.push_back("+fpxx");374    Features.push_back("+nooddspreg");375  } else if (Arg *A = Args.getLastArg(options::OPT_mmsa)) {376    if (A->getOption().matches(options::OPT_mmsa))377      Features.push_back("+fp64");378  }379 380  AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,381                   options::OPT_modd_spreg, "nooddspreg");382  AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,383                   "nomadd4");384  AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");385  AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,386                   "crc");387  AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,388                   "virt");389  AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,390                   "ginv");391 392  if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {393    StringRef Val = StringRef(A->getValue());394    if (Val == "hazard") {395      Arg *B =396          Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);397      Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);398 399      if (B && B->getOption().matches(options::OPT_mmicromips))400        D.Diag(diag::err_drv_unsupported_indirect_jump_opt)401            << "hazard" << "micromips";402      else if (C && C->getOption().matches(options::OPT_mips16))403        D.Diag(diag::err_drv_unsupported_indirect_jump_opt)404            << "hazard" << "mips16";405      else if (mips::supportsIndirectJumpHazardBarrier(CPUName))406        Features.push_back("+use-indirect-jump-hazard");407      else408        D.Diag(diag::err_drv_unsupported_indirect_jump_opt)409            << "hazard" << CPUName;410    } else411      D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val;412  }413}414 415mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {416  // Strictly speaking, mips32r2 and mips64r2 do not conform to the417  // IEEE754-2008 standard. Support for this standard was first introduced418  // in Release 3. However, other compilers have traditionally allowed it419  // for Release 2 so we should do the same.420  return (IEEE754Standard)llvm::StringSwitch<int>(CPU)421      .Case("mips1", Legacy)422      .Case("mips2", Legacy)423      .Case("mips3", Legacy)424      .Case("mips4", Legacy)425      .Case("mips5", Legacy)426      .Case("mips32", Legacy)427      .Case("mips32r2", Legacy | Std2008)428      .Case("mips32r3", Legacy | Std2008)429      .Case("mips32r5", Legacy | Std2008)430      .Case("mips32r6", Std2008)431      .Case("mips64", Legacy)432      .Case("mips64r2", Legacy | Std2008)433      .Case("mips64r3", Legacy | Std2008)434      .Case("mips64r5", Legacy | Std2008)435      .Case("mips64r6", Std2008)436      .Default(Std2008);437}438 439bool mips::hasCompactBranches(StringRef &CPU) {440  // mips32r6 and mips64r6 have compact branches.441  return llvm::StringSwitch<bool>(CPU)442      .Case("mips32r6", true)443      .Case("mips64r6", true)444      .Case("i6400", true)445      .Case("i6500", true)446      .Default(false);447}448 449bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {450  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);451  return A && (A->getValue() == StringRef(Value));452}453 454bool mips::isUCLibc(const ArgList &Args) {455  Arg *A = Args.getLastArg(options::OPT_m_libc_Group);456  return A && A->getOption().matches(options::OPT_muclibc);457}458 459bool mips::isNaN2008(const Driver &D, const ArgList &Args,460                     const llvm::Triple &Triple) {461  if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))462    return llvm::StringSwitch<bool>(NaNArg->getValue())463        .Case("2008", true)464        .Case("legacy", false)465        .Default(false);466 467  // NaN2008 is the default for MIPS32r6/MIPS64r6.468  return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple))469      .Cases({"mips32r6", "mips64r6"}, true)470      .Default(false);471}472 473bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,474                         StringRef ABIName, mips::FloatABI FloatABI) {475  if (ABIName != "32")476    return false;477 478  // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is479  // present.480  if (FloatABI == mips::FloatABI::Soft)481    return false;482 483  return llvm::StringSwitch<bool>(CPUName)484      .Cases({"mips2", "mips3", "mips4", "mips5"}, true)485      .Cases({"mips32", "mips32r2", "mips32r3", "mips32r5"}, true)486      .Cases({"mips64", "mips64r2", "mips64r3", "mips64r5"}, true)487      .Default(false);488}489 490bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,491                         StringRef CPUName, StringRef ABIName,492                         mips::FloatABI FloatABI) {493  bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);494 495  // FPXX shouldn't be used if -msingle-float is present.496  if (Arg *A = Args.getLastArg(options::OPT_msingle_float,497                               options::OPT_mdouble_float))498    if (A->getOption().matches(options::OPT_msingle_float))499      UseFPXX = false;500  // FP64 should be used for MSA.501  if (Arg *A = Args.getLastArg(options::OPT_mmsa))502    if (A->getOption().matches(options::OPT_mmsa))503      UseFPXX = llvm::StringSwitch<bool>(CPUName)504                    .Cases({"mips32r2", "mips32r3", "mips32r5"}, false)505                    .Cases({"mips64r2", "mips64r3", "mips64r5"}, false)506                    .Default(UseFPXX);507 508  return UseFPXX;509}510 511bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {512  // Supporting the hazard barrier method of dealing with indirect513  // jumps requires MIPSR2 support.514  return llvm::StringSwitch<bool>(CPU)515      .Case("mips32r2", true)516      .Case("mips32r3", true)517      .Case("mips32r5", true)518      .Case("mips32r6", true)519      .Case("mips64r2", true)520      .Case("mips64r3", true)521      .Case("mips64r5", true)522      .Case("mips64r6", true)523      .Case("octeon", true)524      .Case("p5600", true)525      .Case("i6400", true)526      .Case("i6500", true)527      .Default(false);528}529