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