xref: /llvm-project/clang/lib/Sema/SemaMIPS.cpp (revision 27d37ee4d067f42e9a46a0871d3cb961323e5c85)
1 //===------ SemaMIPS.cpp -------- MIPS target-specific routines -----------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file implements semantic analysis functions specific to MIPS.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Sema/SemaMIPS.h"
14 #include "clang/Basic/DiagnosticSema.h"
15 #include "clang/Basic/TargetBuiltins.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "clang/Sema/Attr.h"
18 #include "clang/Sema/ParsedAttr.h"
19 #include "clang/Sema/Sema.h"
20 
21 namespace clang {
22 
23 SemaMIPS::SemaMIPS(Sema &S) : SemaBase(S) {}
24 
25 bool SemaMIPS::CheckMipsBuiltinFunctionCall(const TargetInfo &TI,
26                                             unsigned BuiltinID,
27                                             CallExpr *TheCall) {
28   return CheckMipsBuiltinCpu(TI, BuiltinID, TheCall) ||
29          CheckMipsBuiltinArgument(BuiltinID, TheCall);
30 }
31 
32 bool SemaMIPS::CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
33                                    CallExpr *TheCall) {
34 
35   if (Mips::BI__builtin_mips_addu_qb <= BuiltinID &&
36       BuiltinID <= Mips::BI__builtin_mips_lwx) {
37     if (!TI.hasFeature("dsp"))
38       return Diag(TheCall->getBeginLoc(), diag::err_mips_builtin_requires_dsp);
39   }
40 
41   if (Mips::BI__builtin_mips_absq_s_qb <= BuiltinID &&
42       BuiltinID <= Mips::BI__builtin_mips_subuh_r_qb) {
43     if (!TI.hasFeature("dspr2"))
44       return Diag(TheCall->getBeginLoc(),
45                   diag::err_mips_builtin_requires_dspr2);
46   }
47 
48   if (Mips::BI__builtin_msa_add_a_b <= BuiltinID &&
49       BuiltinID <= Mips::BI__builtin_msa_xori_b) {
50     if (!TI.hasFeature("msa"))
51       return Diag(TheCall->getBeginLoc(), diag::err_mips_builtin_requires_msa);
52   }
53 
54   return false;
55 }
56 
57 // CheckMipsBuiltinArgument - Checks the constant value passed to the
58 // intrinsic is correct. The switch statement is ordered by DSP, MSA. The
59 // ordering for DSP is unspecified. MSA is ordered by the data format used
60 // by the underlying instruction i.e., df/m, df/n and then by size.
61 //
62 // FIXME: The size tests here should instead be tablegen'd along with the
63 //        definitions from include/clang/Basic/BuiltinsMips.def.
64 // FIXME: GCC is strict on signedness for some of these intrinsics, we should
65 //        be too.
66 bool SemaMIPS::CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) {
67   unsigned i = 0, l = 0, u = 0, m = 0;
68   switch (BuiltinID) {
69   default: return false;
70   case Mips::BI__builtin_mips_wrdsp: i = 1; l = 0; u = 63; break;
71   case Mips::BI__builtin_mips_rddsp: i = 0; l = 0; u = 63; break;
72   case Mips::BI__builtin_mips_append: i = 2; l = 0; u = 31; break;
73   case Mips::BI__builtin_mips_balign: i = 2; l = 0; u = 3; break;
74   case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break;
75   case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break;
76   case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break;
77   // MSA intrinsics. Instructions (which the intrinsics maps to) which use the
78   // df/m field.
79   // These intrinsics take an unsigned 3 bit immediate.
80   case Mips::BI__builtin_msa_bclri_b:
81   case Mips::BI__builtin_msa_bnegi_b:
82   case Mips::BI__builtin_msa_bseti_b:
83   case Mips::BI__builtin_msa_sat_s_b:
84   case Mips::BI__builtin_msa_sat_u_b:
85   case Mips::BI__builtin_msa_slli_b:
86   case Mips::BI__builtin_msa_srai_b:
87   case Mips::BI__builtin_msa_srari_b:
88   case Mips::BI__builtin_msa_srli_b:
89   case Mips::BI__builtin_msa_srlri_b: i = 1; l = 0; u = 7; break;
90   case Mips::BI__builtin_msa_binsli_b:
91   case Mips::BI__builtin_msa_binsri_b: i = 2; l = 0; u = 7; break;
92   // These intrinsics take an unsigned 4 bit immediate.
93   case Mips::BI__builtin_msa_bclri_h:
94   case Mips::BI__builtin_msa_bnegi_h:
95   case Mips::BI__builtin_msa_bseti_h:
96   case Mips::BI__builtin_msa_sat_s_h:
97   case Mips::BI__builtin_msa_sat_u_h:
98   case Mips::BI__builtin_msa_slli_h:
99   case Mips::BI__builtin_msa_srai_h:
100   case Mips::BI__builtin_msa_srari_h:
101   case Mips::BI__builtin_msa_srli_h:
102   case Mips::BI__builtin_msa_srlri_h: i = 1; l = 0; u = 15; break;
103   case Mips::BI__builtin_msa_binsli_h:
104   case Mips::BI__builtin_msa_binsri_h: i = 2; l = 0; u = 15; break;
105   // These intrinsics take an unsigned 5 bit immediate.
106   // The first block of intrinsics actually have an unsigned 5 bit field,
107   // not a df/n field.
108   case Mips::BI__builtin_msa_cfcmsa:
109   case Mips::BI__builtin_msa_ctcmsa: i = 0; l = 0; u = 31; break;
110   case Mips::BI__builtin_msa_clei_u_b:
111   case Mips::BI__builtin_msa_clei_u_h:
112   case Mips::BI__builtin_msa_clei_u_w:
113   case Mips::BI__builtin_msa_clei_u_d:
114   case Mips::BI__builtin_msa_clti_u_b:
115   case Mips::BI__builtin_msa_clti_u_h:
116   case Mips::BI__builtin_msa_clti_u_w:
117   case Mips::BI__builtin_msa_clti_u_d:
118   case Mips::BI__builtin_msa_maxi_u_b:
119   case Mips::BI__builtin_msa_maxi_u_h:
120   case Mips::BI__builtin_msa_maxi_u_w:
121   case Mips::BI__builtin_msa_maxi_u_d:
122   case Mips::BI__builtin_msa_mini_u_b:
123   case Mips::BI__builtin_msa_mini_u_h:
124   case Mips::BI__builtin_msa_mini_u_w:
125   case Mips::BI__builtin_msa_mini_u_d:
126   case Mips::BI__builtin_msa_addvi_b:
127   case Mips::BI__builtin_msa_addvi_h:
128   case Mips::BI__builtin_msa_addvi_w:
129   case Mips::BI__builtin_msa_addvi_d:
130   case Mips::BI__builtin_msa_bclri_w:
131   case Mips::BI__builtin_msa_bnegi_w:
132   case Mips::BI__builtin_msa_bseti_w:
133   case Mips::BI__builtin_msa_sat_s_w:
134   case Mips::BI__builtin_msa_sat_u_w:
135   case Mips::BI__builtin_msa_slli_w:
136   case Mips::BI__builtin_msa_srai_w:
137   case Mips::BI__builtin_msa_srari_w:
138   case Mips::BI__builtin_msa_srli_w:
139   case Mips::BI__builtin_msa_srlri_w:
140   case Mips::BI__builtin_msa_subvi_b:
141   case Mips::BI__builtin_msa_subvi_h:
142   case Mips::BI__builtin_msa_subvi_w:
143   case Mips::BI__builtin_msa_subvi_d: i = 1; l = 0; u = 31; break;
144   case Mips::BI__builtin_msa_binsli_w:
145   case Mips::BI__builtin_msa_binsri_w: i = 2; l = 0; u = 31; break;
146   // These intrinsics take an unsigned 6 bit immediate.
147   case Mips::BI__builtin_msa_bclri_d:
148   case Mips::BI__builtin_msa_bnegi_d:
149   case Mips::BI__builtin_msa_bseti_d:
150   case Mips::BI__builtin_msa_sat_s_d:
151   case Mips::BI__builtin_msa_sat_u_d:
152   case Mips::BI__builtin_msa_slli_d:
153   case Mips::BI__builtin_msa_srai_d:
154   case Mips::BI__builtin_msa_srari_d:
155   case Mips::BI__builtin_msa_srli_d:
156   case Mips::BI__builtin_msa_srlri_d: i = 1; l = 0; u = 63; break;
157   case Mips::BI__builtin_msa_binsli_d:
158   case Mips::BI__builtin_msa_binsri_d: i = 2; l = 0; u = 63; break;
159   // These intrinsics take a signed 5 bit immediate.
160   case Mips::BI__builtin_msa_ceqi_b:
161   case Mips::BI__builtin_msa_ceqi_h:
162   case Mips::BI__builtin_msa_ceqi_w:
163   case Mips::BI__builtin_msa_ceqi_d:
164   case Mips::BI__builtin_msa_clti_s_b:
165   case Mips::BI__builtin_msa_clti_s_h:
166   case Mips::BI__builtin_msa_clti_s_w:
167   case Mips::BI__builtin_msa_clti_s_d:
168   case Mips::BI__builtin_msa_clei_s_b:
169   case Mips::BI__builtin_msa_clei_s_h:
170   case Mips::BI__builtin_msa_clei_s_w:
171   case Mips::BI__builtin_msa_clei_s_d:
172   case Mips::BI__builtin_msa_maxi_s_b:
173   case Mips::BI__builtin_msa_maxi_s_h:
174   case Mips::BI__builtin_msa_maxi_s_w:
175   case Mips::BI__builtin_msa_maxi_s_d:
176   case Mips::BI__builtin_msa_mini_s_b:
177   case Mips::BI__builtin_msa_mini_s_h:
178   case Mips::BI__builtin_msa_mini_s_w:
179   case Mips::BI__builtin_msa_mini_s_d: i = 1; l = -16; u = 15; break;
180   // These intrinsics take an unsigned 8 bit immediate.
181   case Mips::BI__builtin_msa_andi_b:
182   case Mips::BI__builtin_msa_nori_b:
183   case Mips::BI__builtin_msa_ori_b:
184   case Mips::BI__builtin_msa_shf_b:
185   case Mips::BI__builtin_msa_shf_h:
186   case Mips::BI__builtin_msa_shf_w:
187   case Mips::BI__builtin_msa_xori_b: i = 1; l = 0; u = 255; break;
188   case Mips::BI__builtin_msa_bseli_b:
189   case Mips::BI__builtin_msa_bmnzi_b:
190   case Mips::BI__builtin_msa_bmzi_b: i = 2; l = 0; u = 255; break;
191   // df/n format
192   // These intrinsics take an unsigned 4 bit immediate.
193   case Mips::BI__builtin_msa_copy_s_b:
194   case Mips::BI__builtin_msa_copy_u_b:
195   case Mips::BI__builtin_msa_insve_b:
196   case Mips::BI__builtin_msa_splati_b: i = 1; l = 0; u = 15; break;
197   case Mips::BI__builtin_msa_sldi_b: i = 2; l = 0; u = 15; break;
198   // These intrinsics take an unsigned 3 bit immediate.
199   case Mips::BI__builtin_msa_copy_s_h:
200   case Mips::BI__builtin_msa_copy_u_h:
201   case Mips::BI__builtin_msa_insve_h:
202   case Mips::BI__builtin_msa_splati_h: i = 1; l = 0; u = 7; break;
203   case Mips::BI__builtin_msa_sldi_h: i = 2; l = 0; u = 7; break;
204   // These intrinsics take an unsigned 2 bit immediate.
205   case Mips::BI__builtin_msa_copy_s_w:
206   case Mips::BI__builtin_msa_copy_u_w:
207   case Mips::BI__builtin_msa_insve_w:
208   case Mips::BI__builtin_msa_splati_w: i = 1; l = 0; u = 3; break;
209   case Mips::BI__builtin_msa_sldi_w: i = 2; l = 0; u = 3; break;
210   // These intrinsics take an unsigned 1 bit immediate.
211   case Mips::BI__builtin_msa_copy_s_d:
212   case Mips::BI__builtin_msa_copy_u_d:
213   case Mips::BI__builtin_msa_insve_d:
214   case Mips::BI__builtin_msa_splati_d: i = 1; l = 0; u = 1; break;
215   case Mips::BI__builtin_msa_sldi_d: i = 2; l = 0; u = 1; break;
216   // Memory offsets and immediate loads.
217   // These intrinsics take a signed 10 bit immediate.
218   case Mips::BI__builtin_msa_ldi_b: i = 0; l = -128; u = 255; break;
219   case Mips::BI__builtin_msa_ldi_h:
220   case Mips::BI__builtin_msa_ldi_w:
221   case Mips::BI__builtin_msa_ldi_d: i = 0; l = -512; u = 511; break;
222   case Mips::BI__builtin_msa_ld_b: i = 1; l = -512; u = 511; m = 1; break;
223   case Mips::BI__builtin_msa_ld_h: i = 1; l = -1024; u = 1022; m = 2; break;
224   case Mips::BI__builtin_msa_ld_w: i = 1; l = -2048; u = 2044; m = 4; break;
225   case Mips::BI__builtin_msa_ld_d: i = 1; l = -4096; u = 4088; m = 8; break;
226   case Mips::BI__builtin_msa_ldr_d: i = 1; l = -4096; u = 4088; m = 8; break;
227   case Mips::BI__builtin_msa_ldr_w: i = 1; l = -2048; u = 2044; m = 4; break;
228   case Mips::BI__builtin_msa_st_b: i = 2; l = -512; u = 511; m = 1; break;
229   case Mips::BI__builtin_msa_st_h: i = 2; l = -1024; u = 1022; m = 2; break;
230   case Mips::BI__builtin_msa_st_w: i = 2; l = -2048; u = 2044; m = 4; break;
231   case Mips::BI__builtin_msa_st_d: i = 2; l = -4096; u = 4088; m = 8; break;
232   case Mips::BI__builtin_msa_str_d: i = 2; l = -4096; u = 4088; m = 8; break;
233   case Mips::BI__builtin_msa_str_w: i = 2; l = -2048; u = 2044; m = 4; break;
234   }
235 
236   if (!m)
237     return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u);
238 
239   return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u) ||
240          SemaRef.BuiltinConstantArgMultiple(TheCall, i, m);
241 }
242 
243 void SemaMIPS::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
244   // Only one optional argument permitted.
245   if (AL.getNumArgs() > 1) {
246     Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
247     return;
248   }
249 
250   StringRef Str;
251   SourceLocation ArgLoc;
252 
253   if (AL.getNumArgs() == 0)
254     Str = "";
255   else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
256     return;
257 
258   // Semantic checks for a function with the 'interrupt' attribute for MIPS:
259   // a) Must be a function.
260   // b) Must have no parameters.
261   // c) Must have the 'void' return type.
262   // d) Cannot have the 'mips16' attribute, as that instruction set
263   //    lacks the 'eret' instruction.
264   // e) The attribute itself must either have no argument or one of the
265   //    valid interrupt types, see [MipsInterruptDocs].
266 
267   if (!isFuncOrMethodForAttrSubject(D)) {
268     Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
269         << AL << AL.isRegularKeywordAttribute() << ExpectedFunctionOrMethod;
270     return;
271   }
272 
273   if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
274     Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
275         << /*MIPS*/ 0 << 0;
276     return;
277   }
278 
279   if (!getFunctionOrMethodResultType(D)->isVoidType()) {
280     Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
281         << /*MIPS*/ 0 << 1;
282     return;
283   }
284 
285   // We still have to do this manually because the Interrupt attributes are
286   // a bit special due to sharing their spellings across targets.
287   if (checkAttrMutualExclusion<Mips16Attr>(*this, D, AL))
288     return;
289 
290   MipsInterruptAttr::InterruptType Kind;
291   if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
292     Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
293         << AL << "'" + std::string(Str) + "'";
294     return;
295   }
296 
297   D->addAttr(::new (getASTContext())
298                  MipsInterruptAttr(getASTContext(), AL, Kind));
299 }
300 
301 } // namespace clang
302