xref: /openbsd-src/gnu/llvm/clang/lib/Basic/Targets/Mips.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===--- Mips.cpp - Implement Mips target feature support -----------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements Mips TargetInfo objects.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13e5dd7070Spatrick #include "Mips.h"
14e5dd7070Spatrick #include "Targets.h"
15e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
16e5dd7070Spatrick #include "clang/Basic/MacroBuilder.h"
17e5dd7070Spatrick #include "clang/Basic/TargetBuiltins.h"
18e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
19e5dd7070Spatrick 
20e5dd7070Spatrick using namespace clang;
21e5dd7070Spatrick using namespace clang::targets;
22e5dd7070Spatrick 
23*12c85518Srobert static constexpr Builtin::Info BuiltinInfo[] = {
24e5dd7070Spatrick #define BUILTIN(ID, TYPE, ATTRS)                                               \
25*12c85518Srobert   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
26e5dd7070Spatrick #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
27*12c85518Srobert   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
28e5dd7070Spatrick #include "clang/Basic/BuiltinsMips.def"
29e5dd7070Spatrick };
30e5dd7070Spatrick 
processorSupportsGPR64() const31e5dd7070Spatrick bool MipsTargetInfo::processorSupportsGPR64() const {
32e5dd7070Spatrick   return llvm::StringSwitch<bool>(CPU)
33e5dd7070Spatrick       .Case("mips3", true)
34e5dd7070Spatrick       .Case("mips4", true)
35e5dd7070Spatrick       .Case("mips5", true)
36e5dd7070Spatrick       .Case("mips64", true)
37e5dd7070Spatrick       .Case("mips64r2", true)
38e5dd7070Spatrick       .Case("mips64r3", true)
39e5dd7070Spatrick       .Case("mips64r5", true)
40e5dd7070Spatrick       .Case("mips64r6", true)
41e5dd7070Spatrick       .Case("octeon", true)
42e5dd7070Spatrick       .Case("octeon+", true)
43e5dd7070Spatrick       .Default(false);
44e5dd7070Spatrick }
45e5dd7070Spatrick 
46e5dd7070Spatrick static constexpr llvm::StringLiteral ValidCPUNames[] = {
47e5dd7070Spatrick     {"mips1"},  {"mips2"},    {"mips3"},    {"mips4"},    {"mips5"},
48e5dd7070Spatrick     {"mips32"}, {"mips32r2"}, {"mips32r3"}, {"mips32r5"}, {"mips32r6"},
49e5dd7070Spatrick     {"mips64"}, {"mips64r2"}, {"mips64r3"}, {"mips64r5"}, {"mips64r6"},
50e5dd7070Spatrick     {"octeon"}, {"octeon+"}, {"p5600"}};
51e5dd7070Spatrick 
isValidCPUName(StringRef Name) const52e5dd7070Spatrick bool MipsTargetInfo::isValidCPUName(StringRef Name) const {
53*12c85518Srobert   return llvm::is_contained(ValidCPUNames, Name);
54e5dd7070Spatrick }
55e5dd7070Spatrick 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const56e5dd7070Spatrick void MipsTargetInfo::fillValidCPUList(
57e5dd7070Spatrick     SmallVectorImpl<StringRef> &Values) const {
58e5dd7070Spatrick   Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
59e5dd7070Spatrick }
60e5dd7070Spatrick 
getISARev() const61e5dd7070Spatrick unsigned MipsTargetInfo::getISARev() const {
62e5dd7070Spatrick   return llvm::StringSwitch<unsigned>(getCPU())
63e5dd7070Spatrick              .Cases("mips32", "mips64", 1)
64e5dd7070Spatrick              .Cases("mips32r2", "mips64r2", "octeon", "octeon+", 2)
65e5dd7070Spatrick              .Cases("mips32r3", "mips64r3", 3)
66e5dd7070Spatrick              .Cases("mips32r5", "mips64r5", 5)
67e5dd7070Spatrick              .Cases("mips32r6", "mips64r6", 6)
68e5dd7070Spatrick              .Default(0);
69e5dd7070Spatrick }
70e5dd7070Spatrick 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const71e5dd7070Spatrick void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
72e5dd7070Spatrick                                       MacroBuilder &Builder) const {
73e5dd7070Spatrick   if (BigEndian) {
74e5dd7070Spatrick     DefineStd(Builder, "MIPSEB", Opts);
75e5dd7070Spatrick     Builder.defineMacro("_MIPSEB");
76e5dd7070Spatrick   } else {
77e5dd7070Spatrick     DefineStd(Builder, "MIPSEL", Opts);
78e5dd7070Spatrick     Builder.defineMacro("_MIPSEL");
79e5dd7070Spatrick   }
80e5dd7070Spatrick 
81e5dd7070Spatrick   Builder.defineMacro("__mips__");
82e5dd7070Spatrick   Builder.defineMacro("_mips");
83e5dd7070Spatrick   if (Opts.GNUMode)
84e5dd7070Spatrick     Builder.defineMacro("mips");
85e5dd7070Spatrick 
86e5dd7070Spatrick   if (ABI == "o32") {
87e5dd7070Spatrick     Builder.defineMacro("__mips", "32");
88e5dd7070Spatrick     Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS32");
89e5dd7070Spatrick   } else {
90e5dd7070Spatrick     Builder.defineMacro("__mips", "64");
91e5dd7070Spatrick     Builder.defineMacro("__mips64");
92e5dd7070Spatrick     Builder.defineMacro("__mips64__");
93e5dd7070Spatrick     Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64");
94e5dd7070Spatrick   }
95e5dd7070Spatrick 
96e5dd7070Spatrick   const std::string ISARev = std::to_string(getISARev());
97e5dd7070Spatrick 
98e5dd7070Spatrick   if (!ISARev.empty())
99e5dd7070Spatrick     Builder.defineMacro("__mips_isa_rev", ISARev);
100e5dd7070Spatrick 
101e5dd7070Spatrick   if (ABI == "o32") {
102e5dd7070Spatrick     Builder.defineMacro("__mips_o32");
103e5dd7070Spatrick     Builder.defineMacro("_ABIO32", "1");
104e5dd7070Spatrick     Builder.defineMacro("_MIPS_SIM", "_ABIO32");
105e5dd7070Spatrick   } else if (ABI == "n32") {
106e5dd7070Spatrick     Builder.defineMacro("__mips_n32");
107e5dd7070Spatrick     Builder.defineMacro("_ABIN32", "2");
108e5dd7070Spatrick     Builder.defineMacro("_MIPS_SIM", "_ABIN32");
109e5dd7070Spatrick   } else if (ABI == "n64") {
110e5dd7070Spatrick     Builder.defineMacro("__mips_n64");
111e5dd7070Spatrick     Builder.defineMacro("_ABI64", "3");
112e5dd7070Spatrick     Builder.defineMacro("_MIPS_SIM", "_ABI64");
113e5dd7070Spatrick   } else
114e5dd7070Spatrick     llvm_unreachable("Invalid ABI.");
115e5dd7070Spatrick 
116e5dd7070Spatrick   if (!IsNoABICalls) {
117e5dd7070Spatrick     Builder.defineMacro("__mips_abicalls");
118e5dd7070Spatrick     if (CanUseBSDABICalls)
119e5dd7070Spatrick       Builder.defineMacro("__ABICALLS__");
120e5dd7070Spatrick   }
121e5dd7070Spatrick 
122e5dd7070Spatrick   Builder.defineMacro("__REGISTER_PREFIX__", "");
123e5dd7070Spatrick 
124e5dd7070Spatrick   switch (FloatABI) {
125e5dd7070Spatrick   case HardFloat:
126e5dd7070Spatrick     Builder.defineMacro("__mips_hard_float", Twine(1));
127e5dd7070Spatrick     break;
128e5dd7070Spatrick   case SoftFloat:
129e5dd7070Spatrick     Builder.defineMacro("__mips_soft_float", Twine(1));
130e5dd7070Spatrick     break;
131e5dd7070Spatrick   }
132e5dd7070Spatrick 
133e5dd7070Spatrick   if (IsSingleFloat)
134e5dd7070Spatrick     Builder.defineMacro("__mips_single_float", Twine(1));
135e5dd7070Spatrick 
136e5dd7070Spatrick   switch (FPMode) {
137e5dd7070Spatrick   case FPXX:
138e5dd7070Spatrick     Builder.defineMacro("__mips_fpr", Twine(0));
139e5dd7070Spatrick     break;
140e5dd7070Spatrick   case FP32:
141e5dd7070Spatrick     Builder.defineMacro("__mips_fpr", Twine(32));
142e5dd7070Spatrick     break;
143e5dd7070Spatrick   case FP64:
144e5dd7070Spatrick     Builder.defineMacro("__mips_fpr", Twine(64));
145e5dd7070Spatrick     break;
146e5dd7070Spatrick }
147e5dd7070Spatrick 
148e5dd7070Spatrick   if (FPMode == FP64 || IsSingleFloat)
149e5dd7070Spatrick     Builder.defineMacro("_MIPS_FPSET", Twine(32));
150e5dd7070Spatrick   else
151e5dd7070Spatrick     Builder.defineMacro("_MIPS_FPSET", Twine(16));
152e5dd7070Spatrick 
153e5dd7070Spatrick   if (IsMips16)
154e5dd7070Spatrick     Builder.defineMacro("__mips16", Twine(1));
155e5dd7070Spatrick 
156e5dd7070Spatrick   if (IsMicromips)
157e5dd7070Spatrick     Builder.defineMacro("__mips_micromips", Twine(1));
158e5dd7070Spatrick 
159e5dd7070Spatrick   if (IsNan2008)
160e5dd7070Spatrick     Builder.defineMacro("__mips_nan2008", Twine(1));
161e5dd7070Spatrick 
162e5dd7070Spatrick   if (IsAbs2008)
163e5dd7070Spatrick     Builder.defineMacro("__mips_abs2008", Twine(1));
164e5dd7070Spatrick 
165e5dd7070Spatrick   switch (DspRev) {
166e5dd7070Spatrick   default:
167e5dd7070Spatrick     break;
168e5dd7070Spatrick   case DSP1:
169e5dd7070Spatrick     Builder.defineMacro("__mips_dsp_rev", Twine(1));
170e5dd7070Spatrick     Builder.defineMacro("__mips_dsp", Twine(1));
171e5dd7070Spatrick     break;
172e5dd7070Spatrick   case DSP2:
173e5dd7070Spatrick     Builder.defineMacro("__mips_dsp_rev", Twine(2));
174e5dd7070Spatrick     Builder.defineMacro("__mips_dspr2", Twine(1));
175e5dd7070Spatrick     Builder.defineMacro("__mips_dsp", Twine(1));
176e5dd7070Spatrick     break;
177e5dd7070Spatrick   }
178e5dd7070Spatrick 
179e5dd7070Spatrick   if (HasMSA)
180e5dd7070Spatrick     Builder.defineMacro("__mips_msa", Twine(1));
181e5dd7070Spatrick 
182e5dd7070Spatrick   if (DisableMadd4)
183e5dd7070Spatrick     Builder.defineMacro("__mips_no_madd4", Twine(1));
184e5dd7070Spatrick 
185*12c85518Srobert   Builder.defineMacro("_MIPS_SZPTR", Twine(getPointerWidth(LangAS::Default)));
186e5dd7070Spatrick   Builder.defineMacro("_MIPS_SZINT", Twine(getIntWidth()));
187e5dd7070Spatrick   Builder.defineMacro("_MIPS_SZLONG", Twine(getLongWidth()));
188e5dd7070Spatrick 
189e5dd7070Spatrick   Builder.defineMacro("_MIPS_ARCH", "\"" + CPU + "\"");
190e5dd7070Spatrick   if (CPU == "octeon+")
191e5dd7070Spatrick     Builder.defineMacro("_MIPS_ARCH_OCTEONP");
192e5dd7070Spatrick   else
193e5dd7070Spatrick     Builder.defineMacro("_MIPS_ARCH_" + StringRef(CPU).upper());
194e5dd7070Spatrick 
195e5dd7070Spatrick   if (StringRef(CPU).startswith("octeon"))
196e5dd7070Spatrick     Builder.defineMacro("__OCTEON__");
197e5dd7070Spatrick 
198*12c85518Srobert   if (CPU != "mips1") {
199e5dd7070Spatrick     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
200e5dd7070Spatrick     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
201e5dd7070Spatrick     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
202*12c85518Srobert   }
203e5dd7070Spatrick 
204e5dd7070Spatrick   // 32-bit MIPS processors don't have the necessary lld/scd instructions
205e5dd7070Spatrick   // found in 64-bit processors. In the case of O32 on a 64-bit processor,
206e5dd7070Spatrick   // the instructions exist but using them violates the ABI since they
207e5dd7070Spatrick   // require 64-bit GPRs and O32 only supports 32-bit GPRs.
208e5dd7070Spatrick   if (ABI == "n32" || ABI == "n64")
209e5dd7070Spatrick     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
210e5dd7070Spatrick }
211e5dd7070Spatrick 
hasFeature(StringRef Feature) const212e5dd7070Spatrick bool MipsTargetInfo::hasFeature(StringRef Feature) const {
213e5dd7070Spatrick   return llvm::StringSwitch<bool>(Feature)
214e5dd7070Spatrick       .Case("mips", true)
215e5dd7070Spatrick       .Case("dsp", DspRev >= DSP1)
216e5dd7070Spatrick       .Case("dspr2", DspRev >= DSP2)
217e5dd7070Spatrick       .Case("fp64", FPMode == FP64)
218e5dd7070Spatrick       .Case("msa", HasMSA)
219e5dd7070Spatrick       .Default(false);
220e5dd7070Spatrick }
221e5dd7070Spatrick 
getTargetBuiltins() const222e5dd7070Spatrick ArrayRef<Builtin::Info> MipsTargetInfo::getTargetBuiltins() const {
223*12c85518Srobert   return llvm::ArrayRef(BuiltinInfo,
224*12c85518Srobert                         clang::Mips::LastTSBuiltin - Builtin::FirstTSBuiltin);
225e5dd7070Spatrick }
226e5dd7070Spatrick 
getUnwindWordWidth() const227e5dd7070Spatrick unsigned MipsTargetInfo::getUnwindWordWidth() const {
228e5dd7070Spatrick   return llvm::StringSwitch<unsigned>(ABI)
229e5dd7070Spatrick       .Case("o32", 32)
230e5dd7070Spatrick       .Case("n32", 64)
231e5dd7070Spatrick       .Case("n64", 64)
232*12c85518Srobert       .Default(getPointerWidth(LangAS::Default));
233e5dd7070Spatrick }
234e5dd7070Spatrick 
validateTarget(DiagnosticsEngine & Diags) const235e5dd7070Spatrick bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
236e5dd7070Spatrick   // microMIPS64R6 backend was removed.
237e5dd7070Spatrick   if (getTriple().isMIPS64() && IsMicromips && (ABI == "n32" || ABI == "n64")) {
238e5dd7070Spatrick     Diags.Report(diag::err_target_unsupported_cpu_for_micromips) << CPU;
239e5dd7070Spatrick     return false;
240e5dd7070Spatrick   }
241e5dd7070Spatrick   // FIXME: It's valid to use O32 on a 64-bit CPU but the backend can't handle
242e5dd7070Spatrick   //        this yet. It's better to fail here than on the backend assertion.
243e5dd7070Spatrick   if (processorSupportsGPR64() && ABI == "o32") {
244e5dd7070Spatrick     Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
245e5dd7070Spatrick     return false;
246e5dd7070Spatrick   }
247e5dd7070Spatrick 
248e5dd7070Spatrick   // 64-bit ABI's require 64-bit CPU's.
249e5dd7070Spatrick   if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) {
250e5dd7070Spatrick     Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
251e5dd7070Spatrick     return false;
252e5dd7070Spatrick   }
253e5dd7070Spatrick 
254e5dd7070Spatrick   // FIXME: It's valid to use O32 on a mips64/mips64el triple but the backend
255e5dd7070Spatrick   //        can't handle this yet. It's better to fail here than on the
256e5dd7070Spatrick   //        backend assertion.
257e5dd7070Spatrick   if (getTriple().isMIPS64() && ABI == "o32") {
258e5dd7070Spatrick     Diags.Report(diag::err_target_unsupported_abi_for_triple)
259e5dd7070Spatrick         << ABI << getTriple().str();
260e5dd7070Spatrick     return false;
261e5dd7070Spatrick   }
262e5dd7070Spatrick 
263e5dd7070Spatrick   // FIXME: It's valid to use N32/N64 on a mips/mipsel triple but the backend
264e5dd7070Spatrick   //        can't handle this yet. It's better to fail here than on the
265e5dd7070Spatrick   //        backend assertion.
266e5dd7070Spatrick   if (getTriple().isMIPS32() && (ABI == "n32" || ABI == "n64")) {
267e5dd7070Spatrick     Diags.Report(diag::err_target_unsupported_abi_for_triple)
268e5dd7070Spatrick         << ABI << getTriple().str();
269e5dd7070Spatrick     return false;
270e5dd7070Spatrick   }
271e5dd7070Spatrick 
272e5dd7070Spatrick   // -fpxx is valid only for the o32 ABI
273e5dd7070Spatrick   if (FPMode == FPXX && (ABI == "n32" || ABI == "n64")) {
274e5dd7070Spatrick     Diags.Report(diag::err_unsupported_abi_for_opt) << "-mfpxx" << "o32";
275e5dd7070Spatrick     return false;
276e5dd7070Spatrick   }
277e5dd7070Spatrick 
278e5dd7070Spatrick   // -mfp32 and n32/n64 ABIs are incompatible
279e5dd7070Spatrick   if (FPMode != FP64 && FPMode != FPXX && !IsSingleFloat &&
280e5dd7070Spatrick       (ABI == "n32" || ABI == "n64")) {
281e5dd7070Spatrick     Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx" << CPU;
282e5dd7070Spatrick     return false;
283e5dd7070Spatrick   }
284e5dd7070Spatrick   // Mips revision 6 and -mfp32 are incompatible
285e5dd7070Spatrick   if (FPMode != FP64 && FPMode != FPXX && (CPU == "mips32r6" ||
286e5dd7070Spatrick       CPU == "mips64r6")) {
287e5dd7070Spatrick     Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfp32" << CPU;
288e5dd7070Spatrick     return false;
289e5dd7070Spatrick   }
290e5dd7070Spatrick   // Option -mfp64 permitted on Mips32 iff revision 2 or higher is present
291e5dd7070Spatrick   if (FPMode == FP64 && (CPU == "mips1" || CPU == "mips2" ||
292e5dd7070Spatrick       getISARev() < 2) && ABI == "o32") {
293e5dd7070Spatrick     Diags.Report(diag::err_mips_fp64_req) << "-mfp64";
294e5dd7070Spatrick     return false;
295e5dd7070Spatrick   }
296e5dd7070Spatrick 
297e5dd7070Spatrick   return true;
298e5dd7070Spatrick }
299