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