brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.4 KiB · ce6ad6d Raw
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