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