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