brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.2 KiB · 930271c Raw
495 lines · c
1//===--- Mips.h - Declare Mips target feature support -----------*- 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// This file declares Mips TargetInfo objects.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H14#define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H15 16#include "OSTargets.h"17#include "clang/Basic/TargetInfo.h"18#include "clang/Basic/TargetOptions.h"19#include "llvm/Support/Compiler.h"20#include "llvm/TargetParser/Triple.h"21 22namespace clang {23namespace targets {24 25class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {26  void setDataLayout() {27    StringRef Layout;28 29    if (ABI == "o32")30      Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";31    else if (ABI == "n32")32      Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128";33    else if (ABI == "n64")34      Layout = "m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128";35    else36      llvm_unreachable("Invalid ABI");37 38    if (BigEndian)39      resetDataLayout(("E-" + Layout).str());40    else41      resetDataLayout(("e-" + Layout).str());42  }43 44  std::string CPU;45  bool IsMips16;46  bool IsMicromips;47  bool IsNan2008;48  bool IsAbs2008;49  bool IsSingleFloat;50  bool IsNoABICalls;51  bool CanUseBSDABICalls;52  enum MipsFloatABI { HardFloat, SoftFloat } FloatABI;53  enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev;54  bool HasMSA;55  bool DisableMadd4;56  bool UseIndirectJumpHazard;57  bool NoOddSpreg;58 59protected:60  enum FPModeEnum { FPXX, FP32, FP64 } FPMode;61  std::string ABI;62 63public:64  MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &)65      : TargetInfo(Triple), IsMips16(false), IsMicromips(false),66        IsNan2008(false), IsAbs2008(false), IsSingleFloat(false),67        IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat),68        DspRev(NoDSP), HasMSA(false), DisableMadd4(false),69        UseIndirectJumpHazard(false), FPMode(FPXX) {70    TheCXXABI.set(TargetCXXABI::GenericMIPS);71 72    if (Triple.isMIPS32())73      setABI("o32");74    else if (Triple.isABIN32())75      setABI("n32");76    else77      setABI("n64");78 79    CPU = ABI == "o32" ? "mips32r2" : "mips64r2";80 81    CanUseBSDABICalls = Triple.isOSFreeBSD() ||82                        Triple.isOSOpenBSD();83  }84 85  bool isIEEE754_2008Default() const {86    return CPU == "mips32r6" || CPU == "mips64r6" || CPU == "i6400" ||87           CPU == "i6500";88  }89 90  enum FPModeEnum getDefaultFPMode() const {91    if (CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64")92      return FP64;93    else if (CPU == "mips1")94      return FP32;95    else96      return FPXX;97  }98 99  bool isNan2008() const override { return IsNan2008; }100 101  bool processorSupportsGPR64() const;102 103  StringRef getABI() const override { return ABI; }104 105  bool setABI(const std::string &Name) override {106    if (Name == "o32") {107      setO32ABITypes();108      ABI = Name;109      return true;110    }111 112    if (Name == "n32") {113      setN32ABITypes();114      ABI = Name;115      return true;116    }117    if (Name == "n64") {118      setN64ABITypes();119      ABI = Name;120      return true;121    }122    return false;123  }124 125  void setO32ABITypes() {126    Int64Type = SignedLongLong;127    IntMaxType = Int64Type;128    LongDoubleFormat = &llvm::APFloat::IEEEdouble();129    LongDoubleWidth = LongDoubleAlign = 64;130    LongWidth = LongAlign = 32;131    MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;132    PointerWidth = PointerAlign = 32;133    PtrDiffType = IntPtrType = SignedInt;134    SizeType = UnsignedInt;135    SuitableAlign = 64;136  }137 138  void setN32N64ABITypes() {139    LongDoubleWidth = LongDoubleAlign = 128;140    LongDoubleFormat = &llvm::APFloat::IEEEquad();141    if (getTriple().isOSFreeBSD()) {142      LongDoubleWidth = LongDoubleAlign = 64;143      LongDoubleFormat = &llvm::APFloat::IEEEdouble();144    }145    MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;146    SuitableAlign = 128;147  }148 149  void setN64ABITypes() {150    setN32N64ABITypes();151    if (getTriple().isOSOpenBSD()) {152      Int64Type = SignedLongLong;153    } else {154      Int64Type = SignedLong;155    }156    IntMaxType = Int64Type;157    LongWidth = LongAlign = 64;158    PointerWidth = PointerAlign = 64;159    PtrDiffType = IntPtrType = SignedLong;160    SizeType = UnsignedLong;161  }162 163  void setN32ABITypes() {164    setN32N64ABITypes();165    Int64Type = SignedLongLong;166    IntMaxType = Int64Type;167    LongWidth = LongAlign = 32;168    PointerWidth = PointerAlign = 32;169    PtrDiffType = IntPtrType = SignedInt;170    SizeType = UnsignedInt;171  }172 173  bool isValidCPUName(StringRef Name) const override;174  void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;175 176  bool setCPU(const std::string &Name) override {177    CPU = Name;178    return isValidCPUName(Name);179  }180 181  const std::string &getCPU() const { return CPU; }182  bool183  initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,184                 StringRef CPU,185                 const std::vector<std::string> &FeaturesVec) const override {186    if (CPU.empty())187      CPU = getCPU();188    if (CPU == "octeon")189      Features["mips64r2"] = Features["cnmips"] = true;190    else if (CPU == "octeon+")191      Features["mips64r2"] = Features["cnmips"] = Features["cnmipsp"] = true;192    else193      Features[CPU] = true;194    return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);195  }196 197  unsigned getISARev() const;198 199  void getTargetDefines(const LangOptions &Opts,200                        MacroBuilder &Builder) const override;201 202  llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override;203 204  bool hasFeature(StringRef Feature) const override;205 206  BuiltinVaListKind getBuiltinVaListKind() const override {207    return TargetInfo::VoidPtrBuiltinVaList;208  }209 210  ArrayRef<const char *> getGCCRegNames() const override {211    static const char *const GCCRegNames[] = {212        // CPU register names213        // Must match second column of GCCRegAliases214        "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10",215        "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20",216        "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30",217        "$31",218        // Floating point register names219        "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",220        "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",221        "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",222        "$f28", "$f29", "$f30", "$f31",223        // Hi/lo and condition register names224        "hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5",225        "$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi",226        "$ac3lo",227        // MSA register names228        "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9",229        "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18",230        "$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27",231        "$w28", "$w29", "$w30", "$w31",232        // MSA control register names233        "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify",234        "$msarequest", "$msamap", "$msaunmap"235    };236    return llvm::ArrayRef(GCCRegNames);237  }238 239  bool validateAsmConstraint(const char *&Name,240                             TargetInfo::ConstraintInfo &Info) const override {241    switch (*Name) {242    default:243      return false;244    case 'r': // CPU registers.245    case 'd': // Equivalent to "r" unless generating MIPS16 code.246    case 'y': // Equivalent to "r", backward compatibility only.247    case 'c': // $25 for indirect jumps248    case 'l': // lo register249    case 'x': // hilo register pair250      Info.setAllowsRegister();251      return true;252    case 'f': // floating-point registers.253      Info.setAllowsRegister();254      return FloatABI != SoftFloat;255    case 'I': // Signed 16-bit constant256    case 'J': // Integer 0257    case 'K': // Unsigned 16-bit constant258    case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui)259    case 'M': // Constants not loadable via lui, addiu, or ori260    case 'N': // Constant -1 to -65535261    case 'O': // A signed 15-bit constant262    case 'P': // A constant between 1 go 65535263      return true;264    case 'R': // An address that can be used in a non-macro load or store265      Info.setAllowsMemory();266      return true;267    case 'Z':268      if (Name[1] == 'C') { // An address usable by ll, and sc.269        Info.setAllowsMemory();270        Name++; // Skip over 'Z'.271        return true;272      }273      return false;274    }275  }276 277  std::string convertConstraint(const char *&Constraint) const override {278    std::string R;279    switch (*Constraint) {280    case 'Z': // Two-character constraint; add "^" hint for later parsing.281      if (Constraint[1] == 'C') {282        R = std::string("^") + std::string(Constraint, 2);283        Constraint++;284        return R;285      }286      break;287    }288    return TargetInfo::convertConstraint(Constraint);289  }290 291  std::string_view getClobbers() const override {292    // In GCC, $1 is not widely used in generated code (it's used only in a few293    // specific situations), so there is no real need for users to add it to294    // the clobbers list if they want to use it in their inline assembly code.295    //296    // In LLVM, $1 is treated as a normal GPR and is always allocatable during297    // code generation, so using it in inline assembly without adding it to the298    // clobbers list can cause conflicts between the inline assembly code and299    // the surrounding generated code.300    //301    // Another problem is that LLVM is allowed to choose $1 for inline assembly302    // operands, which will conflict with the ".set at" assembler option (which303    // we use only for inline assembly, in order to maintain compatibility with304    // GCC) and will also conflict with the user's usage of $1.305    //306    // The easiest way to avoid these conflicts and keep $1 as an allocatable307    // register for generated code is to automatically clobber $1 for all inline308    // assembly code.309    //310    // FIXME: We should automatically clobber $1 only for inline assembly code311    // which actually uses it. This would allow LLVM to use $1 for inline312    // assembly operands if the user's assembly code doesn't use it.313    return "~{$1}";314  }315 316  bool handleTargetFeatures(std::vector<std::string> &Features,317                            DiagnosticsEngine &Diags) override {318    IsMips16 = false;319    IsMicromips = false;320    IsNan2008 = isIEEE754_2008Default();321    IsAbs2008 = isIEEE754_2008Default();322    IsSingleFloat = false;323    FloatABI = HardFloat;324    DspRev = NoDSP;325    NoOddSpreg = false;326    FPMode = getDefaultFPMode();327    bool OddSpregGiven = false;328    bool StrictAlign = false;329    bool FpGiven = false;330 331    for (const auto &Feature : Features) {332      if (Feature == "+single-float")333        IsSingleFloat = true;334      else if (Feature == "+soft-float")335        FloatABI = SoftFloat;336      else if (Feature == "+mips16")337        IsMips16 = true;338      else if (Feature == "+micromips")339        IsMicromips = true;340      else if (Feature == "+mips32r6" || Feature == "+mips64r6")341        HasUnalignedAccess = true;342      // We cannot be sure that the order of strict-align vs mips32r6.343      // Thus we need an extra variable here.344      else if (Feature == "+strict-align")345        StrictAlign = true;346      else if (Feature == "+dsp")347        DspRev = std::max(DspRev, DSP1);348      else if (Feature == "+dspr2")349        DspRev = std::max(DspRev, DSP2);350      else if (Feature == "+msa")351        HasMSA = true;352      else if (Feature == "+nomadd4")353        DisableMadd4 = true;354      else if (Feature == "+fp64") {355        FPMode = FP64;356        FpGiven = true;357      } else if (Feature == "-fp64") {358        FPMode = FP32;359        FpGiven = true;360      } else if (Feature == "+fpxx") {361        FPMode = FPXX;362        FpGiven = true;363      } else if (Feature == "+nan2008")364        IsNan2008 = true;365      else if (Feature == "-nan2008")366        IsNan2008 = false;367      else if (Feature == "+abs2008")368        IsAbs2008 = true;369      else if (Feature == "-abs2008")370        IsAbs2008 = false;371      else if (Feature == "+noabicalls")372        IsNoABICalls = true;373      else if (Feature == "+use-indirect-jump-hazard")374        UseIndirectJumpHazard = true;375      else if (Feature == "+nooddspreg") {376        NoOddSpreg = true;377        OddSpregGiven = false;378      } else if (Feature == "-nooddspreg") {379        NoOddSpreg = false;380        OddSpregGiven = true;381      }382    }383 384    if (FPMode == FPXX && !OddSpregGiven)385      NoOddSpreg = true;386 387    if (StrictAlign)388      HasUnalignedAccess = false;389 390    if (HasMSA && !FpGiven) {391      FPMode = FP64;392      Features.push_back("+fp64");393    }394 395    setDataLayout();396 397    return true;398  }399 400  int getEHDataRegisterNumber(unsigned RegNo) const override {401    if (RegNo == 0)402      return 4;403    if (RegNo == 1)404      return 5;405    return -1;406  }407 408  bool isCLZForZeroUndef() const override { return false; }409 410  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {411    static const TargetInfo::GCCRegAlias O32RegAliases[] = {412        {{"at"}, "$1"},  {{"v0"}, "$2"},         {{"v1"}, "$3"},413        {{"a0"}, "$4"},  {{"a1"}, "$5"},         {{"a2"}, "$6"},414        {{"a3"}, "$7"},  {{"t0"}, "$8"},         {{"t1"}, "$9"},415        {{"t2"}, "$10"}, {{"t3"}, "$11"},        {{"t4"}, "$12"},416        {{"t5"}, "$13"}, {{"t6"}, "$14"},        {{"t7"}, "$15"},417        {{"s0"}, "$16"}, {{"s1"}, "$17"},        {{"s2"}, "$18"},418        {{"s3"}, "$19"}, {{"s4"}, "$20"},        {{"s5"}, "$21"},419        {{"s6"}, "$22"}, {{"s7"}, "$23"},        {{"t8"}, "$24"},420        {{"t9"}, "$25"}, {{"k0"}, "$26"},        {{"k1"}, "$27"},421        {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},422        {{"ra"}, "$31"}423    };424    static const TargetInfo::GCCRegAlias NewABIRegAliases[] = {425        {{"at"}, "$1"},  {{"v0"}, "$2"},         {{"v1"}, "$3"},426        {{"a0"}, "$4"},  {{"a1"}, "$5"},         {{"a2"}, "$6"},427        {{"a3"}, "$7"},  {{"a4"}, "$8"},         {{"a5"}, "$9"},428        {{"a6"}, "$10"}, {{"a7"}, "$11"},        {{"t0"}, "$12"},429        {{"t1"}, "$13"}, {{"t2"}, "$14"},        {{"t3"}, "$15"},430        {{"s0"}, "$16"}, {{"s1"}, "$17"},        {{"s2"}, "$18"},431        {{"s3"}, "$19"}, {{"s4"}, "$20"},        {{"s5"}, "$21"},432        {{"s6"}, "$22"}, {{"s7"}, "$23"},        {{"t8"}, "$24"},433        {{"t9"}, "$25"}, {{"k0"}, "$26"},        {{"k1"}, "$27"},434        {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},435        {{"ra"}, "$31"}436    };437    if (ABI == "o32")438      return llvm::ArrayRef(O32RegAliases);439    return llvm::ArrayRef(NewABIRegAliases);440  }441 442  bool hasInt128Type() const override {443    return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128;444  }445 446  unsigned getUnwindWordWidth() const override;447 448  bool validateTarget(DiagnosticsEngine &Diags) const override;449  bool hasBitIntType() const override { return true; }450 451  std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {452    return std::make_pair(32, 32);453  }454};455 456class LLVM_LIBRARY_VISIBILITY WindowsMipsTargetInfo457    : public WindowsTargetInfo<MipsTargetInfo> {458  const llvm::Triple Triple;459 460public:461  WindowsMipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);462 463  void getVisualStudioDefines(const LangOptions &Opts,464                              MacroBuilder &Builder) const;465 466  BuiltinVaListKind getBuiltinVaListKind() const override;467 468  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;469};470 471// Windows MIPS, MS (C++) ABI472class LLVM_LIBRARY_VISIBILITY MicrosoftMipsTargetInfo473    : public WindowsMipsTargetInfo {474public:475  MicrosoftMipsTargetInfo(const llvm::Triple &Triple,476                          const TargetOptions &Opts);477 478  void getTargetDefines(const LangOptions &Opts,479                        MacroBuilder &Builder) const override;480};481 482// MIPS MinGW target483class LLVM_LIBRARY_VISIBILITY MinGWMipsTargetInfo484    : public WindowsMipsTargetInfo {485public:486  MinGWMipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);487 488  void getTargetDefines(const LangOptions &Opts,489                        MacroBuilder &Builder) const override;490};491} // namespace targets492} // namespace clang493 494#endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H495