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