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