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