clang 20.0.0git
SemaMIPS.cpp
Go to the documentation of this file.
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"
16#include "clang/Sema/Attr.h"
18#include "clang/Sema/Sema.h"
19
20namespace clang {
21
23
25 unsigned BuiltinID,
26 CallExpr *TheCall) {
27 return CheckMipsBuiltinCpu(TI, BuiltinID, TheCall) ||
28 CheckMipsBuiltinArgument(BuiltinID, TheCall);
29}
30
31bool 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("dsp"))
37 return Diag(TheCall->getBeginLoc(), 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("dspr2"))
43 return Diag(TheCall->getBeginLoc(),
44 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("msa"))
50 return Diag(TheCall->getBeginLoc(), 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.
65bool 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, i, l, u);
237
238 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u) ||
239 SemaRef.BuiltinConstantArgMultiple(TheCall, i, m);
240}
241
243 // Only one optional argument permitted.
244 if (AL.getNumArgs() > 1) {
245 Diag(AL.getLoc(), 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(AL, 0, Str, &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
267 Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
269 return;
270 }
271
273 Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
274 << /*MIPS*/ 0 << 0;
275 return;
276 }
277
278 if (!getFunctionOrMethodResultType(D)->isVoidType()) {
279 Diag(D->getLocation(), 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>(*this, D, AL))
287 return;
288
289 MipsInterruptAttr::InterruptType Kind;
290 if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
291 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
292 << AL << "'" + std::string(Str) + "'";
293 return;
294 }
295
296 D->addAttr(::new (getASTContext())
297 MipsInterruptAttr(getASTContext(), AL, Kind));
298}
299
300} // namespace clang
const Decl * D
enum clang::sema::@1658::IndirectLocalPathEntry::EntryKind Kind
This file declares semantic analysis functions specific to MIPS.
Enumerates target-specific builtins in their own namespaces within namespace clang.
SourceLocation getLoc() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2830
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1638
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:386
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaMIPS.cpp:31
bool CheckMipsBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaMIPS.cpp:24
bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaMIPS.cpp:65
void handleInterruptAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaMIPS.cpp:242
SemaMIPS(Sema &S)
Definition: SemaMIPS.cpp:22
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:535
bool BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, unsigned Multiple)
BuiltinConstantArgMultiple - Handle a check if argument ArgNum of CallExpr TheCall is a constant expr...
bool BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, bool RangeIsError=true)
BuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr TheCall is a constant express...
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
Encodes a location in the source.
Exposes information about the current target.
Definition: TargetInfo.h:218
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
Definition: TargetInfo.h:1487
The JSON file list parser is used to communicate input to InstallAPI.
@ ExpectedFunctionOrMethod
Definition: ParsedAttr.h:1094
QualType getFunctionOrMethodResultType(const Decl *D)
Definition: Attr.h:98
bool isFuncOrMethodForAttrSubject(const Decl *D)
isFuncOrMethodForAttrSubject - Return true if the given decl has function type (function or function-...
Definition: Attr.h:34
bool hasFunctionProto(const Decl *D)
hasFunctionProto - Return true if the given decl has a argument information.
Definition: Attr.h:55
unsigned getFunctionOrMethodNumParams(const Decl *D)
getFunctionOrMethodNumParams - Return number of function or method parameters.
Definition: Attr.h:64