302 lines · cpp
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-exception6//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 21namespace clang {22 23SemaMIPS::SemaMIPS(Sema &S) : SemaBase(S) {}24 25bool SemaMIPS::CheckMipsBuiltinFunctionCall(const TargetInfo &TI,26 unsigned BuiltinID,27 CallExpr *TheCall) {28 return CheckMipsBuiltinCpu(TI, BuiltinID, TheCall) ||29 CheckMipsBuiltinArgument(BuiltinID, TheCall);30}31 32bool 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("dsp"))38 return Diag(TheCall->getBeginLoc(), 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("dspr2"))44 return Diag(TheCall->getBeginLoc(),45 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("msa"))51 return Diag(TheCall->getBeginLoc(), diag::err_mips_builtin_requires_msa);52 }53 54 return false;55}56 57// CheckMipsBuiltinArgument - Checks the constant value passed to the58// intrinsic is correct. The switch statement is ordered by DSP, MSA. The59// ordering for DSP is unspecified. MSA is ordered by the data format used60// 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 the63// definitions from include/clang/Basic/BuiltinsMips.def.64// FIXME: GCC is strict on signedness for some of these intrinsics, we should65// be too.66bool 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 the78 // 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 format192 // 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, i, l, u);238 239 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u) ||240 SemaRef.BuiltinConstantArgMultiple(TheCall, i, m);241}242 243void SemaMIPS::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {244 // Only one optional argument permitted.245 if (AL.getNumArgs() > 1) {246 Diag(AL.getLoc(), 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(AL, 0, Str, &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 set263 // lacks the 'eret' instruction.264 // e) The attribute itself must either have no argument or one of the265 // valid interrupt types, see [MipsInterruptDocs].266 267 if (!isFuncOrMethodForAttrSubject(D)) {268 Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)269 << AL << AL.isRegularKeywordAttribute() << ExpectedFunctionOrMethod;270 return;271 }272 273 if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {274 Diag(D->getLocation(), diag::warn_interrupt_signal_attribute_invalid)275 << /*MIPS*/ 0 << /*interrupt*/ 0 << 0;276 return;277 }278 279 if (!getFunctionOrMethodResultType(D)->isVoidType()) {280 Diag(D->getLocation(), 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 are286 // a bit special due to sharing their spellings across targets.287 if (checkAttrMutualExclusion<Mips16Attr>(*this, D, AL))288 return;289 290 MipsInterruptAttr::InterruptType Kind;291 if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {292 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)293 << AL << "'" + std::string(Str) + "'";294 return;295 }296 297 D->addAttr(::new (getASTContext())298 MipsInterruptAttr(getASTContext(), AL, Kind));299}300 301} // namespace clang302