Path: blob/main/contrib/llvm-project/clang/lib/Basic/Targets/Mips.h
35266 views
//===--- Mips.h - Declare Mips target feature support -----------*- 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//===----------------------------------------------------------------------===//7//8// This file declares Mips TargetInfo objects.9//10//===----------------------------------------------------------------------===//1112#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H13#define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H1415#include "clang/Basic/TargetInfo.h"16#include "clang/Basic/TargetOptions.h"17#include "llvm/Support/Compiler.h"18#include "llvm/TargetParser/Triple.h"1920namespace clang {21namespace targets {2223class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {24void setDataLayout() {25StringRef Layout;2627if (ABI == "o32")28Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64";29else if (ABI == "n32")30Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128";31else if (ABI == "n64")32Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128";33else34llvm_unreachable("Invalid ABI");3536if (BigEndian)37resetDataLayout(("E-" + Layout).str());38else39resetDataLayout(("e-" + Layout).str());40}4142std::string CPU;43bool IsMips16;44bool IsMicromips;45bool IsNan2008;46bool IsAbs2008;47bool IsSingleFloat;48bool IsNoABICalls;49bool CanUseBSDABICalls;50enum MipsFloatABI { HardFloat, SoftFloat } FloatABI;51enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev;52bool HasMSA;53bool DisableMadd4;54bool UseIndirectJumpHazard;55bool NoOddSpreg;5657protected:58enum FPModeEnum { FPXX, FP32, FP64 } FPMode;59std::string ABI;6061public:62MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &)63: TargetInfo(Triple), IsMips16(false), IsMicromips(false),64IsNan2008(false), IsAbs2008(false), IsSingleFloat(false),65IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat),66DspRev(NoDSP), HasMSA(false), DisableMadd4(false),67UseIndirectJumpHazard(false), FPMode(FPXX) {68TheCXXABI.set(TargetCXXABI::GenericMIPS);6970if (Triple.isMIPS32())71setABI("o32");72else if (Triple.getEnvironment() == llvm::Triple::GNUABIN32)73setABI("n32");74else75setABI("n64");7677CPU = ABI == "o32" ? "mips32r2" : "mips64r2";7879CanUseBSDABICalls = Triple.isOSFreeBSD() ||80Triple.isOSOpenBSD();81}8283bool isIEEE754_2008Default() const {84return CPU == "mips32r6" || CPU == "mips64r6";85}8687enum FPModeEnum getDefaultFPMode() const {88if (CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64")89return FP64;90else if (CPU == "mips1")91return FP32;92else93return FPXX;94}9596bool isNan2008() const override { return IsNan2008; }9798bool processorSupportsGPR64() const;99100StringRef getABI() const override { return ABI; }101102bool setABI(const std::string &Name) override {103if (Name == "o32") {104setO32ABITypes();105ABI = Name;106return true;107}108109if (Name == "n32") {110setN32ABITypes();111ABI = Name;112return true;113}114if (Name == "n64") {115setN64ABITypes();116ABI = Name;117return true;118}119return false;120}121122void setO32ABITypes() {123Int64Type = SignedLongLong;124IntMaxType = Int64Type;125LongDoubleFormat = &llvm::APFloat::IEEEdouble();126LongDoubleWidth = LongDoubleAlign = 64;127LongWidth = LongAlign = 32;128MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;129PointerWidth = PointerAlign = 32;130PtrDiffType = SignedInt;131SizeType = UnsignedInt;132SuitableAlign = 64;133}134135void setN32N64ABITypes() {136LongDoubleWidth = LongDoubleAlign = 128;137LongDoubleFormat = &llvm::APFloat::IEEEquad();138if (getTriple().isOSFreeBSD()) {139LongDoubleWidth = LongDoubleAlign = 64;140LongDoubleFormat = &llvm::APFloat::IEEEdouble();141}142MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;143SuitableAlign = 128;144}145146void setN64ABITypes() {147setN32N64ABITypes();148if (getTriple().isOSOpenBSD()) {149Int64Type = SignedLongLong;150} else {151Int64Type = SignedLong;152}153IntMaxType = Int64Type;154LongWidth = LongAlign = 64;155PointerWidth = PointerAlign = 64;156PtrDiffType = SignedLong;157SizeType = UnsignedLong;158}159160void setN32ABITypes() {161setN32N64ABITypes();162Int64Type = SignedLongLong;163IntMaxType = Int64Type;164LongWidth = LongAlign = 32;165PointerWidth = PointerAlign = 32;166PtrDiffType = SignedInt;167SizeType = UnsignedInt;168}169170bool isValidCPUName(StringRef Name) const override;171void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;172173bool setCPU(const std::string &Name) override {174CPU = Name;175return isValidCPUName(Name);176}177178const std::string &getCPU() const { return CPU; }179bool180initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,181StringRef CPU,182const std::vector<std::string> &FeaturesVec) const override {183if (CPU.empty())184CPU = getCPU();185if (CPU == "octeon")186Features["mips64r2"] = Features["cnmips"] = true;187else if (CPU == "octeon+")188Features["mips64r2"] = Features["cnmips"] = Features["cnmipsp"] = true;189else190Features[CPU] = true;191return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);192}193194unsigned getISARev() const;195196void getTargetDefines(const LangOptions &Opts,197MacroBuilder &Builder) const override;198199ArrayRef<Builtin::Info> getTargetBuiltins() const override;200201bool hasFeature(StringRef Feature) const override;202203BuiltinVaListKind getBuiltinVaListKind() const override {204return TargetInfo::VoidPtrBuiltinVaList;205}206207ArrayRef<const char *> getGCCRegNames() const override {208static const char *const GCCRegNames[] = {209// CPU register names210// Must match second column of GCCRegAliases211"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10",212"$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20",213"$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30",214"$31",215// Floating point register names216"$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9",217"$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18",218"$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",219"$f28", "$f29", "$f30", "$f31",220// Hi/lo and condition register names221"hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5",222"$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi",223"$ac3lo",224// MSA register names225"$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9",226"$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18",227"$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27",228"$w28", "$w29", "$w30", "$w31",229// MSA control register names230"$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify",231"$msarequest", "$msamap", "$msaunmap"232};233return llvm::ArrayRef(GCCRegNames);234}235236bool validateAsmConstraint(const char *&Name,237TargetInfo::ConstraintInfo &Info) const override {238switch (*Name) {239default:240return false;241case 'r': // CPU registers.242case 'd': // Equivalent to "r" unless generating MIPS16 code.243case 'y': // Equivalent to "r", backward compatibility only.244case 'c': // $25 for indirect jumps245case 'l': // lo register246case 'x': // hilo register pair247Info.setAllowsRegister();248return true;249case 'f': // floating-point registers.250Info.setAllowsRegister();251return FloatABI != SoftFloat;252case 'I': // Signed 16-bit constant253case 'J': // Integer 0254case 'K': // Unsigned 16-bit constant255case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui)256case 'M': // Constants not loadable via lui, addiu, or ori257case 'N': // Constant -1 to -65535258case 'O': // A signed 15-bit constant259case 'P': // A constant between 1 go 65535260return true;261case 'R': // An address that can be used in a non-macro load or store262Info.setAllowsMemory();263return true;264case 'Z':265if (Name[1] == 'C') { // An address usable by ll, and sc.266Info.setAllowsMemory();267Name++; // Skip over 'Z'.268return true;269}270return false;271}272}273274std::string convertConstraint(const char *&Constraint) const override {275std::string R;276switch (*Constraint) {277case 'Z': // Two-character constraint; add "^" hint for later parsing.278if (Constraint[1] == 'C') {279R = std::string("^") + std::string(Constraint, 2);280Constraint++;281return R;282}283break;284}285return TargetInfo::convertConstraint(Constraint);286}287288std::string_view getClobbers() const override {289// In GCC, $1 is not widely used in generated code (it's used only in a few290// specific situations), so there is no real need for users to add it to291// the clobbers list if they want to use it in their inline assembly code.292//293// In LLVM, $1 is treated as a normal GPR and is always allocatable during294// code generation, so using it in inline assembly without adding it to the295// clobbers list can cause conflicts between the inline assembly code and296// the surrounding generated code.297//298// Another problem is that LLVM is allowed to choose $1 for inline assembly299// operands, which will conflict with the ".set at" assembler option (which300// we use only for inline assembly, in order to maintain compatibility with301// GCC) and will also conflict with the user's usage of $1.302//303// The easiest way to avoid these conflicts and keep $1 as an allocatable304// register for generated code is to automatically clobber $1 for all inline305// assembly code.306//307// FIXME: We should automatically clobber $1 only for inline assembly code308// which actually uses it. This would allow LLVM to use $1 for inline309// assembly operands if the user's assembly code doesn't use it.310return "~{$1}";311}312313bool handleTargetFeatures(std::vector<std::string> &Features,314DiagnosticsEngine &Diags) override {315IsMips16 = false;316IsMicromips = false;317IsNan2008 = isIEEE754_2008Default();318IsAbs2008 = isIEEE754_2008Default();319IsSingleFloat = false;320FloatABI = HardFloat;321DspRev = NoDSP;322NoOddSpreg = false;323FPMode = getDefaultFPMode();324bool OddSpregGiven = false;325bool StrictAlign = false;326bool FpGiven = false;327328for (const auto &Feature : Features) {329if (Feature == "+single-float")330IsSingleFloat = true;331else if (Feature == "+soft-float")332FloatABI = SoftFloat;333else if (Feature == "+mips16")334IsMips16 = true;335else if (Feature == "+micromips")336IsMicromips = true;337else if (Feature == "+mips32r6" || Feature == "+mips64r6")338HasUnalignedAccess = true;339// We cannot be sure that the order of strict-align vs mips32r6.340// Thus we need an extra variable here.341else if (Feature == "+strict-align")342StrictAlign = true;343else if (Feature == "+dsp")344DspRev = std::max(DspRev, DSP1);345else if (Feature == "+dspr2")346DspRev = std::max(DspRev, DSP2);347else if (Feature == "+msa")348HasMSA = true;349else if (Feature == "+nomadd4")350DisableMadd4 = true;351else if (Feature == "+fp64") {352FPMode = FP64;353FpGiven = true;354} else if (Feature == "-fp64") {355FPMode = FP32;356FpGiven = true;357} else if (Feature == "+fpxx") {358FPMode = FPXX;359FpGiven = true;360} else if (Feature == "+nan2008")361IsNan2008 = true;362else if (Feature == "-nan2008")363IsNan2008 = false;364else if (Feature == "+abs2008")365IsAbs2008 = true;366else if (Feature == "-abs2008")367IsAbs2008 = false;368else if (Feature == "+noabicalls")369IsNoABICalls = true;370else if (Feature == "+use-indirect-jump-hazard")371UseIndirectJumpHazard = true;372else if (Feature == "+nooddspreg") {373NoOddSpreg = true;374OddSpregGiven = false;375} else if (Feature == "-nooddspreg") {376NoOddSpreg = false;377OddSpregGiven = true;378}379}380381if (FPMode == FPXX && !OddSpregGiven)382NoOddSpreg = true;383384if (StrictAlign)385HasUnalignedAccess = false;386387if (HasMSA && !FpGiven) {388FPMode = FP64;389Features.push_back("+fp64");390}391392setDataLayout();393394return true;395}396397int getEHDataRegisterNumber(unsigned RegNo) const override {398if (RegNo == 0)399return 4;400if (RegNo == 1)401return 5;402return -1;403}404405bool isCLZForZeroUndef() const override { return false; }406407ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {408static const TargetInfo::GCCRegAlias O32RegAliases[] = {409{{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},410{{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},411{{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"},412{{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"},413{{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"},414{{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},415{{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},416{{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},417{{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},418{{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},419{{"ra"}, "$31"}420};421static const TargetInfo::GCCRegAlias NewABIRegAliases[] = {422{{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"},423{{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"},424{{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"},425{{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"},426{{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"},427{{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"},428{{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"},429{{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"},430{{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"},431{{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"},432{{"ra"}, "$31"}433};434if (ABI == "o32")435return llvm::ArrayRef(O32RegAliases);436return llvm::ArrayRef(NewABIRegAliases);437}438439bool hasInt128Type() const override {440return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128;441}442443unsigned getUnwindWordWidth() const override;444445bool validateTarget(DiagnosticsEngine &Diags) const override;446bool hasBitIntType() const override { return true; }447448std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {449return std::make_pair(32, 32);450}451};452} // namespace targets453} // namespace clang454455#endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H456457458