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
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>(Val: Arg->IgnoreParens());
32 if (!ICE)
33 return;
34
35 const auto *DR = dyn_cast<DeclRefExpr>(Val: ICE->getSubExpr());
36 if (!DR)
37 return;
38
39 const auto *PD = dyn_cast<ParmVarDecl>(Val: 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 BitSize: AA->getAlignment(Ctx&: getASTContext()));
48 if (Alignment.getQuantity() == 16) {
49 Diag(Loc: FD->getLocation(), DiagID: diag::warn_not_xl_compatible) << FD;
50 Diag(Loc, DiagID: 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 case PPC::BI__builtin_amo_lwat:
91 case PPC::BI__builtin_amo_ldat:
92 case PPC::BI__builtin_amo_lwat_s:
93 case PPC::BI__builtin_amo_ldat_s:
94 case PPC::BI__builtin_amo_lwat_cond:
95 case PPC::BI__builtin_amo_ldat_cond:
96 case PPC::BI__builtin_amo_lwat_cond_s:
97 case PPC::BI__builtin_amo_ldat_cond_s:
98 case PPC::BI__builtin_amo_stwat:
99 case PPC::BI__builtin_amo_stdat:
100 case PPC::BI__builtin_amo_stwat_s:
101 case PPC::BI__builtin_amo_stdat_s:
102 case PPC::BI__builtin_amo_lwat_csne:
103 case PPC::BI__builtin_amo_ldat_csne:
104 case PPC::BI__builtin_amo_lwat_csne_s:
105 case PPC::BI__builtin_amo_ldat_csne_s:
106 return true;
107 }
108 return false;
109}
110
111bool SemaPPC::CheckPPCBuiltinFunctionCall(const TargetInfo &TI,
112 unsigned BuiltinID,
113 CallExpr *TheCall) {
114 ASTContext &Context = getASTContext();
115 bool IsTarget64Bit = TI.getTypeWidth(T: TI.getIntPtrType()) == 64;
116
117 if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
118 return Diag(Loc: TheCall->getBeginLoc(), DiagID: diag::err_64_bit_builtin_32_bit_tgt)
119 << TheCall->getSourceRange();
120
121 // Common BCD type-validation helpers
122 // Emit error diagnostics and return true on success
123 // - IsTypeVecUChar: enforces vector unsigned char
124 // - IsIntType: enforces any integer type
125 // Lambdas centralize type checks for BCD builtin handlers
126
127 // Lambda 1: verify vector unsigned char type
128 auto IsTypeVecUChar = [&](QualType ArgTy, unsigned ArgIndex) -> bool {
129 QualType VecType = Context.getVectorType(VectorType: Context.UnsignedCharTy, NumElts: 16,
130 VecKind: VectorKind::AltiVecVector);
131 if (Context.hasSameType(T1: ArgTy, T2: VecType))
132 return true;
133
134 Diag(Loc: TheCall->getArg(Arg: ArgIndex)->getBeginLoc(),
135 DiagID: diag::err_ppc_invalid_arg_type)
136 << ArgIndex << VecType << ArgTy;
137 return false;
138 };
139
140 // Lambda 2: verify integer type
141 auto IsIntType = [&](QualType ArgTy, unsigned ArgIndex) -> bool {
142 if (ArgTy->isIntegerType())
143 return true;
144
145 Diag(Loc: TheCall->getArg(Arg: ArgIndex)->getBeginLoc(),
146 DiagID: diag::err_ppc_invalid_arg_type)
147 << ArgIndex << "integer" << ArgTy;
148 return false;
149 };
150
151 switch (BuiltinID) {
152 default:
153 return false;
154 case PPC::BI__builtin_ppc_bcdsetsign: {
155 // Arg0 must be vector unsigned char
156 if (!IsTypeVecUChar(TheCall->getArg(Arg: 0)->getType(), 0))
157 return false;
158
159 // Restrict Arg1 constant range (0–1)
160 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 1);
161 }
162 case PPC::BI__builtin_ppc_national2packed:
163 case PPC::BI__builtin_ppc_packed2zoned:
164 case PPC::BI__builtin_ppc_zoned2packed:
165 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 1);
166 case PPC::BI__builtin_ppc_bcdshift:
167 case PPC::BI__builtin_ppc_bcdshiftround:
168 case PPC::BI__builtin_ppc_bcdtruncate: {
169
170 // Arg0 must be vector unsigned char
171 if (!IsTypeVecUChar(TheCall->getArg(Arg: 0)->getType(), 0))
172 return false;
173
174 // Arg1 must be integer type
175 if (!IsIntType(TheCall->getArg(Arg: 1)->getType(), 1))
176 return false;
177
178 // Restrict Arg2 constant range (0–1)
179 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 1);
180 }
181 case PPC::BI__builtin_altivec_crypto_vshasigmaw:
182 case PPC::BI__builtin_altivec_crypto_vshasigmad:
183 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 1) ||
184 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 15);
185 case PPC::BI__builtin_altivec_dss:
186 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 3);
187 case PPC::BI__builtin_tbegin:
188 case PPC::BI__builtin_tend:
189 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 1);
190 case PPC::BI__builtin_tsr:
191 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 7);
192 case PPC::BI__builtin_tabortwc:
193 case PPC::BI__builtin_tabortdc:
194 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 31);
195 case PPC::BI__builtin_tabortwci:
196 case PPC::BI__builtin_tabortdci:
197 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 31) ||
198 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 31);
199 // According to GCC 'Basic PowerPC Built-in Functions Available on ISA 2.05',
200 // __builtin_(un)pack_longdouble are available only if long double uses IBM
201 // extended double representation.
202 case PPC::BI__builtin_unpack_longdouble:
203 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 1))
204 return true;
205 [[fallthrough]];
206 case PPC::BI__builtin_pack_longdouble:
207 if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())
208 return Diag(Loc: TheCall->getBeginLoc(), DiagID: diag::err_ppc_builtin_requires_abi)
209 << "ibmlongdouble";
210 return false;
211 case PPC::BI__builtin_altivec_dst:
212 case PPC::BI__builtin_altivec_dstt:
213 case PPC::BI__builtin_altivec_dstst:
214 case PPC::BI__builtin_altivec_dststt:
215 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 3);
216 case PPC::BI__builtin_vsx_xxpermdi:
217 case PPC::BI__builtin_vsx_xxsldwi:
218 return BuiltinVSX(TheCall);
219 case PPC::BI__builtin_unpack_vector_int128:
220 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 1);
221 case PPC::BI__builtin_altivec_vgnb:
222 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 2, High: 7);
223 case PPC::BI__builtin_vsx_xxeval:
224 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 3, Low: 0, High: 255);
225 case PPC::BI__builtin_altivec_vsldbi:
226 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 7);
227 case PPC::BI__builtin_altivec_vsrdbi:
228 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 7);
229 case PPC::BI__builtin_vsx_xxpermx:
230 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 3, Low: 0, High: 7);
231 case PPC::BI__builtin_ppc_tw:
232 case PPC::BI__builtin_ppc_tdw:
233 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 1, High: 31);
234 case PPC::BI__builtin_ppc_cmprb:
235 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 1);
236 // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must
237 // be a constant that represents a contiguous bit field.
238 case PPC::BI__builtin_ppc_rlwnm:
239 return SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 2);
240 case PPC::BI__builtin_ppc_rlwimi:
241 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 31) ||
242 SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 3);
243 case PPC::BI__builtin_ppc_rldimi:
244 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 63) ||
245 SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 3);
246 case PPC::BI__builtin_ppc_addex: {
247 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 2, Low: 0, High: 3))
248 return true;
249 // Output warning for reserved values 1 to 3.
250 int ArgValue =
251 TheCall->getArg(Arg: 2)->getIntegerConstantExpr(Ctx: Context)->getSExtValue();
252 if (ArgValue != 0)
253 Diag(Loc: TheCall->getBeginLoc(), DiagID: diag::warn_argument_undefined_behaviour)
254 << ArgValue;
255 return false;
256 }
257 case PPC::BI__builtin_ppc_mtfsb0:
258 case PPC::BI__builtin_ppc_mtfsb1:
259 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 31);
260 case PPC::BI__builtin_ppc_mtfsf:
261 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 255);
262 case PPC::BI__builtin_ppc_mtfsfi:
263 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 0, Low: 0, High: 7) ||
264 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 15);
265 case PPC::BI__builtin_ppc_alignx:
266 return SemaRef.BuiltinConstantArgPower2(TheCall, ArgNum: 0);
267 case PPC::BI__builtin_ppc_rdlam:
268 return SemaRef.ValueIsRunOfOnes(TheCall, ArgNum: 2);
269 case PPC::BI__builtin_vsx_ldrmb:
270 case PPC::BI__builtin_vsx_strmb:
271 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 1, High: 16);
272 case PPC::BI__builtin_altivec_vcntmbb:
273 case PPC::BI__builtin_altivec_vcntmbh:
274 case PPC::BI__builtin_altivec_vcntmbw:
275 case PPC::BI__builtin_altivec_vcntmbd:
276 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 1);
277 case PPC::BI__builtin_vsx_xxgenpcvbm:
278 case PPC::BI__builtin_vsx_xxgenpcvhm:
279 case PPC::BI__builtin_vsx_xxgenpcvwm:
280 case PPC::BI__builtin_vsx_xxgenpcvdm:
281 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 3);
282 case PPC::BI__builtin_ppc_test_data_class: {
283 // Check if the first argument of the __builtin_ppc_test_data_class call is
284 // valid. The argument must be 'float' or 'double' or '__float128'.
285 QualType ArgType = TheCall->getArg(Arg: 0)->getType();
286 if (ArgType != QualType(Context.FloatTy) &&
287 ArgType != QualType(Context.DoubleTy) &&
288 ArgType != QualType(Context.Float128Ty))
289 return Diag(Loc: TheCall->getBeginLoc(),
290 DiagID: diag::err_ppc_invalid_test_data_class_type);
291 return SemaRef.BuiltinConstantArgRange(TheCall, ArgNum: 1, Low: 0, High: 127);
292 }
293 case PPC::BI__builtin_ppc_maxfe:
294 case PPC::BI__builtin_ppc_minfe:
295 case PPC::BI__builtin_ppc_maxfl:
296 case PPC::BI__builtin_ppc_minfl:
297 case PPC::BI__builtin_ppc_maxfs:
298 case PPC::BI__builtin_ppc_minfs: {
299 if (Context.getTargetInfo().getTriple().isOSAIX() &&
300 (BuiltinID == PPC::BI__builtin_ppc_maxfe ||
301 BuiltinID == PPC::BI__builtin_ppc_minfe))
302 return Diag(Loc: TheCall->getBeginLoc(), DiagID: diag::err_target_unsupported_type)
303 << "builtin" << true << 128 << QualType(Context.LongDoubleTy)
304 << false << Context.getTargetInfo().getTriple().str();
305 // Argument type should be exact.
306 QualType ArgType = QualType(Context.LongDoubleTy);
307 if (BuiltinID == PPC::BI__builtin_ppc_maxfl ||
308 BuiltinID == PPC::BI__builtin_ppc_minfl)
309 ArgType = QualType(Context.DoubleTy);
310 else if (BuiltinID == PPC::BI__builtin_ppc_maxfs ||
311 BuiltinID == PPC::BI__builtin_ppc_minfs)
312 ArgType = QualType(Context.FloatTy);
313 for (unsigned I = 0, E = TheCall->getNumArgs(); I < E; ++I)
314 if (TheCall->getArg(Arg: I)->getType() != ArgType)
315 return Diag(Loc: TheCall->getBeginLoc(),
316 DiagID: diag::err_typecheck_convert_incompatible)
317 << TheCall->getArg(Arg: I)->getType() << ArgType << 1 << 0 << 0;
318 return false;
319 }
320#define CUSTOM_BUILTIN(Name, Intr, Types, Acc, Feature) \
321 case PPC::BI__builtin_##Name: \
322 return BuiltinPPCMMACall(TheCall, BuiltinID, Types);
323#include "clang/Basic/BuiltinsPPC.def"
324 case PPC::BI__builtin_amo_lwat:
325 case PPC::BI__builtin_amo_ldat:
326 case PPC::BI__builtin_amo_lwat_s:
327 case PPC::BI__builtin_amo_ldat_s: {
328 llvm::APSInt Result;
329 if (SemaRef.BuiltinConstantArg(TheCall, ArgNum: 2, Result))
330 return true;
331 unsigned Val = Result.getZExtValue();
332
333 bool IsUnsigned = (BuiltinID == PPC::BI__builtin_amo_lwat ||
334 BuiltinID == PPC::BI__builtin_amo_ldat);
335
336 bool IsValid = IsUnsigned
337 ? llvm::is_contained(Set: {0u, 1u, 2u, 3u, 4u, 6u, 8u}, Element: Val)
338 : llvm::is_contained(Set: {0u, 5u, 7u, 8u}, Element: Val);
339
340 if (IsValid)
341 return false;
342
343 Expr *Arg = TheCall->getArg(Arg: 2);
344 return SemaRef.Diag(Loc: Arg->getBeginLoc(), DiagID: diag::err_argument_invalid_range)
345 << toString(I: Result, Radix: 10) << (IsUnsigned ? "0-4, 6" : "0, 5, 7") << "8"
346 << Arg->getSourceRange();
347 }
348 case PPC::BI__builtin_amo_lwat_cond:
349 case PPC::BI__builtin_amo_ldat_cond:
350 case PPC::BI__builtin_amo_lwat_cond_s:
351 case PPC::BI__builtin_amo_ldat_cond_s: {
352 llvm::APSInt Result;
353 if (SemaRef.BuiltinConstantArg(TheCall, ArgNum: 1, Result))
354 return true;
355 unsigned Val = Result.getZExtValue();
356 if (llvm::is_contained(Set: {24u, 25u, 28u}, Element: Val))
357 return false;
358
359 Expr *Arg = TheCall->getArg(Arg: 1);
360 return SemaRef.Diag(Loc: Arg->getBeginLoc(), DiagID: diag::err_argument_invalid_range)
361 << toString(I: Result, Radix: 10) << "24, 25" << "28" << Arg->getSourceRange();
362 }
363 case PPC::BI__builtin_amo_stwat:
364 case PPC::BI__builtin_amo_stdat:
365 case PPC::BI__builtin_amo_stwat_s:
366 case PPC::BI__builtin_amo_stdat_s: {
367 llvm::APSInt Result;
368 if (SemaRef.BuiltinConstantArg(TheCall, ArgNum: 2, Result))
369 return true;
370 unsigned Val = Result.getZExtValue();
371
372 bool IsUnsigned = (BuiltinID == PPC::BI__builtin_amo_stwat ||
373 BuiltinID == PPC::BI__builtin_amo_stdat);
374
375 bool IsValid = IsUnsigned
376 ? llvm::is_contained(Set: {0u, 1u, 2u, 3u, 4u, 6u, 24u}, Element: Val)
377 : llvm::is_contained(Set: {0u, 5u, 7u, 24u}, Element: Val);
378
379 if (IsValid)
380 return false;
381
382 Expr *Arg = TheCall->getArg(Arg: 2);
383 return SemaRef.Diag(Loc: Arg->getBeginLoc(), DiagID: diag::err_argument_invalid_range)
384 << toString(I: Result, Radix: 10) << (IsUnsigned ? "0-4, 6" : "0, 5, 7")
385 << "24" << Arg->getSourceRange();
386 }
387 }
388 llvm_unreachable("must return from switch");
389}
390
391// Check if the given type is a non-pointer PPC MMA type. This function is used
392// in Sema to prevent invalid uses of restricted PPC MMA types.
393bool SemaPPC::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) {
394 ASTContext &Context = getASTContext();
395 if (Type->isPointerType() || Type->isArrayType())
396 return false;
397
398 QualType CoreType = Type.getCanonicalType().getUnqualifiedType();
399#define PPC_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty
400 if (false
401#include "clang/Basic/PPCTypes.def"
402 ) {
403 Diag(Loc: TypeLoc, DiagID: diag::err_ppc_invalid_use_mma_type);
404 return true;
405 }
406 return false;
407}
408
409/// DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str,
410/// advancing the pointer over the consumed characters. The decoded type is
411/// returned. If the decoded type represents a constant integer with a
412/// constraint on its value then Mask is set to that value. The type descriptors
413/// used in Str are specific to PPC MMA builtins and are documented in the file
414/// defining the PPC builtins.
415static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str,
416 unsigned &Mask) {
417 bool RequireICE = false;
418 ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;
419 switch (*Str++) {
420 case 'V':
421 return Context.getVectorType(VectorType: Context.UnsignedCharTy, NumElts: 16,
422 VecKind: VectorKind::AltiVecVector);
423 case 'i': {
424 char *End;
425 unsigned size = strtoul(nptr: Str, endptr: &End, base: 10);
426 assert(End != Str && "Missing constant parameter constraint");
427 Str = End;
428 Mask = size;
429 return Context.IntTy;
430 }
431 case 'W': {
432 char *End;
433 unsigned size = strtoul(nptr: Str, endptr: &End, base: 10);
434 assert(End != Str && "Missing PowerPC MMA type size");
435 Str = End;
436 QualType Type;
437 switch (size) {
438#define PPC_VECTOR_TYPE(typeName, Id, size) \
439 case size: \
440 Type = Context.Id##Ty; \
441 break;
442#include "clang/Basic/PPCTypes.def"
443 default:
444 llvm_unreachable("Invalid PowerPC MMA vector type");
445 }
446 bool CheckVectorArgs = false;
447 while (!CheckVectorArgs) {
448 switch (*Str++) {
449 case '*':
450 Type = Context.getPointerType(T: Type);
451 break;
452 case 'C':
453 Type = Type.withConst();
454 break;
455 default:
456 CheckVectorArgs = true;
457 --Str;
458 break;
459 }
460 }
461 return Type;
462 }
463 default:
464 return Context.DecodeTypeStr(Str&: --Str, Context, Error, RequireICE, AllowTypeModifiers: true);
465 }
466}
467
468bool SemaPPC::BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
469 const char *TypeStr) {
470
471 assert((TypeStr[0] != '\0') &&
472 "Invalid types in PPC MMA builtin declaration");
473
474 ASTContext &Context = getASTContext();
475 unsigned Mask = 0;
476 unsigned ArgNum = 0;
477
478 // The first type in TypeStr is the type of the value returned by the
479 // builtin. So we first read that type and change the type of TheCall.
480 QualType type = DecodePPCMMATypeFromStr(Context, Str&: TypeStr, Mask);
481 TheCall->setType(type);
482
483 while (*TypeStr != '\0') {
484 Mask = 0;
485 QualType ExpectedType = DecodePPCMMATypeFromStr(Context, Str&: TypeStr, Mask);
486 if (ArgNum >= TheCall->getNumArgs()) {
487 ArgNum++;
488 break;
489 }
490
491 Expr *Arg = TheCall->getArg(Arg: ArgNum);
492 QualType PassedType = Arg->getType();
493 QualType StrippedRVType = PassedType.getCanonicalType();
494
495 // Strip Restrict/Volatile qualifiers.
496 if (StrippedRVType.isRestrictQualified() ||
497 StrippedRVType.isVolatileQualified())
498 StrippedRVType = StrippedRVType.getCanonicalType().getUnqualifiedType();
499
500 // The only case where the argument type and expected type are allowed to
501 // mismatch is if the argument type is a non-void pointer (or array) and
502 // expected type is a void pointer.
503 if (StrippedRVType != ExpectedType)
504 if (!(ExpectedType->isVoidPointerType() &&
505 (StrippedRVType->isPointerType() || StrippedRVType->isArrayType())))
506 return Diag(Loc: Arg->getBeginLoc(),
507 DiagID: diag::err_typecheck_convert_incompatible)
508 << PassedType << ExpectedType << 1 << 0 << 0;
509
510 // If the value of the Mask is not 0, we have a constraint in the size of
511 // the integer argument so here we ensure the argument is a constant that
512 // is in the valid range.
513 if (Mask != 0 &&
514 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, Low: 0, High: Mask, RangeIsError: true))
515 return true;
516
517 ArgNum++;
518 }
519
520 // In case we exited early from the previous loop, there are other types to
521 // read from TypeStr. So we need to read them all to ensure we have the right
522 // number of arguments in TheCall and if it is not the case, to display a
523 // better error message.
524 while (*TypeStr != '\0') {
525 (void)DecodePPCMMATypeFromStr(Context, Str&: TypeStr, Mask);
526 ArgNum++;
527 }
528 if (SemaRef.checkArgCount(Call: TheCall, DesiredArgCount: ArgNum))
529 return true;
530
531 return false;
532}
533
534bool SemaPPC::BuiltinVSX(CallExpr *TheCall) {
535 unsigned ExpectedNumArgs = 3;
536 if (SemaRef.checkArgCount(Call: TheCall, DesiredArgCount: ExpectedNumArgs))
537 return true;
538
539 // Check the third argument is a compile time constant
540 if (!TheCall->getArg(Arg: 2)->isIntegerConstantExpr(Ctx: getASTContext()))
541 return Diag(Loc: TheCall->getBeginLoc(),
542 DiagID: diag::err_vsx_builtin_nonconstant_argument)
543 << 3 /* argument index */ << TheCall->getDirectCallee()
544 << SourceRange(TheCall->getArg(Arg: 2)->getBeginLoc(),
545 TheCall->getArg(Arg: 2)->getEndLoc());
546
547 QualType Arg1Ty = TheCall->getArg(Arg: 0)->getType();
548 QualType Arg2Ty = TheCall->getArg(Arg: 1)->getType();
549
550 // Check the type of argument 1 and argument 2 are vectors.
551 SourceLocation BuiltinLoc = TheCall->getBeginLoc();
552 if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
553 (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
554 return Diag(Loc: BuiltinLoc, DiagID: diag::err_vec_builtin_non_vector)
555 << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
556 << SourceRange(TheCall->getArg(Arg: 0)->getBeginLoc(),
557 TheCall->getArg(Arg: 1)->getEndLoc());
558 }
559
560 // Check the first two arguments are the same type.
561 if (!getASTContext().hasSameUnqualifiedType(T1: Arg1Ty, T2: Arg2Ty)) {
562 return Diag(Loc: BuiltinLoc, DiagID: diag::err_vec_builtin_incompatible_vector)
563 << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
564 << SourceRange(TheCall->getArg(Arg: 0)->getBeginLoc(),
565 TheCall->getArg(Arg: 1)->getEndLoc());
566 }
567
568 // When default clang type checking is turned off and the customized type
569 // checking is used, the returning type of the function must be explicitly
570 // set. Otherwise it is _Bool by default.
571 TheCall->setType(Arg1Ty);
572
573 return false;
574}
575
576} // namespace clang
577