clang 24.0.0git
SemaPPC.cpp
Go to the documentation of this file.
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"
15#include "clang/AST/Attr.h"
16#include "clang/AST/CharUnits.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/Type.h"
24#include "clang/Sema/Sema.h"
25#include "llvm/ADT/APSInt.h"
26#include "llvm/TargetParser/PPCTargetParser.h"
27
28namespace clang {
29
31
33 const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg->IgnoreParens());
34 if (!ICE)
35 return;
36
37 const auto *DR = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
38 if (!DR)
39 return;
40
41 const auto *PD = dyn_cast<ParmVarDecl>(DR->getDecl());
42 if (!PD || !PD->getType()->isRecordType())
43 return;
44
45 QualType ArgType = Arg->getType();
46 for (const FieldDecl *FD : ArgType->castAsRecordDecl()->fields()) {
47 if (const auto *AA = FD->getAttr<AlignedAttr>()) {
49 AA->getAlignment(getASTContext()));
50 if (Alignment.getQuantity() == 16) {
51 Diag(FD->getLocation(), diag::warn_not_xl_compatible) << FD;
52 Diag(Loc, diag::note_misaligned_member_used_here) << PD;
53 }
54 }
55 }
56}
57
58static bool isPPC_64Builtin(unsigned BuiltinID) {
59 // These builtins only work on PPC 64bit targets.
60 switch (BuiltinID) {
61 case PPC::BI__builtin_divde:
62 case PPC::BI__builtin_divdeu:
63 case PPC::BI__builtin_bpermd:
64 case PPC::BI__builtin_pdepd:
65 case PPC::BI__builtin_pextd:
66 case PPC::BI__builtin_ppc_cdtbcd:
67 case PPC::BI__builtin_ppc_cbcdtd:
68 case PPC::BI__builtin_ppc_addg6s:
69 case PPC::BI__builtin_ppc_ldarx:
70 case PPC::BI__builtin_ppc_stdcx:
71 case PPC::BI__builtin_ppc_tdw:
72 case PPC::BI__builtin_ppc_trapd:
73 case PPC::BI__builtin_ppc_cmpeqb:
74 case PPC::BI__builtin_ppc_setb:
75 case PPC::BI__builtin_ppc_mulhd:
76 case PPC::BI__builtin_ppc_mulhdu:
77 case PPC::BI__builtin_ppc_maddhd:
78 case PPC::BI__builtin_ppc_maddhdu:
79 case PPC::BI__builtin_ppc_maddld:
80 case PPC::BI__builtin_ppc_load8r:
81 case PPC::BI__builtin_ppc_store8r:
82 case PPC::BI__builtin_ppc_insert_exp:
83 case PPC::BI__builtin_ppc_extract_sig:
84 case PPC::BI__builtin_ppc_addex:
85 case PPC::BI__builtin_darn:
86 case PPC::BI__builtin_darn_raw:
87 case PPC::BI__builtin_ppc_compare_and_swaplp:
88 case PPC::BI__builtin_ppc_fetch_and_addlp:
89 case PPC::BI__builtin_ppc_fetch_and_andlp:
90 case PPC::BI__builtin_ppc_fetch_and_orlp:
91 case PPC::BI__builtin_ppc_fetch_and_swaplp:
92 case PPC::BI__builtin_amo_lwat:
93 case PPC::BI__builtin_amo_ldat:
94 case PPC::BI__builtin_amo_lwat_s:
95 case PPC::BI__builtin_amo_ldat_s:
96 case PPC::BI__builtin_amo_lwat_cond:
97 case PPC::BI__builtin_amo_ldat_cond:
98 case PPC::BI__builtin_amo_lwat_cond_s:
99 case PPC::BI__builtin_amo_ldat_cond_s:
100 case PPC::BI__builtin_amo_stwat:
101 case PPC::BI__builtin_amo_stdat:
102 case PPC::BI__builtin_amo_stwat_s:
103 case PPC::BI__builtin_amo_stdat_s:
104 case PPC::BI__builtin_amo_lwat_csne:
105 case PPC::BI__builtin_amo_ldat_csne:
106 case PPC::BI__builtin_amo_lwat_csne_s:
107 case PPC::BI__builtin_amo_ldat_csne_s:
108 return true;
109 }
110 return false;
111}
112
114 unsigned BuiltinID,
115 CallExpr *TheCall) {
116 ASTContext &Context = getASTContext();
117 bool IsTarget64Bit = TI.getTypeWidth(TI.getIntPtrType()) == 64;
118
119 if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
120 return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
121 << TheCall->getSourceRange();
122
123 // Check if the builtin requires specific target features.
124 StringRef FeatureList(Context.BuiltinInfo.getRequiredFeatures(BuiltinID));
125 if (!FeatureList.empty()) {
126 const auto *FD = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
127 llvm::StringMap<bool> CallerFeatureMap;
128 Context.getFunctionFeatureMap(CallerFeatureMap, FD);
130 CallerFeatureMap)) {
131 // Get the builtin name from the CallExpr's callee
132 const FunctionDecl *BuiltinDecl = TheCall->getDirectCallee();
133 Diag(TheCall->getBeginLoc(), diag::err_builtin_needs_feature)
134 << (BuiltinDecl ? BuiltinDecl->getDeclName()
135 : DeclarationName(&Context.Idents.get(
136 Context.BuiltinInfo.getName(BuiltinID))))
137 << FeatureList;
138 return true;
139 }
140 }
141
142 // Common BCD type-validation helpers
143 // Emit error diagnostics and return true on success
144 // - IsTypeVecUChar: enforces vector unsigned char
145 // - IsIntType: enforces any integer type
146 // Lambdas centralize type checks for BCD builtin handlers
147
148 // Lambda 1: verify vector unsigned char type
149 auto IsTypeVecUChar = [&](QualType ArgTy, unsigned ArgIndex) -> bool {
150 QualType VecType = Context.getVectorType(Context.UnsignedCharTy, 16,
152 if (Context.hasSameType(ArgTy, VecType))
153 return true;
154
155 Diag(TheCall->getArg(ArgIndex)->getBeginLoc(),
156 diag::err_ppc_invalid_arg_type)
157 << ArgIndex << VecType << ArgTy;
158 return false;
159 };
160
161 // Lambda 2: verify integer type
162 auto IsIntType = [&](QualType ArgTy, unsigned ArgIndex) -> bool {
163 if (ArgTy->isIntegerType())
164 return true;
165
166 Diag(TheCall->getArg(ArgIndex)->getBeginLoc(),
167 diag::err_ppc_invalid_arg_type)
168 << ArgIndex << "integer" << ArgTy;
169 return false;
170 };
171
172 switch (BuiltinID) {
173 default:
174 return false;
175 case PPC::BI__builtin_ppc_bcdsetsign: {
176 // Arg0 must be vector unsigned char
177 if (!IsTypeVecUChar(TheCall->getArg(0)->getType(), 0))
178 return false;
179
180 // Restrict Arg1 constant range (0–1)
181 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
182 }
183 case PPC::BI__builtin_ppc_national2packed:
184 case PPC::BI__builtin_ppc_packed2zoned:
185 case PPC::BI__builtin_ppc_zoned2packed:
186 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
187 case PPC::BI__builtin_ppc_bcdshift:
188 case PPC::BI__builtin_ppc_bcdshiftround:
189 case PPC::BI__builtin_ppc_bcdtruncate: {
190
191 // Arg0 must be vector unsigned char
192 if (!IsTypeVecUChar(TheCall->getArg(0)->getType(), 0))
193 return false;
194
195 // Arg1 must be integer type
196 if (!IsIntType(TheCall->getArg(1)->getType(), 1))
197 return false;
198
199 // Restrict Arg2 constant range (0–1)
200 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
201 }
202 case PPC::BI__builtin_altivec_crypto_vshasigmaw:
203 case PPC::BI__builtin_altivec_crypto_vshasigmad:
204 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
205 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 15);
206 case PPC::BI__builtin_altivec_dss:
207 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 3);
208 case PPC::BI__builtin_tbegin:
209 case PPC::BI__builtin_tend:
210 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1);
211 case PPC::BI__builtin_tsr:
212 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 7);
213 case PPC::BI__builtin_tabortwc:
214 case PPC::BI__builtin_tabortdc:
215 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
216 case PPC::BI__builtin_tabortwci:
217 case PPC::BI__builtin_tabortdci:
218 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31) ||
219 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31);
220 // According to GCC 'Basic PowerPC Built-in Functions Available on ISA 2.05',
221 // __builtin_(un)pack_longdouble are available only if long double uses IBM
222 // extended double representation.
223 case PPC::BI__builtin_unpack_longdouble:
224 if (SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1))
225 return true;
226 [[fallthrough]];
227 case PPC::BI__builtin_pack_longdouble:
228 if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())
229 return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_requires_abi)
230 << "ibmlongdouble";
231 return false;
232 case PPC::BI__builtin_altivec_dst:
233 case PPC::BI__builtin_altivec_dstt:
234 case PPC::BI__builtin_altivec_dstst:
235 case PPC::BI__builtin_altivec_dststt:
236 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3);
237 case PPC::BI__builtin_vsx_xxpermdi:
238 case PPC::BI__builtin_vsx_xxsldwi:
239 return BuiltinVSX(TheCall);
240 case PPC::BI__builtin_unpack_vector_int128:
241 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
242 case PPC::BI__builtin_altivec_vgnb:
243 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 2, 7);
244 case PPC::BI__builtin_vsx_xxeval:
245 return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 255);
246 case PPC::BI__builtin_altivec_vsldbi:
247 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
248 case PPC::BI__builtin_altivec_vsrdbi:
249 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
250 case PPC::BI__builtin_vsx_xxpermx:
251 return SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 7);
252 case PPC::BI__builtin_altivec_vupkint4tobf16:
253 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
254 case PPC::BI__builtin_altivec_vupkint8tobf16:
255 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
256 case PPC::BI__builtin_altivec_vupkint4tofp32:
257 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 7);
258 case PPC::BI__builtin_altivec_vupkint8tofp32:
259 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
260 case PPC::BI__builtin_ppc_tw:
261 case PPC::BI__builtin_ppc_tdw:
262 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 1, 31);
263 case PPC::BI__builtin_ppc_cmprb:
264 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 1);
265 // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must
266 // be a constant that represents a contiguous bit field.
267 case PPC::BI__builtin_ppc_rlwnm:
268 return SemaRef.ValueIsRunOfOnes(TheCall, 2);
269 case PPC::BI__builtin_ppc_rlwimi:
270 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 31) ||
271 SemaRef.ValueIsRunOfOnes(TheCall, 3);
272 case PPC::BI__builtin_ppc_rldimi:
273 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 63) ||
274 SemaRef.ValueIsRunOfOnes(TheCall, 3);
275 case PPC::BI__builtin_ppc_addex: {
276 if (SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3))
277 return true;
278 // Output warning for reserved values 1 to 3.
279 int ArgValue =
280 TheCall->getArg(2)->getIntegerConstantExpr(Context)->getSExtValue();
281 if (ArgValue != 0)
282 Diag(TheCall->getBeginLoc(), diag::warn_argument_undefined_behaviour)
283 << ArgValue;
284 return false;
285 }
286 case PPC::BI__builtin_ppc_mtfsb0:
287 case PPC::BI__builtin_ppc_mtfsb1:
288 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
289 case PPC::BI__builtin_ppc_mtfsf:
290 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 255);
291 case PPC::BI__builtin_ppc_mtfsfi:
292 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 7) ||
293 SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
294 case PPC::BI__builtin_ppc_alignx:
295 return SemaRef.BuiltinConstantArgPower2(TheCall, 0);
296 case PPC::BI__builtin_ppc_rdlam:
297 return SemaRef.ValueIsRunOfOnes(TheCall, 2);
298 case PPC::BI__builtin_vsx_ldrmb:
299 case PPC::BI__builtin_vsx_strmb:
300 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
301 case PPC::BI__builtin_altivec_vcntmbb:
302 case PPC::BI__builtin_altivec_vcntmbh:
303 case PPC::BI__builtin_altivec_vcntmbw:
304 case PPC::BI__builtin_altivec_vcntmbd:
305 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
306 case PPC::BI__builtin_vsx_xxgenpcvbm:
307 case PPC::BI__builtin_vsx_xxgenpcvhm:
308 case PPC::BI__builtin_vsx_xxgenpcvwm:
309 case PPC::BI__builtin_vsx_xxgenpcvdm:
310 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3);
311 case PPC::BI__builtin_ppc_test_data_class: {
312 // Check if the first argument of the __builtin_ppc_test_data_class call is
313 // valid. The argument must be 'float' or 'double' or '__float128'.
314 QualType ArgType = TheCall->getArg(0)->getType();
315 if (ArgType != QualType(Context.FloatTy) &&
316 ArgType != QualType(Context.DoubleTy) &&
317 ArgType != QualType(Context.Float128Ty))
318 return Diag(TheCall->getBeginLoc(),
319 diag::err_ppc_invalid_test_data_class_type);
320 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 127);
321 }
322 case PPC::BI__builtin_ppc_maxfe:
323 case PPC::BI__builtin_ppc_minfe:
324 case PPC::BI__builtin_ppc_maxfl:
325 case PPC::BI__builtin_ppc_minfl:
326 case PPC::BI__builtin_ppc_maxfs:
327 case PPC::BI__builtin_ppc_minfs: {
328 if (Context.getTargetInfo().getTriple().isOSAIX() &&
329 (BuiltinID == PPC::BI__builtin_ppc_maxfe ||
330 BuiltinID == PPC::BI__builtin_ppc_minfe))
331 return Diag(TheCall->getBeginLoc(), diag::err_target_unsupported_type)
332 << "builtin" << true << 128 << QualType(Context.LongDoubleTy)
333 << false << Context.getTargetInfo().getTriple().str();
334 // Argument type should be exact.
335 QualType ArgType = QualType(Context.LongDoubleTy);
336 if (BuiltinID == PPC::BI__builtin_ppc_maxfl ||
337 BuiltinID == PPC::BI__builtin_ppc_minfl)
338 ArgType = QualType(Context.DoubleTy);
339 else if (BuiltinID == PPC::BI__builtin_ppc_maxfs ||
340 BuiltinID == PPC::BI__builtin_ppc_minfs)
341 ArgType = QualType(Context.FloatTy);
342 for (unsigned I = 0, E = TheCall->getNumArgs(); I < E; ++I)
343 if (TheCall->getArg(I)->getType() != ArgType)
344 return Diag(TheCall->getBeginLoc(),
345 diag::err_typecheck_convert_incompatible)
346 << TheCall->getArg(I)->getType() << ArgType << 1 << 0 << 0;
347 return false;
348 }
349#define CUSTOM_BUILTIN(Name, Intr, Types, Acc, Feature) \
350 case PPC::BI__builtin_##Name: \
351 return BuiltinPPCMMACall(TheCall, BuiltinID, Types);
352#include "clang/Basic/BuiltinsPPC.def"
353 case PPC::BI__builtin_amo_lwat:
354 case PPC::BI__builtin_amo_ldat:
355 case PPC::BI__builtin_amo_lwat_s:
356 case PPC::BI__builtin_amo_ldat_s: {
357 llvm::APSInt Result;
358 if (SemaRef.BuiltinConstantArg(TheCall, 2, Result))
359 return true;
360 unsigned Val = Result.getZExtValue();
361
362 bool IsUnsigned = (BuiltinID == PPC::BI__builtin_amo_lwat ||
363 BuiltinID == PPC::BI__builtin_amo_ldat);
364
365 bool IsValid = IsUnsigned
366 ? llvm::is_contained({0u, 1u, 2u, 3u, 4u, 6u, 8u}, Val)
367 : llvm::is_contained({0u, 5u, 7u, 8u}, Val);
368
369 if (IsValid)
370 return false;
371
372 Expr *Arg = TheCall->getArg(2);
373 return SemaRef.Diag(Arg->getBeginLoc(), diag::err_argument_invalid_range)
374 << toString(Result, 10) << (IsUnsigned ? "0-4, 6" : "0, 5, 7") << "8"
375 << Arg->getSourceRange();
376 }
377 case PPC::BI__builtin_amo_lwat_cond:
378 case PPC::BI__builtin_amo_ldat_cond:
379 case PPC::BI__builtin_amo_lwat_cond_s:
380 case PPC::BI__builtin_amo_ldat_cond_s: {
381 llvm::APSInt Result;
382 if (SemaRef.BuiltinConstantArg(TheCall, 1, Result))
383 return true;
384 unsigned Val = Result.getZExtValue();
385 if (llvm::is_contained({24u, 25u, 28u}, Val))
386 return false;
387
388 Expr *Arg = TheCall->getArg(1);
389 return SemaRef.Diag(Arg->getBeginLoc(), diag::err_argument_invalid_range)
390 << toString(Result, 10) << "24, 25" << "28" << Arg->getSourceRange();
391 }
392 case PPC::BI__builtin_amo_stwat:
393 case PPC::BI__builtin_amo_stdat:
394 case PPC::BI__builtin_amo_stwat_s:
395 case PPC::BI__builtin_amo_stdat_s: {
396 llvm::APSInt Result;
397 if (SemaRef.BuiltinConstantArg(TheCall, 2, Result))
398 return true;
399 unsigned Val = Result.getZExtValue();
400
401 bool IsUnsigned = (BuiltinID == PPC::BI__builtin_amo_stwat ||
402 BuiltinID == PPC::BI__builtin_amo_stdat);
403
404 bool IsValid = IsUnsigned
405 ? llvm::is_contained({0u, 1u, 2u, 3u, 4u, 6u, 24u}, Val)
406 : llvm::is_contained({0u, 5u, 7u, 24u}, Val);
407
408 if (IsValid)
409 return false;
410
411 Expr *Arg = TheCall->getArg(2);
412 return SemaRef.Diag(Arg->getBeginLoc(), diag::err_argument_invalid_range)
413 << toString(Result, 10) << (IsUnsigned ? "0-4, 6" : "0, 5, 7")
414 << "24" << Arg->getSourceRange();
415 }
416 }
417 llvm_unreachable("must return from switch");
418}
419
420// Check if the given type is a non-pointer PPC MMA type. This function is used
421// in Sema to prevent invalid uses of restricted PPC MMA types.
423 ASTContext &Context = getASTContext();
424 if (Type->isPointerType() || Type->isArrayType())
425 return false;
426
427 QualType CoreType = Type.getCanonicalType().getUnqualifiedType();
428#define PPC_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty
429 if (false
430#include "clang/Basic/PPCTypes.def"
431 ) {
432 Diag(TypeLoc, diag::err_ppc_invalid_use_mma_type);
433 return true;
434 }
435 return false;
436}
437
438/// DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str,
439/// advancing the pointer over the consumed characters. The decoded type is
440/// returned. If the decoded type represents a constant integer with a
441/// constraint on its value then Mask is set to that value. The type descriptors
442/// used in Str are specific to PPC MMA builtins and are documented in the file
443/// defining the PPC builtins.
444static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str,
445 unsigned &Mask) {
446 bool RequireICE = false;
448 switch (*Str++) {
449 case 'V':
450 return Context.getVectorType(Context.UnsignedCharTy, 16,
452 case 'i': {
453 char *End;
454 unsigned size = strtoul(Str, &End, 10);
455 assert(End != Str && "Missing constant parameter constraint");
456 Str = End;
457 Mask = size;
458 return Context.IntTy;
459 }
460 case 'W': {
461 char *End;
462 unsigned size = strtoul(Str, &End, 10);
463 assert(End != Str && "Missing PowerPC MMA type size");
464 Str = End;
466 switch (size) {
467#define PPC_VECTOR_TYPE(typeName, Id, size) \
468 case size: \
469 Type = Context.Id##Ty; \
470 break;
471#include "clang/Basic/PPCTypes.def"
472 default:
473 llvm_unreachable("Invalid PowerPC MMA vector type");
474 }
475 bool CheckVectorArgs = false;
476 while (!CheckVectorArgs) {
477 switch (*Str++) {
478 case '*':
479 Type = Context.getPointerType(Type);
480 break;
481 case 'C':
482 Type = Type.withConst();
483 break;
484 default:
485 CheckVectorArgs = true;
486 --Str;
487 break;
488 }
489 }
490 return Type;
491 }
492 default:
493 return Context.DecodeTypeStr(--Str, Context, Error, RequireICE, true);
494 }
495}
496
497bool SemaPPC::BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
498 const char *TypeStr) {
499
500 assert((TypeStr[0] != '\0') &&
501 "Invalid types in PPC MMA builtin declaration");
502
503 ASTContext &Context = getASTContext();
504 unsigned Mask = 0;
505 unsigned ArgNum = 0;
506
507 // The first type in TypeStr is the type of the value returned by the
508 // builtin. So we first read that type and change the type of TheCall.
509 QualType type = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
510 TheCall->setType(type);
511
512 while (*TypeStr != '\0') {
513 Mask = 0;
514 QualType ExpectedType = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
515 if (ArgNum >= TheCall->getNumArgs()) {
516 ArgNum++;
517 break;
518 }
519
520 Expr *Arg = TheCall->getArg(ArgNum);
521 QualType PassedType = Arg->getType();
522 QualType StrippedRVType = PassedType.getCanonicalType();
523
524 // Strip Restrict/Volatile qualifiers.
525 if (StrippedRVType.isRestrictQualified() ||
526 StrippedRVType.isVolatileQualified())
527 StrippedRVType = StrippedRVType.getCanonicalType().getUnqualifiedType();
528
529 // The only case where the argument type and expected type are allowed to
530 // mismatch is if the argument type is a non-void pointer (or array) and
531 // expected type is a void pointer.
532 if (StrippedRVType != ExpectedType)
533 if (!(ExpectedType->isVoidPointerType() &&
534 (StrippedRVType->isPointerType() || StrippedRVType->isArrayType())))
535 return Diag(Arg->getBeginLoc(),
536 diag::err_typecheck_convert_incompatible)
537 << PassedType << ExpectedType << 1 << 0 << 0;
538
539 // If the value of the Mask is not 0, we have a constraint in the size of
540 // the integer argument so here we ensure the argument is a constant that
541 // is in the valid range.
542 if (Mask != 0 &&
543 SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, Mask, true))
544 return true;
545
546 ArgNum++;
547 }
548
549 // In case we exited early from the previous loop, there are other types to
550 // read from TypeStr. So we need to read them all to ensure we have the right
551 // number of arguments in TheCall and if it is not the case, to display a
552 // better error message.
553 while (*TypeStr != '\0') {
554 (void)DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
555 ArgNum++;
556 }
557 if (SemaRef.checkArgCount(TheCall, ArgNum))
558 return true;
559
560 return false;
561}
562
564 unsigned ExpectedNumArgs = 3;
565 if (SemaRef.checkArgCount(TheCall, ExpectedNumArgs))
566 return true;
567
568 // Check the third argument is a compile time constant
569 if (!TheCall->getArg(2)->isIntegerConstantExpr(getASTContext()))
570 return Diag(TheCall->getBeginLoc(),
571 diag::err_vsx_builtin_nonconstant_argument)
572 << 3 /* argument index */ << TheCall->getDirectCallee()
573 << SourceRange(TheCall->getArg(2)->getBeginLoc(),
574 TheCall->getArg(2)->getEndLoc());
575
576 QualType Arg1Ty = TheCall->getArg(0)->getType();
577 QualType Arg2Ty = TheCall->getArg(1)->getType();
578
579 // Check the type of argument 1 and argument 2 are vectors.
580 SourceLocation BuiltinLoc = TheCall->getBeginLoc();
581 if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
582 (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
583 return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
584 << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
585 << SourceRange(TheCall->getArg(0)->getBeginLoc(),
586 TheCall->getArg(1)->getEndLoc());
587 }
588
589 // Check the first two arguments are the same type.
590 if (!getASTContext().hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {
591 return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
592 << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
593 << SourceRange(TheCall->getArg(0)->getBeginLoc(),
594 TheCall->getArg(1)->getEndLoc());
595 }
596
597 // When default clang type checking is turned off and the customized type
598 // checking is used, the returning type of the function must be explicitly
599 // set. Otherwise it is _Bool by default.
600 TheCall->setType(Arg1Ty);
601
602 return false;
603}
604
608 SourceLocation AttrLoc) {
609 using namespace DiagAttrParams;
610
611 assert(Params.size() == Locs.size() &&
612 "Mismatch between number of string parameters and locations");
613
615 bool HasDefault = false;
616 bool HasComma = false;
617 bool HasNegativeDisablableFeature = false;
618 StringRef DisablableFeatureName;
619 for (unsigned I = 0, E = Params.size(); I < E; ++I) {
620 const StringRef Param = Params[I].trim();
621 const SourceLocation &Loc = Locs[I];
622
623 if (Param.empty() || Param.ends_with(','))
624 return Diag(Loc, diag::warn_unsupported_target_attribute)
625 << Unsupported << None << "" << TargetClones;
626
627 if (Param.contains(','))
628 HasComma = true;
629
630 StringRef LHS;
631 StringRef RHS = Param;
632 do {
633 std::tie(LHS, RHS) = RHS.split(',');
634 LHS = LHS.trim();
635 const SourceLocation &CurLoc =
636 Loc.getLocWithOffset(LHS.data() - Param.data());
637
638 if (LHS.empty())
639 return Diag(CurLoc, diag::warn_unsupported_target_attribute)
640 << Unsupported << None << "" << TargetClones;
641
642 if (LHS.starts_with("cpu=")) {
643 StringRef CPUStr = LHS.drop_front(sizeof("cpu=") - 1);
644 if (!TargetInfo.isValidCPUName(CPUStr))
645 return Diag(CurLoc, diag::warn_unsupported_target_attribute)
646 << Unknown << CPU << CPUStr << TargetClones;
647 else if (!TargetInfo.validateCpuIs(CPUStr))
648 return Diag(CurLoc, diag::warn_unsupported_target_attribute)
649 << Unsupported << CPU << CPUStr << TargetClones;
650 } else if (LHS == "default") {
651 HasDefault = true;
652 } else {
653 bool IsNegated = LHS.starts_with("no-");
654 StringRef FeatureName = IsNegated ? LHS.drop_front(3) : LHS;
655 if (!TargetInfo.isValidClonesFeatureName(FeatureName))
656 return Diag(CurLoc, diag::err_ppc_feature_no_runtime_detection)
657 << FeatureName;
658 // All target_clones feature names must be valid target feature names.
659 assert(TargetInfo.isValidFeatureName(FeatureName));
660
661 if (llvm::PPC::canDisableFeatureOnAIX(FeatureName)) {
662 if (IsNegated) {
663 // Only one negative target-feature that can be disabled.
664 if (HasNegativeDisablableFeature) {
665 return Diag(CurLoc, diag::err_ppc_multiple_negative_disableable)
666 << LHS << DisablableFeatureName;
667 }
668 HasNegativeDisablableFeature = true;
669 DisablableFeatureName = LHS;
670 }
671 // Positive disableable features are always allowed.
672 }
673 // Non-disableable features (positive or negative) are always allowed.
674 }
675 SmallString<64> CPU;
676 if (LHS.starts_with("cpu=")) {
677 CPU.append("cpu=");
678 CPU.append(
679 llvm::PPC::normalizeCPUName(LHS.drop_front(sizeof("cpu=") - 1)));
680 LHS = CPU.str();
681 }
682 if (llvm::is_contained(NewParams, LHS)) {
683 Diag(CurLoc, diag::warn_target_clone_duplicate_options);
684 continue;
685 }
686 NewParams.push_back(LHS);
687 } while (!RHS.empty());
688 }
689 if (HasComma && Params.size() > 1)
690 Diag(Locs[0], diag::warn_target_clone_mixed_values);
691
692 if (!HasDefault)
693 return Diag(AttrLoc, diag::err_target_clone_must_have_default);
694
695 return false;
696}
697} // namespace clang
Defines the clang::ASTContext interface.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
This file declares semantic analysis functions specific to PowerPC.
Defines the clang::SourceLocation class and associated facilities.
Enumerates target-specific builtins in their own namespaces within namespace clang.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:239
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:965
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
@ GE_None
No error.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3191
SourceLocation getBeginLoc() const
Definition Expr.h:3321
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3170
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3178
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
The name of a declaration.
This represents one expression.
Definition Expr.h:113
bool isIntegerConstantExpr(const ASTContext &Ctx) const
void setType(QualType t)
Definition Expr.h:146
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3119
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition Expr.h:145
Represents a member of a struct/union/class.
Definition Decl.h:3295
Represents a function declaration or definition.
Definition Decl.h:2059
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:341
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8512
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
Definition TypeBase.h:8506
QualType getCanonicalType() const
Definition TypeBase.h:8480
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8522
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
bool checkTargetClonesAttr(const SmallVectorImpl< StringRef > &Params, const SmallVectorImpl< SourceLocation > &Locs, SmallVectorImpl< SmallString< 64 > > &NewParams, SourceLocation AttrLoc)
Definition SemaPPC.cpp:605
bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaPPC.cpp:113
void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg)
Definition SemaPPC.cpp:32
SemaPPC(Sema &S)
Definition SemaPPC.cpp:30
bool BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID, const char *TypeDesc)
BuiltinPPCMMACall - Check the call to a PPC MMA builtin for validity.
Definition SemaPPC.cpp:497
bool BuiltinVSX(CallExpr *TheCall)
Definition SemaPPC.cpp:563
bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc)
Definition SemaPPC.cpp:422
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:863
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
A trivial tuple used to represent a source range.
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
Exposes information about the current target.
Definition TargetInfo.h:226
virtual bool validateCpuIs(StringRef Name) const
virtual bool isValidClonesFeatureName(StringRef Feature) const
Does this TargetInfo support the given feature on target_clones?
unsigned getTypeWidth(IntType T) const
Return the width (in bits) of the specified integer type enum.
IntType getIntPtrType() const
Definition TargetInfo.h:420
const llvm::fltSemantics & getLongDoubleFormat() const
Definition TargetInfo.h:803
virtual bool isValidFeatureName(StringRef Feature) const
Determine whether this TargetInfo supports the given feature.
virtual bool isValidCPUName(StringRef Name) const
Determine whether this TargetInfo supports the given CPU name.
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isArrayType() const
Definition TypeBase.h:8764
bool isPointerType() const
Definition TypeBase.h:8665
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9081
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2859
bool isVectorType() const
Definition TypeBase.h:8804
Defines the clang::TargetInfo interface.
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
Enums for the diagnostics of target, target_version and target_clones.
Definition Sema.h:849
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
Top level wrappers for InstallAPI frontend operations.
static bool isPPC_64Builtin(unsigned BuiltinID)
Definition SemaPPC.cpp:58
@ Result
The result type of a method or function.
Definition TypeBase.h:906
llvm::Expected< QualType > ExpectedType
static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str, unsigned &Mask)
DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str, advancing the pointer ov...
Definition SemaPPC.cpp:444
@ AltiVecVector
is AltiVec vector
Definition TypeBase.h:4230
@ None
The alignment was not explicit in code.
Definition ASTContext.h:176