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