brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.2 KiB · bfa458d Raw
446 lines · cpp
1//===------ SemaPPC.cpp ------ PowerPC 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 PowerPC.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Sema/SemaPPC.h"14#include "clang/AST/ASTContext.h"15#include "clang/AST/Attr.h"16#include "clang/AST/CharUnits.h"17#include "clang/AST/Decl.h"18#include "clang/AST/Type.h"19#include "clang/Basic/DiagnosticSema.h"20#include "clang/Basic/SourceLocation.h"21#include "clang/Basic/TargetBuiltins.h"22#include "clang/Basic/TargetInfo.h"23#include "clang/Sema/Sema.h"24#include "llvm/ADT/APSInt.h"25 26namespace clang {27 28SemaPPC::SemaPPC(Sema &S) : SemaBase(S) {}29 30void SemaPPC::checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg) {31  const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg->IgnoreParens());32  if (!ICE)33    return;34 35  const auto *DR = dyn_cast<DeclRefExpr>(ICE->getSubExpr());36  if (!DR)37    return;38 39  const auto *PD = dyn_cast<ParmVarDecl>(DR->getDecl());40  if (!PD || !PD->getType()->isRecordType())41    return;42 43  QualType ArgType = Arg->getType();44  for (const FieldDecl *FD : ArgType->castAsRecordDecl()->fields()) {45    if (const auto *AA = FD->getAttr<AlignedAttr>()) {46      CharUnits Alignment = getASTContext().toCharUnitsFromBits(47          AA->getAlignment(getASTContext()));48      if (Alignment.getQuantity() == 16) {49        Diag(FD->getLocation(), diag::warn_not_xl_compatible) << FD;50        Diag(Loc, diag::note_misaligned_member_used_here) << PD;51      }52    }53  }54}55 56static bool isPPC_64Builtin(unsigned BuiltinID) {57  // These builtins only work on PPC 64bit targets.58  switch (BuiltinID) {59  case PPC::BI__builtin_divde:60  case PPC::BI__builtin_divdeu:61  case PPC::BI__builtin_bpermd:62  case PPC::BI__builtin_pdepd:63  case PPC::BI__builtin_pextd:64  case PPC::BI__builtin_ppc_cdtbcd:65  case PPC::BI__builtin_ppc_cbcdtd:66  case PPC::BI__builtin_ppc_addg6s:67  case PPC::BI__builtin_ppc_ldarx:68  case PPC::BI__builtin_ppc_stdcx:69  case PPC::BI__builtin_ppc_tdw:70  case PPC::BI__builtin_ppc_trapd:71  case PPC::BI__builtin_ppc_cmpeqb:72  case PPC::BI__builtin_ppc_setb:73  case PPC::BI__builtin_ppc_mulhd:74  case PPC::BI__builtin_ppc_mulhdu:75  case PPC::BI__builtin_ppc_maddhd:76  case PPC::BI__builtin_ppc_maddhdu:77  case PPC::BI__builtin_ppc_maddld:78  case PPC::BI__builtin_ppc_load8r:79  case PPC::BI__builtin_ppc_store8r:80  case PPC::BI__builtin_ppc_insert_exp:81  case PPC::BI__builtin_ppc_extract_sig:82  case PPC::BI__builtin_ppc_addex:83  case PPC::BI__builtin_darn:84  case PPC::BI__builtin_darn_raw:85  case PPC::BI__builtin_ppc_compare_and_swaplp:86  case PPC::BI__builtin_ppc_fetch_and_addlp:87  case PPC::BI__builtin_ppc_fetch_and_andlp:88  case PPC::BI__builtin_ppc_fetch_and_orlp:89  case PPC::BI__builtin_ppc_fetch_and_swaplp:90    return true;91  }92  return false;93}94 95bool SemaPPC::CheckPPCBuiltinFunctionCall(const TargetInfo &TI,96                                          unsigned BuiltinID,97                                          CallExpr *TheCall) {98  ASTContext &Context = getASTContext();99  bool IsTarget64Bit = TI.getTypeWidth(TI.getIntPtrType()) == 64;100 101  if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)102    return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)103           << TheCall->getSourceRange();104 105  switch (BuiltinID) {106  default:107    return false;108  case PPC::BI__builtin_ppc_bcdsetsign:109  case PPC::BI__builtin_ppc_national2packed:110  case PPC::BI__builtin_ppc_packed2zoned:111  case PPC::BI__builtin_ppc_zoned2packed:112    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);113  case PPC::BI__builtin_altivec_crypto_vshasigmaw:114  case PPC::BI__builtin_altivec_crypto_vshasigmad:115    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||116           SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 15);117  case PPC::BI__builtin_altivec_dss:118    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3);119  case PPC::BI__builtin_tbegin:120  case PPC::BI__builtin_tend:121    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1);122  case PPC::BI__builtin_tsr:123    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 7);124  case PPC::BI__builtin_tabortwc:125  case PPC::BI__builtin_tabortdc:126    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);127  case PPC::BI__builtin_tabortwci:128  case PPC::BI__builtin_tabortdci:129    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31) ||130           SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31);131  // According to GCC 'Basic PowerPC Built-in Functions Available on ISA 2.05',132  // __builtin_(un)pack_longdouble are available only if long double uses IBM133  // extended double representation.134  case PPC::BI__builtin_unpack_longdouble:135    if (SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1))136      return true;137    [[fallthrough]];138  case PPC::BI__builtin_pack_longdouble:139    if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())140      return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_requires_abi)141             << "ibmlongdouble";142    return false;143  case PPC::BI__builtin_altivec_dst:144  case PPC::BI__builtin_altivec_dstt:145  case PPC::BI__builtin_altivec_dstst:146  case PPC::BI__builtin_altivec_dststt:147    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);148  case PPC::BI__builtin_vsx_xxpermdi:149  case PPC::BI__builtin_vsx_xxsldwi:150    return BuiltinVSX(TheCall);151  case PPC::BI__builtin_unpack_vector_int128:152    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);153  case PPC::BI__builtin_altivec_vgnb:154    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 2, 7);155  case PPC::BI__builtin_vsx_xxeval:156    return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 255);157  case PPC::BI__builtin_altivec_vsldbi:158    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);159  case PPC::BI__builtin_altivec_vsrdbi:160    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);161  case PPC::BI__builtin_vsx_xxpermx:162    return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 7);163  case PPC::BI__builtin_ppc_tw:164  case PPC::BI__builtin_ppc_tdw:165    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 1, 31);166  case PPC::BI__builtin_ppc_cmprb:167    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1);168  // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must169  // be a constant that represents a contiguous bit field.170  case PPC::BI__builtin_ppc_rlwnm:171    return SemaRef.ValueIsRunOfOnes(TheCall, 2);172  case PPC::BI__builtin_ppc_rlwimi:173    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31) ||174           SemaRef.ValueIsRunOfOnes(TheCall, 3);175  case PPC::BI__builtin_ppc_rldimi:176    return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 63) ||177           SemaRef.ValueIsRunOfOnes(TheCall, 3);178  case PPC::BI__builtin_ppc_addex: {179    if (SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3))180      return true;181    // Output warning for reserved values 1 to 3.182    int ArgValue =183        TheCall->getArg(2)->getIntegerConstantExpr(Context)->getSExtValue();184    if (ArgValue != 0)185      Diag(TheCall->getBeginLoc(), diag::warn_argument_undefined_behaviour)186          << ArgValue;187    return false;188  }189  case PPC::BI__builtin_ppc_mtfsb0:190  case PPC::BI__builtin_ppc_mtfsb1:191    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);192  case PPC::BI__builtin_ppc_mtfsf:193    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 255);194  case PPC::BI__builtin_ppc_mtfsfi:195    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 7) ||196           SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);197  case PPC::BI__builtin_ppc_alignx:198    return SemaRef.BuiltinConstantArgPower2(TheCall, 0);199  case PPC::BI__builtin_ppc_rdlam:200    return SemaRef.ValueIsRunOfOnes(TheCall, 2);201  case PPC::BI__builtin_vsx_ldrmb:202  case PPC::BI__builtin_vsx_strmb:203    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);204  case PPC::BI__builtin_altivec_vcntmbb:205  case PPC::BI__builtin_altivec_vcntmbh:206  case PPC::BI__builtin_altivec_vcntmbw:207  case PPC::BI__builtin_altivec_vcntmbd:208    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);209  case PPC::BI__builtin_vsx_xxgenpcvbm:210  case PPC::BI__builtin_vsx_xxgenpcvhm:211  case PPC::BI__builtin_vsx_xxgenpcvwm:212  case PPC::BI__builtin_vsx_xxgenpcvdm:213    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);214  case PPC::BI__builtin_ppc_test_data_class: {215    // Check if the first argument of the __builtin_ppc_test_data_class call is216    // valid. The argument must be 'float' or 'double' or '__float128'.217    QualType ArgType = TheCall->getArg(0)->getType();218    if (ArgType != QualType(Context.FloatTy) &&219        ArgType != QualType(Context.DoubleTy) &&220        ArgType != QualType(Context.Float128Ty))221      return Diag(TheCall->getBeginLoc(),222                  diag::err_ppc_invalid_test_data_class_type);223    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 127);224  }225  case PPC::BI__builtin_ppc_maxfe:226  case PPC::BI__builtin_ppc_minfe:227  case PPC::BI__builtin_ppc_maxfl:228  case PPC::BI__builtin_ppc_minfl:229  case PPC::BI__builtin_ppc_maxfs:230  case PPC::BI__builtin_ppc_minfs: {231    if (Context.getTargetInfo().getTriple().isOSAIX() &&232        (BuiltinID == PPC::BI__builtin_ppc_maxfe ||233         BuiltinID == PPC::BI__builtin_ppc_minfe))234      return Diag(TheCall->getBeginLoc(), diag::err_target_unsupported_type)235             << "builtin" << true << 128 << QualType(Context.LongDoubleTy)236             << false << Context.getTargetInfo().getTriple().str();237    // Argument type should be exact.238    QualType ArgType = QualType(Context.LongDoubleTy);239    if (BuiltinID == PPC::BI__builtin_ppc_maxfl ||240        BuiltinID == PPC::BI__builtin_ppc_minfl)241      ArgType = QualType(Context.DoubleTy);242    else if (BuiltinID == PPC::BI__builtin_ppc_maxfs ||243             BuiltinID == PPC::BI__builtin_ppc_minfs)244      ArgType = QualType(Context.FloatTy);245    for (unsigned I = 0, E = TheCall->getNumArgs(); I < E; ++I)246      if (TheCall->getArg(I)->getType() != ArgType)247        return Diag(TheCall->getBeginLoc(),248                    diag::err_typecheck_convert_incompatible)249               << TheCall->getArg(I)->getType() << ArgType << 1 << 0 << 0;250    return false;251  }252#define CUSTOM_BUILTIN(Name, Intr, Types, Acc, Feature)                        \253  case PPC::BI__builtin_##Name:                                                \254    return BuiltinPPCMMACall(TheCall, BuiltinID, Types);255#include "clang/Basic/BuiltinsPPC.def"256  }257  llvm_unreachable("must return from switch");258}259 260// Check if the given type is a non-pointer PPC MMA type. This function is used261// in Sema to prevent invalid uses of restricted PPC MMA types.262bool SemaPPC::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) {263  ASTContext &Context = getASTContext();264  if (Type->isPointerType() || Type->isArrayType())265    return false;266 267  QualType CoreType = Type.getCanonicalType().getUnqualifiedType();268#define PPC_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty269  if (false270#include "clang/Basic/PPCTypes.def"271  ) {272    Diag(TypeLoc, diag::err_ppc_invalid_use_mma_type);273    return true;274  }275  return false;276}277 278/// DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str,279/// advancing the pointer over the consumed characters. The decoded type is280/// returned. If the decoded type represents a constant integer with a281/// constraint on its value then Mask is set to that value. The type descriptors282/// used in Str are specific to PPC MMA builtins and are documented in the file283/// defining the PPC builtins.284static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str,285                                        unsigned &Mask) {286  bool RequireICE = false;287  ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;288  switch (*Str++) {289  case 'V':290    return Context.getVectorType(Context.UnsignedCharTy, 16,291                                 VectorKind::AltiVecVector);292  case 'i': {293    char *End;294    unsigned size = strtoul(Str, &End, 10);295    assert(End != Str && "Missing constant parameter constraint");296    Str = End;297    Mask = size;298    return Context.IntTy;299  }300  case 'W': {301    char *End;302    unsigned size = strtoul(Str, &End, 10);303    assert(End != Str && "Missing PowerPC MMA type size");304    Str = End;305    QualType Type;306    switch (size) {307#define PPC_VECTOR_TYPE(typeName, Id, size)                                    \308  case size:                                                                   \309    Type = Context.Id##Ty;                                                     \310    break;311#include "clang/Basic/PPCTypes.def"312    default:313      llvm_unreachable("Invalid PowerPC MMA vector type");314    }315    bool CheckVectorArgs = false;316    while (!CheckVectorArgs) {317      switch (*Str++) {318      case '*':319        Type = Context.getPointerType(Type);320        break;321      case 'C':322        Type = Type.withConst();323        break;324      default:325        CheckVectorArgs = true;326        --Str;327        break;328      }329    }330    return Type;331  }332  default:333    return Context.DecodeTypeStr(--Str, Context, Error, RequireICE, true);334  }335}336 337bool SemaPPC::BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,338                                const char *TypeStr) {339 340  assert((TypeStr[0] != '\0') &&341         "Invalid types in PPC MMA builtin declaration");342 343  ASTContext &Context = getASTContext();344  unsigned Mask = 0;345  unsigned ArgNum = 0;346 347  // The first type in TypeStr is the type of the value returned by the348  // builtin. So we first read that type and change the type of TheCall.349  QualType type = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);350  TheCall->setType(type);351 352  while (*TypeStr != '\0') {353    Mask = 0;354    QualType ExpectedType = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);355    if (ArgNum >= TheCall->getNumArgs()) {356      ArgNum++;357      break;358    }359 360    Expr *Arg = TheCall->getArg(ArgNum);361    QualType PassedType = Arg->getType();362    QualType StrippedRVType = PassedType.getCanonicalType();363 364    // Strip Restrict/Volatile qualifiers.365    if (StrippedRVType.isRestrictQualified() ||366        StrippedRVType.isVolatileQualified())367      StrippedRVType = StrippedRVType.getCanonicalType().getUnqualifiedType();368 369    // The only case where the argument type and expected type are allowed to370    // mismatch is if the argument type is a non-void pointer (or array) and371    // expected type is a void pointer.372    if (StrippedRVType != ExpectedType)373      if (!(ExpectedType->isVoidPointerType() &&374            (StrippedRVType->isPointerType() || StrippedRVType->isArrayType())))375        return Diag(Arg->getBeginLoc(),376                    diag::err_typecheck_convert_incompatible)377               << PassedType << ExpectedType << 1 << 0 << 0;378 379    // If the value of the Mask is not 0, we have a constraint in the size of380    // the integer argument so here we ensure the argument is a constant that381    // is in the valid range.382    if (Mask != 0 &&383        SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, Mask, true))384      return true;385 386    ArgNum++;387  }388 389  // In case we exited early from the previous loop, there are other types to390  // read from TypeStr. So we need to read them all to ensure we have the right391  // number of arguments in TheCall and if it is not the case, to display a392  // better error message.393  while (*TypeStr != '\0') {394    (void)DecodePPCMMATypeFromStr(Context, TypeStr, Mask);395    ArgNum++;396  }397  if (SemaRef.checkArgCount(TheCall, ArgNum))398    return true;399 400  return false;401}402 403bool SemaPPC::BuiltinVSX(CallExpr *TheCall) {404  unsigned ExpectedNumArgs = 3;405  if (SemaRef.checkArgCount(TheCall, ExpectedNumArgs))406    return true;407 408  // Check the third argument is a compile time constant409  if (!TheCall->getArg(2)->isIntegerConstantExpr(getASTContext()))410    return Diag(TheCall->getBeginLoc(),411                diag::err_vsx_builtin_nonconstant_argument)412           << 3 /* argument index */ << TheCall->getDirectCallee()413           << SourceRange(TheCall->getArg(2)->getBeginLoc(),414                          TheCall->getArg(2)->getEndLoc());415 416  QualType Arg1Ty = TheCall->getArg(0)->getType();417  QualType Arg2Ty = TheCall->getArg(1)->getType();418 419  // Check the type of argument 1 and argument 2 are vectors.420  SourceLocation BuiltinLoc = TheCall->getBeginLoc();421  if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||422      (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {423    return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)424           << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false425           << SourceRange(TheCall->getArg(0)->getBeginLoc(),426                          TheCall->getArg(1)->getEndLoc());427  }428 429  // Check the first two arguments are the same type.430  if (!getASTContext().hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {431    return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)432           << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false433           << SourceRange(TheCall->getArg(0)->getBeginLoc(),434                          TheCall->getArg(1)->getEndLoc());435  }436 437  // When default clang type checking is turned off and the customized type438  // checking is used, the returning type of the function must be explicitly439  // set. Otherwise it is _Bool by default.440  TheCall->setType(Arg1Ty);441 442  return false;443}444 445} // namespace clang446