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