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 102 if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit) 103 return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt) 104 << TheCall->getSourceRange(); 105 106 switch (BuiltinID) { 107 default: 108 return false; 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 IBM 133 // 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 must 169 // 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 is 216 // 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 used 261 // in Sema to prevent invalid uses of restricted PPC MMA types. 262 bool 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##Ty 269 if (false 270 #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 is 280 /// returned. If the decoded type represents a constant integer with a 281 /// constraint on its value then Mask is set to that value. The type descriptors 282 /// used in Str are specific to PPC MMA builtins and are documented in the file 283 /// defining the PPC builtins. 284 static 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 337 bool 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 the 348 // 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 to 370 // mismatch is if the argument type is a non-void pointer (or array) and 371 // 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 of 380 // the integer argument so here we ensure the argument is a constant that 381 // 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 to 390 // read from TypeStr. So we need to read them all to ensure we have the right 391 // number of arguments in TheCall and if it is not the case, to display a 392 // 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 403 bool 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 constant 409 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*/ false 425 << 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*/ false 433 << SourceRange(TheCall->getArg(0)->getBeginLoc(), 434 TheCall->getArg(1)->getEndLoc()); 435 } 436 437 // When default clang type checking is turned off and the customized type 438 // checking is used, the returning type of the function must be explicitly 439 // set. Otherwise it is _Bool by default. 440 TheCall->setType(Arg1Ty); 441 442 return false; 443 } 444 445 } // namespace clang 446