375 lines · cpp
1//===--- Mips.cpp - Implement Mips target feature support -----------------===//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 implements Mips TargetInfo objects.10//11//===----------------------------------------------------------------------===//12 13#include "Mips.h"14#include "clang/Basic/Diagnostic.h"15#include "clang/Basic/MacroBuilder.h"16#include "clang/Basic/TargetBuiltins.h"17#include "llvm/ADT/StringSwitch.h"18 19using namespace clang;20using namespace clang::targets;21 22static constexpr int NumBuiltins =23 clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin;24 25static constexpr llvm::StringTable BuiltinStrings =26 CLANG_BUILTIN_STR_TABLE_START27#define BUILTIN CLANG_BUILTIN_STR_TABLE28#include "clang/Basic/BuiltinsMips.def"29 ;30 31static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({32#define BUILTIN CLANG_BUILTIN_ENTRY33#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY34#include "clang/Basic/BuiltinsMips.def"35});36 37bool MipsTargetInfo::processorSupportsGPR64() const {38 return llvm::StringSwitch<bool>(CPU)39 .Case("mips3", true)40 .Case("mips4", true)41 .Case("mips5", true)42 .Case("mips64", true)43 .Case("mips64r2", true)44 .Case("mips64r3", true)45 .Case("mips64r5", true)46 .Case("mips64r6", true)47 .Case("octeon", true)48 .Case("octeon+", true)49 .Case("i6400", true)50 .Case("i6500", true)51 .Default(false);52}53 54static constexpr llvm::StringLiteral ValidCPUNames[] = {55 {"mips1"}, {"mips2"}, {"mips3"}, {"mips4"}, {"mips5"},56 {"mips32"}, {"mips32r2"}, {"mips32r3"}, {"mips32r5"}, {"mips32r6"},57 {"mips64"}, {"mips64r2"}, {"mips64r3"}, {"mips64r5"}, {"mips64r6"},58 {"octeon"}, {"octeon+"}, {"p5600"}, {"i6400"}, {"i6500"}};59 60bool MipsTargetInfo::isValidCPUName(StringRef Name) const {61 return llvm::is_contained(ValidCPUNames, Name);62}63 64void MipsTargetInfo::fillValidCPUList(65 SmallVectorImpl<StringRef> &Values) const {66 Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));67}68 69unsigned MipsTargetInfo::getISARev() const {70 return llvm::StringSwitch<unsigned>(getCPU())71 .Cases({"mips32", "mips64"}, 1)72 .Cases({"mips32r2", "mips64r2", "octeon", "octeon+"}, 2)73 .Cases({"mips32r3", "mips64r3"}, 3)74 .Cases({"mips32r5", "mips64r5", "p5600"}, 5)75 .Cases({"mips32r6", "mips64r6", "i6400", "i6500"}, 6)76 .Default(0);77}78 79void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,80 MacroBuilder &Builder) const {81 if (BigEndian) {82 DefineStd(Builder, "MIPSEB", Opts);83 Builder.defineMacro("_MIPSEB");84 } else {85 DefineStd(Builder, "MIPSEL", Opts);86 Builder.defineMacro("_MIPSEL");87 }88 89 Builder.defineMacro("__mips__");90 Builder.defineMacro("_mips");91 if (Opts.GNUMode)92 Builder.defineMacro("mips");93 94 if (ABI == "o32") {95 Builder.defineMacro("__mips", "32");96 Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS32");97 } else {98 Builder.defineMacro("__mips", "64");99 Builder.defineMacro("__mips64");100 Builder.defineMacro("__mips64__");101 Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64");102 }103 104 const std::string ISARev = std::to_string(getISARev());105 106 if (!ISARev.empty())107 Builder.defineMacro("__mips_isa_rev", ISARev);108 109 if (ABI == "o32") {110 Builder.defineMacro("__mips_o32");111 Builder.defineMacro("_ABIO32", "1");112 Builder.defineMacro("_MIPS_SIM", "_ABIO32");113 } else if (ABI == "n32") {114 Builder.defineMacro("__mips_n32");115 Builder.defineMacro("_ABIN32", "2");116 Builder.defineMacro("_MIPS_SIM", "_ABIN32");117 } else if (ABI == "n64") {118 Builder.defineMacro("__mips_n64");119 Builder.defineMacro("_ABI64", "3");120 Builder.defineMacro("_MIPS_SIM", "_ABI64");121 } else122 llvm_unreachable("Invalid ABI.");123 124 if (!IsNoABICalls) {125 Builder.defineMacro("__mips_abicalls");126 if (CanUseBSDABICalls)127 Builder.defineMacro("__ABICALLS__");128 }129 130 Builder.defineMacro("__REGISTER_PREFIX__", "");131 132 switch (FloatABI) {133 case HardFloat:134 Builder.defineMacro("__mips_hard_float", Twine(1));135 break;136 case SoftFloat:137 Builder.defineMacro("__mips_soft_float", Twine(1));138 break;139 }140 141 if (IsSingleFloat)142 Builder.defineMacro("__mips_single_float", Twine(1));143 144 switch (FPMode) {145 case FPXX:146 Builder.defineMacro("__mips_fpr", Twine(0));147 break;148 case FP32:149 Builder.defineMacro("__mips_fpr", Twine(32));150 break;151 case FP64:152 Builder.defineMacro("__mips_fpr", Twine(64));153 break;154}155 156 if (FPMode == FP64 || IsSingleFloat)157 Builder.defineMacro("_MIPS_FPSET", Twine(32));158 else159 Builder.defineMacro("_MIPS_FPSET", Twine(16));160 if (NoOddSpreg)161 Builder.defineMacro("_MIPS_SPFPSET", Twine(16));162 else163 Builder.defineMacro("_MIPS_SPFPSET", Twine(32));164 165 if (IsMips16)166 Builder.defineMacro("__mips16", Twine(1));167 168 if (IsMicromips)169 Builder.defineMacro("__mips_micromips", Twine(1));170 171 if (IsNan2008)172 Builder.defineMacro("__mips_nan2008", Twine(1));173 174 if (IsAbs2008)175 Builder.defineMacro("__mips_abs2008", Twine(1));176 177 switch (DspRev) {178 default:179 break;180 case DSP1:181 Builder.defineMacro("__mips_dsp_rev", Twine(1));182 Builder.defineMacro("__mips_dsp", Twine(1));183 break;184 case DSP2:185 Builder.defineMacro("__mips_dsp_rev", Twine(2));186 Builder.defineMacro("__mips_dspr2", Twine(1));187 Builder.defineMacro("__mips_dsp", Twine(1));188 break;189 }190 191 if (HasMSA)192 Builder.defineMacro("__mips_msa", Twine(1));193 194 if (DisableMadd4)195 Builder.defineMacro("__mips_no_madd4", Twine(1));196 197 Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(LangAS::Default)));198 Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));199 Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));200 201 Builder.defineMacro("_MIPS_ARCH", "\"" + CPU + "\"");202 if (CPU == "octeon+")203 Builder.defineMacro("_MIPS_ARCH_OCTEONP");204 else205 Builder.defineMacro("_MIPS_ARCH_" + StringRef(CPU).upper());206 207 if (StringRef(CPU).starts_with("octeon"))208 Builder.defineMacro("__OCTEON__");209 210 if (CPU != "mips1") {211 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");212 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");213 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");214 }215 216 // 32-bit MIPS processors don't have the necessary lld/scd instructions217 // found in 64-bit processors. In the case of O32 on a 64-bit processor,218 // the instructions exist but using them violates the ABI since they219 // require 64-bit GPRs and O32 only supports 32-bit GPRs.220 if (ABI == "n32" || ABI == "n64")221 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");222}223 224bool MipsTargetInfo::hasFeature(StringRef Feature) const {225 return llvm::StringSwitch<bool>(Feature)226 .Case("mips", true)227 .Case("dsp", DspRev >= DSP1)228 .Case("dspr2", DspRev >= DSP2)229 .Case("fp64", FPMode == FP64)230 .Case("msa", HasMSA)231 .Default(false);232}233 234llvm::SmallVector<Builtin::InfosShard>235MipsTargetInfo::getTargetBuiltins() const {236 return {{&BuiltinStrings, BuiltinInfos}};237}238 239unsigned MipsTargetInfo::getUnwindWordWidth() const {240 return llvm::StringSwitch<unsigned>(ABI)241 .Case("o32", 32)242 .Case("n32", 64)243 .Case("n64", 64)244 .Default(getPointerWidth(LangAS::Default));245}246 247bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {248 // microMIPS64R6 backend was removed.249 if (getTriple().isMIPS64() && IsMicromips && (ABI == "n32" || ABI == "n64")) {250 Diags.Report(diag::err_target_unsupported_cpu_for_micromips) << CPU;251 return false;252 }253 254 // 64-bit ABI's require 64-bit CPU's.255 if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) {256 Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;257 return false;258 }259 260 // -fpxx is valid only for the o32 ABI261 if (FPMode == FPXX && (ABI == "n32" || ABI == "n64")) {262 Diags.Report(diag::err_unsupported_abi_for_opt) << "-mfpxx" << "o32";263 return false;264 }265 266 // -mfp32 and n32/n64 ABIs are incompatible267 if (FPMode != FP64 && FPMode != FPXX && !IsSingleFloat &&268 (ABI == "n32" || ABI == "n64")) {269 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx" << CPU;270 return false;271 }272 // Mips revision 6 and -mfp32 are incompatible273 if (FPMode != FP64 && FPMode != FPXX &&274 (CPU == "mips32r6" || CPU == "mips64r6" || CPU == "i6400" ||275 CPU == "i6500")) {276 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfp32" << CPU;277 return false;278 }279 // Option -mfp64 permitted on Mips32 iff revision 2 or higher is present280 if (FPMode == FP64 && (CPU == "mips1" || CPU == "mips2" ||281 getISARev() < 2) && ABI == "o32") {282 Diags.Report(diag::err_mips_fp64_req) << "-mfp64";283 return false;284 }285 // FPXX requires mips2+286 if (FPMode == FPXX && CPU == "mips1") {287 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx" << CPU;288 return false;289 }290 // -mmsa with -msoft-float makes nonsense291 if (FloatABI == SoftFloat && HasMSA) {292 Diags.Report(diag::err_opt_not_valid_with_opt) << "-msoft-float"293 << "-mmsa";294 return false;295 }296 // Option -mmsa permitted on Mips32 iff revision 2 or higher is present297 if (HasMSA && (CPU == "mips1" || CPU == "mips2" || getISARev() < 2) &&298 ABI == "o32") {299 Diags.Report(diag::err_mips_fp64_req) << "-mmsa";300 return false;301 }302 // MSA requires FP64303 if (FPMode == FPXX && HasMSA) {304 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx"305 << "-mmsa";306 return false;307 }308 if (FPMode == FP32 && HasMSA) {309 Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfp32"310 << "-mmsa";311 return false;312 }313 314 return true;315}316 317WindowsMipsTargetInfo::WindowsMipsTargetInfo(const llvm::Triple &Triple,318 const TargetOptions &Opts)319 : WindowsTargetInfo<MipsTargetInfo>(Triple, Opts), Triple(Triple) {}320 321void WindowsMipsTargetInfo::getVisualStudioDefines(322 const LangOptions &Opts, MacroBuilder &Builder) const {323 Builder.defineMacro("_M_MRX000", "4000");324}325 326TargetInfo::BuiltinVaListKind327WindowsMipsTargetInfo::getBuiltinVaListKind() const {328 return TargetInfo::CharPtrBuiltinVaList;329}330 331TargetInfo::CallingConvCheckResult332WindowsMipsTargetInfo::checkCallingConvention(CallingConv CC) const {333 switch (CC) {334 case CC_X86StdCall:335 case CC_X86ThisCall:336 case CC_X86FastCall:337 case CC_X86VectorCall:338 return CCCR_Ignore;339 case CC_C:340 case CC_DeviceKernel:341 case CC_PreserveMost:342 case CC_PreserveAll:343 case CC_Swift:344 case CC_SwiftAsync:345 return CCCR_OK;346 default:347 return CCCR_Warning;348 }349}350 351// Windows MIPS, MS (C++) ABI352MicrosoftMipsTargetInfo::MicrosoftMipsTargetInfo(const llvm::Triple &Triple,353 const TargetOptions &Opts)354 : WindowsMipsTargetInfo(Triple, Opts) {355 TheCXXABI.set(TargetCXXABI::Microsoft);356}357 358void MicrosoftMipsTargetInfo::getTargetDefines(const LangOptions &Opts,359 MacroBuilder &Builder) const {360 WindowsMipsTargetInfo::getTargetDefines(Opts, Builder);361 WindowsMipsTargetInfo::getVisualStudioDefines(Opts, Builder);362}363 364MinGWMipsTargetInfo::MinGWMipsTargetInfo(const llvm::Triple &Triple,365 const TargetOptions &Opts)366 : WindowsMipsTargetInfo(Triple, Opts) {367 TheCXXABI.set(TargetCXXABI::GenericMIPS);368}369 370void MinGWMipsTargetInfo::getTargetDefines(const LangOptions &Opts,371 MacroBuilder &Builder) const {372 WindowsMipsTargetInfo::getTargetDefines(Opts, Builder);373 Builder.defineMacro("_MIPS_");374}375