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