clang 22.0.0git
SemaARM.cpp
Go to the documentation of this file.
1//===------ SemaARM.cpp ---------- ARM 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 ARM.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Sema/SemaARM.h"
19#include "clang/Sema/Sema.h"
20
21namespace clang {
22
24
25/// BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions
27 CallExpr *TheCall) {
28 ASTContext &Context = getASTContext();
29
30 if (BuiltinID == AArch64::BI__builtin_arm_irg) {
31 if (SemaRef.checkArgCount(TheCall, 2))
32 return true;
33 Expr *Arg0 = TheCall->getArg(0);
34 Expr *Arg1 = TheCall->getArg(1);
35
37 if (FirstArg.isInvalid())
38 return true;
39 QualType FirstArgType = FirstArg.get()->getType();
40 if (!FirstArgType->isAnyPointerType())
41 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
42 << "first" << FirstArgType << Arg0->getSourceRange();
43 TheCall->setArg(0, FirstArg.get());
44
46 if (SecArg.isInvalid())
47 return true;
48 QualType SecArgType = SecArg.get()->getType();
49 if (!SecArgType->isIntegerType())
50 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
51 << "second" << SecArgType << Arg1->getSourceRange();
52
53 // Derive the return type from the pointer argument.
54 TheCall->setType(FirstArgType);
55 return false;
56 }
57
58 if (BuiltinID == AArch64::BI__builtin_arm_addg) {
59 if (SemaRef.checkArgCount(TheCall, 2))
60 return true;
61
62 Expr *Arg0 = TheCall->getArg(0);
64 if (FirstArg.isInvalid())
65 return true;
66 QualType FirstArgType = FirstArg.get()->getType();
67 if (!FirstArgType->isAnyPointerType())
68 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
69 << "first" << FirstArgType << Arg0->getSourceRange();
70 TheCall->setArg(0, FirstArg.get());
71
72 // Derive the return type from the pointer argument.
73 TheCall->setType(FirstArgType);
74
75 // Second arg must be an constant in range [0,15]
76 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
77 }
78
79 if (BuiltinID == AArch64::BI__builtin_arm_gmi) {
80 if (SemaRef.checkArgCount(TheCall, 2))
81 return true;
82 Expr *Arg0 = TheCall->getArg(0);
83 Expr *Arg1 = TheCall->getArg(1);
84
86 if (FirstArg.isInvalid())
87 return true;
88 QualType FirstArgType = FirstArg.get()->getType();
89 if (!FirstArgType->isAnyPointerType())
90 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
91 << "first" << FirstArgType << Arg0->getSourceRange();
92
93 QualType SecArgType = Arg1->getType();
94 if (!SecArgType->isIntegerType())
95 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
96 << "second" << SecArgType << Arg1->getSourceRange();
97 TheCall->setType(Context.IntTy);
98 return false;
99 }
100
101 if (BuiltinID == AArch64::BI__builtin_arm_ldg ||
102 BuiltinID == AArch64::BI__builtin_arm_stg) {
103 if (SemaRef.checkArgCount(TheCall, 1))
104 return true;
105 Expr *Arg0 = TheCall->getArg(0);
107 if (FirstArg.isInvalid())
108 return true;
109
110 QualType FirstArgType = FirstArg.get()->getType();
111 if (!FirstArgType->isAnyPointerType())
112 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
113 << "first" << FirstArgType << Arg0->getSourceRange();
114 TheCall->setArg(0, FirstArg.get());
115
116 // Derive the return type from the pointer argument.
117 if (BuiltinID == AArch64::BI__builtin_arm_ldg)
118 TheCall->setType(FirstArgType);
119 return false;
120 }
121
122 if (BuiltinID == AArch64::BI__builtin_arm_subp) {
123 Expr *ArgA = TheCall->getArg(0);
124 Expr *ArgB = TheCall->getArg(1);
125
128
129 if (ArgExprA.isInvalid() || ArgExprB.isInvalid())
130 return true;
131
132 QualType ArgTypeA = ArgExprA.get()->getType();
133 QualType ArgTypeB = ArgExprB.get()->getType();
134
135 auto isNull = [&](Expr *E) -> bool {
136 return E->isNullPointerConstant(Context,
138 };
139
140 // argument should be either a pointer or null
141 if (!ArgTypeA->isAnyPointerType() && !isNull(ArgA))
142 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
143 << "first" << ArgTypeA << ArgA->getSourceRange();
144
145 if (!ArgTypeB->isAnyPointerType() && !isNull(ArgB))
146 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
147 << "second" << ArgTypeB << ArgB->getSourceRange();
148
149 // Ensure Pointee types are compatible
150 if (ArgTypeA->isAnyPointerType() && !isNull(ArgA) &&
151 ArgTypeB->isAnyPointerType() && !isNull(ArgB)) {
152 QualType pointeeA = ArgTypeA->getPointeeType();
153 QualType pointeeB = ArgTypeB->getPointeeType();
154 if (!Context.typesAreCompatible(
155 Context.getCanonicalType(pointeeA).getUnqualifiedType(),
156 Context.getCanonicalType(pointeeB).getUnqualifiedType())) {
157 return Diag(TheCall->getBeginLoc(),
158 diag::err_typecheck_sub_ptr_compatible)
159 << ArgTypeA << ArgTypeB << ArgA->getSourceRange()
160 << ArgB->getSourceRange();
161 }
162 }
163
164 // at least one argument should be pointer type
165 if (!ArgTypeA->isAnyPointerType() && !ArgTypeB->isAnyPointerType())
166 return Diag(TheCall->getBeginLoc(), diag::err_memtag_any2arg_pointer)
167 << ArgTypeA << ArgTypeB << ArgA->getSourceRange();
168
169 if (isNull(ArgA)) // adopt type of the other pointer
170 ArgExprA =
171 SemaRef.ImpCastExprToType(ArgExprA.get(), ArgTypeB, CK_NullToPointer);
172
173 if (isNull(ArgB))
174 ArgExprB =
175 SemaRef.ImpCastExprToType(ArgExprB.get(), ArgTypeA, CK_NullToPointer);
176
177 TheCall->setArg(0, ArgExprA.get());
178 TheCall->setArg(1, ArgExprB.get());
179 TheCall->setType(Context.LongLongTy);
180 return false;
181 }
182 assert(false && "Unhandled ARM MTE intrinsic");
183 return true;
184}
185
186/// BuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr
187/// TheCall is an ARM/AArch64 special register string literal.
188bool SemaARM::BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
189 int ArgNum, unsigned ExpectedFieldNum,
190 bool AllowName) {
191 bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
192 BuiltinID == ARM::BI__builtin_arm_wsr64 ||
193 BuiltinID == ARM::BI__builtin_arm_rsr ||
194 BuiltinID == ARM::BI__builtin_arm_rsrp ||
195 BuiltinID == ARM::BI__builtin_arm_wsr ||
196 BuiltinID == ARM::BI__builtin_arm_wsrp;
197 bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
198 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
199 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
200 BuiltinID == AArch64::BI__builtin_arm_wsr128 ||
201 BuiltinID == AArch64::BI__builtin_arm_rsr ||
202 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
203 BuiltinID == AArch64::BI__builtin_arm_wsr ||
204 BuiltinID == AArch64::BI__builtin_arm_wsrp;
205 assert((IsARMBuiltin || IsAArch64Builtin) && "Unexpected ARM builtin.");
206
207 // We can't check the value of a dependent argument.
208 Expr *Arg = TheCall->getArg(ArgNum);
209 if (Arg->isTypeDependent() || Arg->isValueDependent())
210 return false;
211
212 // Check if the argument is a string literal.
213 if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
214 return Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
215 << Arg->getSourceRange();
216
217 // Check the type of special register given.
218 StringRef Reg = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
220 Reg.split(Fields, ":");
221
222 if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
223 return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
224 << Arg->getSourceRange();
225
226 // If the string is the name of a register then we cannot check that it is
227 // valid here but if the string is of one the forms described in ACLE then we
228 // can check that the supplied fields are integers and within the valid
229 // ranges.
230 if (Fields.size() > 1) {
231 bool FiveFields = Fields.size() == 5;
232
233 bool ValidString = true;
234 if (IsARMBuiltin) {
235 ValidString &= Fields[0].starts_with_insensitive("cp") ||
236 Fields[0].starts_with_insensitive("p");
237 if (ValidString)
238 Fields[0] = Fields[0].drop_front(
239 Fields[0].starts_with_insensitive("cp") ? 2 : 1);
240
241 ValidString &= Fields[2].starts_with_insensitive("c");
242 if (ValidString)
243 Fields[2] = Fields[2].drop_front(1);
244
245 if (FiveFields) {
246 ValidString &= Fields[3].starts_with_insensitive("c");
247 if (ValidString)
248 Fields[3] = Fields[3].drop_front(1);
249 }
250 }
251
252 SmallVector<int, 5> FieldBitWidths;
253 if (FiveFields)
254 FieldBitWidths.append({IsAArch64Builtin ? 2 : 4, 3, 4, 4, 3});
255 else
256 FieldBitWidths.append({4, 3, 4});
257
258 for (unsigned i = 0; i < Fields.size(); ++i) {
259 int IntField;
260 ValidString &= !Fields[i].getAsInteger(10, IntField);
261 ValidString &= (IntField >= 0 && IntField < (1 << FieldBitWidths[i]));
262 }
263
264 if (!ValidString)
265 return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
266 << Arg->getSourceRange();
267 } else if (IsAArch64Builtin && Fields.size() == 1) {
268 // This code validates writes to PSTATE registers.
269
270 // Not a write.
271 if (TheCall->getNumArgs() != 2)
272 return false;
273
274 // The 128-bit system register accesses do not touch PSTATE.
275 if (BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
276 BuiltinID == AArch64::BI__builtin_arm_wsr128)
277 return false;
278
279 // These are the named PSTATE accesses using "MSR (immediate)" instructions,
280 // along with the upper limit on the immediates allowed.
281 auto MaxLimit = llvm::StringSwitch<std::optional<unsigned>>(Reg)
282 .CaseLower("spsel", 15)
283 .CaseLower("daifclr", 15)
284 .CaseLower("daifset", 15)
285 .CaseLower("pan", 15)
286 .CaseLower("uao", 15)
287 .CaseLower("dit", 15)
288 .CaseLower("ssbs", 15)
289 .CaseLower("tco", 15)
290 .CaseLower("allint", 1)
291 .CaseLower("pm", 1)
292 .Default(std::nullopt);
293
294 // If this is not a named PSTATE, just continue without validating, as this
295 // will be lowered to an "MSR (register)" instruction directly
296 if (!MaxLimit)
297 return false;
298
299 // Here we only allow constants in the range for that pstate, as required by
300 // the ACLE.
301 //
302 // While clang also accepts the names of system registers in its ACLE
303 // intrinsics, we prevent this with the PSTATE names used in MSR (immediate)
304 // as the value written via a register is different to the value used as an
305 // immediate to have the same effect. e.g., for the instruction `msr tco,
306 // x0`, it is bit 25 of register x0 that is written into PSTATE.TCO, but
307 // with `msr tco, #imm`, it is bit 0 of xN that is written into PSTATE.TCO.
308 //
309 // If a programmer wants to codegen the MSR (register) form of `msr tco,
310 // xN`, they can still do so by specifying the register using five
311 // colon-separated numbers in a string.
312 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit);
313 }
314
315 return false;
316}
317
318/// getNeonEltType - Return the QualType corresponding to the elements of
319/// the vector type specified by the NeonTypeFlags. This is used to check
320/// the pointer arguments for Neon load/store intrinsics.
322 bool IsPolyUnsigned, bool IsInt64Long) {
323 switch (Flags.getEltType()) {
325 return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
327 return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
329 return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
331 if (IsInt64Long)
332 return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
333 else
334 return Flags.isUnsigned() ? Context.UnsignedLongLongTy
335 : Context.LongLongTy;
337 return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
339 return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
341 if (IsInt64Long)
342 return Context.UnsignedLongTy;
343 else
344 return Context.UnsignedLongLongTy;
346 break;
348 return Context.HalfTy;
350 return Context.FloatTy;
352 return Context.DoubleTy;
354 return Context.BFloat16Ty;
356 return Context.MFloat8Ty;
357 }
358 llvm_unreachable("Invalid NeonTypeFlag!");
359}
360
361enum ArmSMEState : unsigned {
363
364 ArmInZA = 0b01,
365 ArmOutZA = 0b10,
367 ArmZAMask = 0b11,
368
369 ArmInZT0 = 0b01 << 2,
370 ArmOutZT0 = 0b10 << 2,
371 ArmInOutZT0 = 0b11 << 2,
372 ArmZT0Mask = 0b11 << 2
374
375bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy,
376 unsigned ArgIdx, unsigned EltBitWidth,
377 unsigned ContainerBitWidth) {
378 // Function that checks whether the operand (ArgIdx) is an immediate
379 // that is one of a given set of values.
380 auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set,
381 int ErrDiag) -> bool {
382 // We can't check the value of a dependent argument.
383 Expr *Arg = TheCall->getArg(ArgIdx);
384 if (Arg->isTypeDependent() || Arg->isValueDependent())
385 return false;
386
387 // Check constant-ness first.
388 llvm::APSInt Imm;
389 if (SemaRef.BuiltinConstantArg(TheCall, ArgIdx, Imm))
390 return true;
391
392 if (!llvm::is_contained(Set, Imm.getSExtValue()))
393 return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
394 return false;
395 };
396
397 switch ((ImmCheckType)CheckTy) {
398 case ImmCheckType::ImmCheck0_31:
399 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 31))
400 return true;
401 break;
402 case ImmCheckType::ImmCheck0_13:
403 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 13))
404 return true;
405 break;
406 case ImmCheckType::ImmCheck0_63:
407 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63))
408 return true;
409 break;
410 case ImmCheckType::ImmCheck1_16:
411 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16))
412 return true;
413 break;
414 case ImmCheckType::ImmCheck0_7:
415 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7))
416 return true;
417 break;
418 case ImmCheckType::ImmCheck1_1:
419 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 1))
420 return true;
421 break;
422 case ImmCheckType::ImmCheck1_3:
423 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 3))
424 return true;
425 break;
426 case ImmCheckType::ImmCheck1_7:
427 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 7))
428 return true;
429 break;
430 case ImmCheckType::ImmCheckExtract:
431 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
432 (2048 / EltBitWidth) - 1))
433 return true;
434 break;
435 case ImmCheckType::ImmCheckCvt:
436 case ImmCheckType::ImmCheckShiftRight:
437 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth))
438 return true;
439 break;
440 case ImmCheckType::ImmCheckShiftRightNarrow:
441 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth / 2))
442 return true;
443 break;
444 case ImmCheckType::ImmCheckShiftLeft:
445 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1))
446 return true;
447 break;
448 case ImmCheckType::ImmCheckLaneIndex:
449 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
450 (ContainerBitWidth / EltBitWidth) - 1))
451 return true;
452 break;
453 case ImmCheckType::ImmCheckLaneIndexCompRotate:
455 TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1))
456 return true;
457 break;
458 case ImmCheckType::ImmCheckLaneIndexDot:
460 TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1))
461 return true;
462 break;
463 case ImmCheckType::ImmCheckComplexRot90_270:
464 if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd))
465 return true;
466 break;
467 case ImmCheckType::ImmCheckComplexRotAll90:
468 if (CheckImmediateInSet({0, 90, 180, 270},
469 diag::err_rotation_argument_to_cmla))
470 return true;
471 break;
472 case ImmCheckType::ImmCheck0_1:
473 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 1))
474 return true;
475 break;
476 case ImmCheckType::ImmCheck0_2:
477 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 2))
478 return true;
479 break;
480 case ImmCheckType::ImmCheck0_3:
481 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3))
482 return true;
483 break;
484 case ImmCheckType::ImmCheck0_0:
485 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 0))
486 return true;
487 break;
488 case ImmCheckType::ImmCheck0_15:
489 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 15))
490 return true;
491 break;
492 case ImmCheckType::ImmCheck0_255:
493 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 255))
494 return true;
495 break;
496 case ImmCheckType::ImmCheck1_32:
497 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32))
498 return true;
499 break;
500 case ImmCheckType::ImmCheck1_64:
501 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64))
502 return true;
503 break;
504 case ImmCheckType::ImmCheck2_4_Mul2:
505 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 2, 4) ||
506 SemaRef.BuiltinConstantArgMultiple(TheCall, ArgIdx, 2))
507 return true;
508 break;
509 }
510 return false;
511}
512
514 CallExpr *TheCall,
515 SmallVectorImpl<std::tuple<int, int, int, int>> &ImmChecks,
516 int OverloadType) {
517 bool HasError = false;
518
519 for (const auto &I : ImmChecks) {
520 auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I;
521
522 if (OverloadType >= 0)
523 ElementBitWidth = NeonTypeFlags(OverloadType).getEltSizeInBits();
524
525 HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth,
526 VecBitWidth);
527 }
528
529 return HasError;
530}
531
533 CallExpr *TheCall, SmallVectorImpl<std::tuple<int, int, int>> &ImmChecks) {
534 bool HasError = false;
535
536 for (const auto &I : ImmChecks) {
537 auto [ArgIdx, CheckTy, ElementBitWidth] = I;
538 HasError |=
539 CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 128);
540 }
541
542 return HasError;
543}
544
546 if (FD->hasAttr<ArmLocallyStreamingAttr>())
548 if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
549 if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
550 if (FPT->getAArch64SMEAttributes() &
553 if (FPT->getAArch64SMEAttributes() &
556 }
557 }
559}
560
561static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
562 const FunctionDecl *FD,
564 unsigned BuiltinID) {
566
567 // Check if the intrinsic is available in the right mode, i.e.
568 // * When compiling for SME only, the caller must be in streaming mode.
569 // * When compiling for SVE only, the caller must be in non-streaming mode.
570 // * When compiling for both SVE and SME, the caller can be in either mode.
572 llvm::StringMap<bool> CallerFeatures;
573 S.Context.getFunctionFeatureMap(CallerFeatures, FD);
574
575 // Avoid emitting diagnostics for a function that can never compile.
576 if (FnType == SemaARM::ArmStreaming && !CallerFeatures["sme"])
577 return false;
578
579 const auto FindTopLevelPipe = [](const char *S) {
580 unsigned Depth = 0;
581 unsigned I = 0, E = strlen(S);
582 for (; I < E; ++I) {
583 if (S[I] == '|' && Depth == 0)
584 break;
585 if (S[I] == '(')
586 ++Depth;
587 else if (S[I] == ')')
588 --Depth;
589 }
590 return I;
591 };
592
593 const char *RequiredFeatures =
595 unsigned PipeIdx = FindTopLevelPipe(RequiredFeatures);
596 assert(PipeIdx != 0 && PipeIdx != strlen(RequiredFeatures) &&
597 "Expected feature string of the form 'SVE-EXPR|SME-EXPR'");
598 StringRef NonStreamingBuiltinGuard = StringRef(RequiredFeatures, PipeIdx);
599 StringRef StreamingBuiltinGuard = StringRef(RequiredFeatures + PipeIdx + 1);
600
601 bool SatisfiesSVE = Builtin::evaluateRequiredTargetFeatures(
602 NonStreamingBuiltinGuard, CallerFeatures);
603 bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures(
604 StreamingBuiltinGuard, CallerFeatures);
605
606 if ((SatisfiesSVE && SatisfiesSME) ||
607 (SatisfiesSVE && FnType == SemaARM::ArmStreamingCompatible))
608 return false;
609 else if (SatisfiesSVE)
611 else if (SatisfiesSME)
613 else
614 // This should be diagnosed by CodeGen
615 return false;
616 }
617
618 if (FnType != SemaARM::ArmNonStreaming &&
620 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
621 << TheCall->getSourceRange() << "non-streaming";
622 else if (FnType != SemaARM::ArmStreaming &&
624 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
625 << TheCall->getSourceRange() << "streaming";
626 else
627 return false;
628
629 return true;
630}
631
632static ArmSMEState getSMEState(unsigned BuiltinID) {
633 switch (BuiltinID) {
634 default:
635 return ArmNoState;
636#define GET_SME_BUILTIN_GET_STATE
637#include "clang/Basic/arm_sme_builtins_za_state.inc"
638#undef GET_SME_BUILTIN_GET_STATE
639 }
640}
641
643 CallExpr *TheCall) {
644 if (const FunctionDecl *FD =
645 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
646 std::optional<ArmStreamingType> BuiltinType;
647
648 switch (BuiltinID) {
649#define GET_SME_STREAMING_ATTRS
650#include "clang/Basic/arm_sme_streaming_attrs.inc"
651#undef GET_SME_STREAMING_ATTRS
652 }
653
654 if (BuiltinType &&
655 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
656 return true;
657
658 if ((getSMEState(BuiltinID) & ArmZAMask) && !hasArmZAState(FD))
659 Diag(TheCall->getBeginLoc(),
660 diag::warn_attribute_arm_za_builtin_no_za_state)
661 << TheCall->getSourceRange();
662
663 if ((getSMEState(BuiltinID) & ArmZT0Mask) && !hasArmZT0State(FD))
664 Diag(TheCall->getBeginLoc(),
665 diag::warn_attribute_arm_zt0_builtin_no_zt0_state)
666 << TheCall->getSourceRange();
667 }
668
669 // Range check SME intrinsics that take immediate values.
671
672 switch (BuiltinID) {
673 default:
674 return false;
675#define GET_SME_IMMEDIATE_CHECK
676#include "clang/Basic/arm_sme_sema_rangechecks.inc"
677#undef GET_SME_IMMEDIATE_CHECK
678 }
679
680 return PerformSVEImmChecks(TheCall, ImmChecks);
681}
682
684 CallExpr *TheCall) {
685 if (const FunctionDecl *FD =
686 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
687 std::optional<ArmStreamingType> BuiltinType;
688
689 switch (BuiltinID) {
690#define GET_SVE_STREAMING_ATTRS
691#include "clang/Basic/arm_sve_streaming_attrs.inc"
692#undef GET_SVE_STREAMING_ATTRS
693 }
694 if (BuiltinType &&
695 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
696 return true;
697 }
698 // Range check SVE intrinsics that take immediate values.
700
701 switch (BuiltinID) {
702 default:
703 return false;
704#define GET_SVE_IMMEDIATE_CHECK
705#include "clang/Basic/arm_sve_sema_rangechecks.inc"
706#undef GET_SVE_IMMEDIATE_CHECK
707 }
708
709 return PerformSVEImmChecks(TheCall, ImmChecks);
710}
711
713 unsigned BuiltinID,
714 CallExpr *TheCall) {
715 if (const FunctionDecl *FD =
716 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
717 std::optional<ArmStreamingType> BuiltinType;
718
719 switch (BuiltinID) {
720 default:
721 break;
722#define GET_NEON_STREAMING_COMPAT_FLAG
723#include "clang/Basic/arm_neon.inc"
724#undef GET_NEON_STREAMING_COMPAT_FLAG
725 }
726 if (BuiltinType &&
727 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
728 return true;
729 }
730
731 llvm::APSInt Result;
732 uint64_t mask = 0;
733 int TV = -1;
734 int PtrArgNum = -1;
735 bool HasConstPtr = false;
736 switch (BuiltinID) {
737#define GET_NEON_OVERLOAD_CHECK
738#include "clang/Basic/arm_fp16.inc"
739#include "clang/Basic/arm_neon.inc"
740#undef GET_NEON_OVERLOAD_CHECK
741 }
742
743 // For NEON intrinsics which are overloaded on vector element type, validate
744 // the immediate which specifies which variant to emit.
745 unsigned ImmArg = TheCall->getNumArgs() - 1;
746 if (mask) {
747 if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result))
748 return true;
749
750 TV = Result.getLimitedValue(64);
751 if ((TV > 63) || (mask & (1ULL << TV)) == 0)
752 return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
753 << TheCall->getArg(ImmArg)->getSourceRange();
754 }
755
756 if (PtrArgNum >= 0) {
757 // Check that pointer arguments have the specified type.
758 Expr *Arg = TheCall->getArg(PtrArgNum);
759 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
760 Arg = ICE->getSubExpr();
762 QualType RHSTy = RHS.get()->getType();
763
764 llvm::Triple::ArchType Arch = TI.getTriple().getArch();
765 bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
766 Arch == llvm::Triple::aarch64_32 ||
767 Arch == llvm::Triple::aarch64_be;
768 bool IsInt64Long = TI.getInt64Type() == TargetInfo::SignedLong;
770 IsPolyUnsigned, IsInt64Long);
771 if (HasConstPtr)
772 EltTy = EltTy.withConst();
773 QualType LHSTy = getASTContext().getPointerType(EltTy);
774 AssignConvertType ConvTy;
775 ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);
776 if (RHS.isInvalid())
777 return true;
778 if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy,
779 RHSTy, RHS.get(),
781 return true;
782 }
783
784 // For NEON intrinsics which take an immediate value as part of the
785 // instruction, range check them here.
787 switch (BuiltinID) {
788 default:
789 return false;
790#define GET_NEON_IMMEDIATE_CHECK
791#include "clang/Basic/arm_fp16.inc"
792#include "clang/Basic/arm_neon.inc"
793#undef GET_NEON_IMMEDIATE_CHECK
794 }
795
796 return PerformNeonImmChecks(TheCall, ImmChecks, TV);
797}
798
800 CallExpr *TheCall) {
801 switch (BuiltinID) {
802 default:
803 return false;
804#include "clang/Basic/arm_mve_builtin_sema.inc"
805 }
806}
807
809 unsigned BuiltinID,
810 CallExpr *TheCall) {
811 bool Err = false;
812 switch (BuiltinID) {
813 default:
814 return false;
815#include "clang/Basic/arm_cde_builtin_sema.inc"
816 }
817
818 if (Err)
819 return true;
820
821 return CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), /*WantCDE*/ true);
822}
823
825 const Expr *CoprocArg,
826 bool WantCDE) {
827 ASTContext &Context = getASTContext();
829 return false;
830
831 // We can't check the value of a dependent argument.
832 if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
833 return false;
834
835 llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context);
836 int64_t CoprocNo = CoprocNoAP.getExtValue();
837 assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
838
839 uint32_t CDECoprocMask = TI.getARMCDECoprocMask();
840 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
841
842 if (IsCDECoproc != WantCDE)
843 return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
844 << (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange();
845
846 return false;
847}
848
850 unsigned BuiltinID,
851 CallExpr *TheCall) {
852 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
853 BuiltinID == ARM::BI__builtin_arm_ldaex ||
854 BuiltinID == ARM::BI__builtin_arm_strex ||
855 BuiltinID == ARM::BI__builtin_arm_stlex ||
856 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
857 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
858 BuiltinID == AArch64::BI__builtin_arm_strex ||
859 BuiltinID == AArch64::BI__builtin_arm_stlex) &&
860 "unexpected ARM builtin");
861 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
862 BuiltinID == ARM::BI__builtin_arm_ldaex ||
863 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
864 BuiltinID == AArch64::BI__builtin_arm_ldaex;
865
866 ASTContext &Context = getASTContext();
867 DeclRefExpr *DRE =
868 cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
869
870 // Ensure that we have the proper number of arguments.
871 if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))
872 return true;
873
874 // Inspect the pointer argument of the atomic builtin. This should always be
875 // a pointer type, whose element is an integral scalar or pointer type.
876 // Because it is a pointer type, we don't have to worry about any implicit
877 // casts here.
878 Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
879 ExprResult PointerArgRes =
881 if (PointerArgRes.isInvalid())
882 return true;
883 PointerArg = PointerArgRes.get();
884
885 const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
886 if (!pointerType) {
887 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
888 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
889 return true;
890 }
891
892 // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next
893 // task is to insert the appropriate casts into the AST. First work out just
894 // what the appropriate type is.
895 QualType ValType = pointerType->getPointeeType();
896 QualType AddrType = ValType.getUnqualifiedType().withVolatile();
897 if (IsLdrex)
898 AddrType.addConst();
899
900 // Issue a warning if the cast is dodgy.
901 CastKind CastNeeded = CK_NoOp;
902 if (!AddrType.isAtLeastAsQualifiedAs(ValType, getASTContext())) {
903 CastNeeded = CK_BitCast;
904 Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
905 << PointerArg->getType() << Context.getPointerType(AddrType)
906 << AssignmentAction::Passing << PointerArg->getSourceRange();
907 }
908
909 // Finally, do the cast and replace the argument with the corrected version.
910 AddrType = Context.getPointerType(AddrType);
911 PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);
912 if (PointerArgRes.isInvalid())
913 return true;
914 PointerArg = PointerArgRes.get();
915
916 TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
917
918 // In general, we allow ints, floats and pointers to be loaded and stored.
919 if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
920 !ValType->isBlockPointerType() && !ValType->isFloatingType()) {
921 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
922 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
923 return true;
924 }
925
926 // Check whether the size of the type can be handled atomically on this
927 // target.
928 if (!TI.getTriple().isAArch64()) {
929 unsigned Mask = TI.getARMLDREXMask();
930 unsigned Bits = Context.getTypeSize(ValType);
931 bool Supported =
932 (llvm::isPowerOf2_64(Bits)) && Bits >= 8 && (Mask & (Bits / 8));
933
934 if (!Supported) {
935 // Emit a diagnostic saying that this size isn't available. If _no_ size
936 // of exclusive access is supported on this target, we emit a diagnostic
937 // with special wording for that case, but otherwise, we emit
938 // err_atomic_exclusive_builtin_pointer_size and loop over `Mask` to
939 // control what subset of sizes it lists as legal.
940 if (Mask) {
941 auto D = Diag(DRE->getBeginLoc(),
942 diag::err_atomic_exclusive_builtin_pointer_size)
943 << PointerArg->getType();
944 bool Started = false;
945 for (unsigned Size = 1; Size <= 8; Size <<= 1) {
946 // For each of the sizes 1,2,4,8, pass two integers into the
947 // diagnostic. The first selects a separator from the previous
948 // number: 0 for no separator at all, 1 for a comma, 2 for " or "
949 // which appears before the final number in a list of more than one.
950 // The second integer just indicates whether we print this size in
951 // the message at all.
952 if (!(Mask & Size)) {
953 // This size isn't one of the supported ones, so emit no separator
954 // text and don't print the size itself.
955 D << 0 << 0;
956 } else {
957 // This size is supported, so print it, and an appropriate
958 // separator.
959 Mask &= ~Size;
960 if (!Started)
961 D << 0; // No separator if this is the first size we've printed
962 else if (Mask)
963 D << 1; // "," if there's still another size to come
964 else
965 D << 2; // " or " if the size we're about to print is the last
966 D << 1; // print the size itself
967 Started = true;
968 }
969 }
970 } else {
971 Diag(DRE->getBeginLoc(),
972 diag::err_atomic_exclusive_builtin_pointer_size_none)
973 << PointerArg->getSourceRange();
974 }
975 }
976 }
977
978 switch (ValType.getObjCLifetime()) {
981 // okay
982 break;
983
987 Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
988 << ValType << PointerArg->getSourceRange();
989 return true;
990 }
991
992 if (IsLdrex) {
993 TheCall->setType(ValType);
994 return false;
995 }
996
997 // Initialize the argument to be stored.
998 ExprResult ValArg = TheCall->getArg(0);
1000 Context, ValType, /*consume*/ false);
1001 ValArg = SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg);
1002 if (ValArg.isInvalid())
1003 return true;
1004 TheCall->setArg(0, ValArg.get());
1005
1006 // __builtin_arm_strex always returns an int. It's marked as such in the .def,
1007 // but the custom checker bypasses all default analysis.
1008 TheCall->setType(Context.IntTy);
1009 return false;
1010}
1011
1013 unsigned BuiltinID,
1014 CallExpr *TheCall) {
1015 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
1016 BuiltinID == ARM::BI__builtin_arm_ldaex ||
1017 BuiltinID == ARM::BI__builtin_arm_strex ||
1018 BuiltinID == ARM::BI__builtin_arm_stlex) {
1019 return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
1020 }
1021
1022 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
1023 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1024 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
1025 }
1026
1027 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
1028 BuiltinID == ARM::BI__builtin_arm_wsr64)
1029 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);
1030
1031 if (BuiltinID == ARM::BI__builtin_arm_rsr ||
1032 BuiltinID == ARM::BI__builtin_arm_rsrp ||
1033 BuiltinID == ARM::BI__builtin_arm_wsr ||
1034 BuiltinID == ARM::BI__builtin_arm_wsrp)
1035 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1036
1037 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1038 return true;
1039 if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall))
1040 return true;
1041 if (CheckCDEBuiltinFunctionCall(TI, BuiltinID, TheCall))
1042 return true;
1043
1044 // For intrinsics which take an immediate value as part of the instruction,
1045 // range check them here.
1046 // FIXME: VFP Intrinsics should error if VFP not present.
1047 switch (BuiltinID) {
1048 default:
1049 return false;
1050 case ARM::BI__builtin_arm_ssat:
1051 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);
1052 case ARM::BI__builtin_arm_usat:
1053 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1054 case ARM::BI__builtin_arm_ssat16:
1055 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
1056 case ARM::BI__builtin_arm_usat16:
1057 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
1058 case ARM::BI__builtin_arm_vcvtr_f:
1059 case ARM::BI__builtin_arm_vcvtr_d:
1060 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
1061 case ARM::BI__builtin_arm_dmb:
1062 case ARM::BI__dmb:
1063 case ARM::BI__builtin_arm_dsb:
1064 case ARM::BI__dsb:
1065 case ARM::BI__builtin_arm_isb:
1066 case ARM::BI__isb:
1067 case ARM::BI__builtin_arm_dbg:
1068 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
1069 case ARM::BI__builtin_arm_cdp:
1070 case ARM::BI__builtin_arm_cdp2:
1071 case ARM::BI__builtin_arm_mcr:
1072 case ARM::BI__builtin_arm_mcr2:
1073 case ARM::BI__builtin_arm_mrc:
1074 case ARM::BI__builtin_arm_mrc2:
1075 case ARM::BI__builtin_arm_mcrr:
1076 case ARM::BI__builtin_arm_mcrr2:
1077 case ARM::BI__builtin_arm_mrrc:
1078 case ARM::BI__builtin_arm_mrrc2:
1079 case ARM::BI__builtin_arm_ldc:
1080 case ARM::BI__builtin_arm_ldcl:
1081 case ARM::BI__builtin_arm_ldc2:
1082 case ARM::BI__builtin_arm_ldc2l:
1083 case ARM::BI__builtin_arm_stc:
1084 case ARM::BI__builtin_arm_stcl:
1085 case ARM::BI__builtin_arm_stc2:
1086 case ARM::BI__builtin_arm_stc2l:
1087 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
1088 CheckARMCoprocessorImmediate(TI, TheCall->getArg(0),
1089 /*WantCDE*/ false);
1090 }
1091}
1092
1094 unsigned BuiltinID,
1095 CallExpr *TheCall) {
1096 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1097 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1098 BuiltinID == AArch64::BI__builtin_arm_strex ||
1099 BuiltinID == AArch64::BI__builtin_arm_stlex) {
1100 return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
1101 }
1102
1103 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
1104 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1105 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
1106 SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
1107 SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);
1108 }
1109
1110 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
1111 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
1112 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
1113 BuiltinID == AArch64::BI__builtin_arm_wsr128)
1114 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1115
1116 // Memory Tagging Extensions (MTE) Intrinsics
1117 if (BuiltinID == AArch64::BI__builtin_arm_irg ||
1118 BuiltinID == AArch64::BI__builtin_arm_addg ||
1119 BuiltinID == AArch64::BI__builtin_arm_gmi ||
1120 BuiltinID == AArch64::BI__builtin_arm_ldg ||
1121 BuiltinID == AArch64::BI__builtin_arm_stg ||
1122 BuiltinID == AArch64::BI__builtin_arm_subp) {
1123 return BuiltinARMMemoryTaggingCall(BuiltinID, TheCall);
1124 }
1125
1126 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
1127 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
1128 BuiltinID == AArch64::BI__builtin_arm_wsr ||
1129 BuiltinID == AArch64::BI__builtin_arm_wsrp)
1130 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1131
1132 // Only check the valid encoding range. Any constant in this range would be
1133 // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
1134 // an exception for incorrect registers. This matches MSVC behavior.
1135 if (BuiltinID == AArch64::BI_ReadStatusReg ||
1136 BuiltinID == AArch64::BI_WriteStatusReg || BuiltinID == AArch64::BI__sys)
1137 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
1138
1139 if (BuiltinID == AArch64::BI__getReg)
1140 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
1141
1142 if (BuiltinID == AArch64::BI__break)
1143 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1144
1145 if (BuiltinID == AArch64::BI__hlt)
1146 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1147
1148 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1149 return true;
1150
1151 if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall))
1152 return true;
1153
1154 if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall))
1155 return true;
1156
1157 // For intrinsics which take an immediate value as part of the instruction,
1158 // range check them here.
1159 unsigned i = 0, l = 0, u = 0;
1160 switch (BuiltinID) {
1161 default: return false;
1162 case AArch64::BI__builtin_arm_dmb:
1163 case AArch64::BI__dmb:
1164 case AArch64::BI__builtin_arm_dsb:
1165 case AArch64::BI__dsb:
1166 case AArch64::BI__builtin_arm_isb:
1167 case AArch64::BI__isb:
1168 l = 0;
1169 u = 15;
1170 break;
1171 case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break;
1172 }
1173
1174 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
1175}
1176
1177namespace {
1178struct IntrinToName {
1179 uint32_t Id;
1180 int32_t FullName;
1181 int32_t ShortName;
1182};
1183} // unnamed namespace
1184
1185static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
1187 const char *IntrinNames) {
1188 AliasName.consume_front("__arm_");
1189 const IntrinToName *It =
1190 llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
1191 return L.Id < Id;
1192 });
1193 if (It == Map.end() || It->Id != BuiltinID)
1194 return false;
1195 StringRef FullName(&IntrinNames[It->FullName]);
1196 if (AliasName == FullName)
1197 return true;
1198 if (It->ShortName == -1)
1199 return false;
1200 StringRef ShortName(&IntrinNames[It->ShortName]);
1201 return AliasName == ShortName;
1202}
1203
1204bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1205#include "clang/Basic/arm_mve_builtin_aliases.inc"
1206 // The included file defines:
1207 // - ArrayRef<IntrinToName> Map
1208 // - const char IntrinNames[]
1209 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1210}
1211
1212bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1213#include "clang/Basic/arm_cde_builtin_aliases.inc"
1214 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1215}
1216
1217bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1218 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1219 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1220 return BuiltinID >= AArch64::FirstSVEBuiltin &&
1221 BuiltinID <= AArch64::LastSVEBuiltin;
1222}
1223
1224bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1225 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1226 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1227 return BuiltinID >= AArch64::FirstSMEBuiltin &&
1228 BuiltinID <= AArch64::LastSMEBuiltin;
1229}
1230
1232 ASTContext &Context = getASTContext();
1233 if (!AL.isArgIdent(0)) {
1234 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
1235 << AL << 1 << AANT_ArgumentIdentifier;
1236 return;
1237 }
1238
1240 unsigned BuiltinID = Ident->getBuiltinID();
1241 StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
1242
1243 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
1244 if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) &&
1245 !SmeAliasValid(BuiltinID, AliasName)) ||
1246 (!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) &&
1247 !CdeAliasValid(BuiltinID, AliasName))) {
1248 Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
1249 return;
1250 }
1251
1252 D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
1253}
1254
1256 Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT,
1257 FunctionType::ArmStateValue CurrentState, StringRef StateName) {
1258 auto CheckForIncompatibleAttr =
1259 [&](FunctionType::ArmStateValue IncompatibleState,
1260 StringRef IncompatibleStateName) {
1261 if (CurrentState == IncompatibleState) {
1262 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
1263 << (std::string("'__arm_new(\"") + StateName.str() + "\")'")
1264 << (std::string("'") + IncompatibleStateName.str() + "(\"" +
1265 StateName.str() + "\")'")
1266 << true;
1267 AL.setInvalid();
1268 }
1269 };
1270
1271 CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in");
1272 CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out");
1273 CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout");
1274 CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves");
1275 return AL.isInvalid();
1276}
1277
1279 if (!AL.getNumArgs()) {
1280 Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
1281 AL.setInvalid();
1282 return;
1283 }
1284
1285 std::vector<StringRef> NewState;
1286 if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) {
1287 for (StringRef S : ExistingAttr->newArgs())
1288 NewState.push_back(S);
1289 }
1290
1291 bool HasZA = false;
1292 bool HasZT0 = false;
1293 for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1294 StringRef StateName;
1295 SourceLocation LiteralLoc;
1296 if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
1297 return;
1298
1299 if (StateName == "za")
1300 HasZA = true;
1301 else if (StateName == "zt0")
1302 HasZT0 = true;
1303 else {
1304 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
1305 AL.setInvalid();
1306 return;
1307 }
1308
1309 if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates.
1310 NewState.push_back(StateName);
1311 }
1312
1313 if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) {
1315 FunctionType::getArmZAState(FPT->getAArch64SMEAttributes());
1316 if (HasZA && ZAState != FunctionType::ARM_None &&
1317 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za"))
1318 return;
1320 FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes());
1321 if (HasZT0 && ZT0State != FunctionType::ARM_None &&
1322 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0"))
1323 return;
1324 }
1325
1326 D->dropAttr<ArmNewAttr>();
1327 D->addAttr(::new (getASTContext()) ArmNewAttr(
1328 getASTContext(), AL, NewState.data(), NewState.size()));
1329}
1330
1332 if (getLangOpts().CPlusPlus && !D->getDeclContext()->isExternCContext()) {
1333 Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
1334 return;
1335 }
1336
1337 const auto *FD = cast<FunctionDecl>(D);
1338 if (!FD->isExternallyVisible()) {
1339 Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
1340 return;
1341 }
1342
1343 D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL));
1344}
1345
1347 // Check the attribute arguments.
1348 if (AL.getNumArgs() > 1) {
1349 Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
1350 return;
1351 }
1352
1353 StringRef Str;
1354 SourceLocation ArgLoc;
1355
1356 if (AL.getNumArgs() == 0)
1357 Str = "";
1358 else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1359 return;
1360
1361 ARMInterruptAttr::InterruptType Kind;
1362 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
1363 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1364 << AL << Str << ArgLoc;
1365 return;
1366 }
1367
1368 if (!D->hasAttr<ARMSaveFPAttr>()) {
1369 const TargetInfo &TI = getASTContext().getTargetInfo();
1370 if (TI.hasFeature("vfp"))
1371 Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1372 }
1373
1374 D->addAttr(::new (getASTContext())
1375 ARMInterruptAttr(getASTContext(), AL, Kind));
1376}
1377
1379 // Go ahead and add ARMSaveFPAttr because handleInterruptAttr() checks for
1380 // it when deciding to issue a diagnostic about clobbering floating point
1381 // registers, which ARMSaveFPAttr prevents.
1382 D->addAttr(::new (SemaRef.Context) ARMSaveFPAttr(SemaRef.Context, AL));
1384
1385 // If ARM().handleInterruptAttr() failed, remove ARMSaveFPAttr.
1386 if (!D->hasAttr<ARMInterruptAttr>()) {
1387 D->dropAttr<ARMSaveFPAttr>();
1388 return;
1389 }
1390
1391 // If VFP not enabled, remove ARMSaveFPAttr but leave ARMInterruptAttr.
1392 bool VFP = SemaRef.Context.getTargetInfo().hasFeature("vfp");
1393
1394 if (!VFP) {
1395 SemaRef.Diag(D->getLocation(), diag::warn_arm_interrupt_save_fp_without_vfp_unit);
1396 D->dropAttr<ARMSaveFPAttr>();
1397 }
1398}
1399
1400// Check if the function definition uses any AArch64 SME features without
1401// having the '+sme' feature enabled and warn user if sme locally streaming
1402// function returns or uses arguments with VL-based types.
1404 const auto *Attr = FD->getAttr<ArmNewAttr>();
1405 bool UsesSM = FD->hasAttr<ArmLocallyStreamingAttr>();
1406 bool UsesZA = Attr && Attr->isNewZA();
1407 bool UsesZT0 = Attr && Attr->isNewZT0();
1408
1409 if (UsesZA || UsesZT0) {
1410 if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
1411 FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1413 Diag(FD->getLocation(), diag::err_sme_unsupported_agnostic_new);
1414 }
1415 }
1416
1417 if (FD->hasAttr<ArmLocallyStreamingAttr>()) {
1419 Diag(FD->getLocation(),
1420 diag::warn_sme_locally_streaming_has_vl_args_returns)
1421 << /*IsArg=*/false;
1422 if (llvm::any_of(FD->parameters(), [](ParmVarDecl *P) {
1423 return P->getOriginalType()->isSizelessVectorType();
1424 }))
1425 Diag(FD->getLocation(),
1426 diag::warn_sme_locally_streaming_has_vl_args_returns)
1427 << /*IsArg=*/true;
1428 }
1429 if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
1430 FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1436 }
1437
1438 ASTContext &Context = getASTContext();
1439 if (UsesSM || UsesZA) {
1440 llvm::StringMap<bool> FeatureMap;
1441 Context.getFunctionFeatureMap(FeatureMap, FD);
1442 if (!FeatureMap.contains("sme")) {
1443 if (UsesSM)
1444 Diag(FD->getLocation(),
1445 diag::err_sme_definition_using_sm_in_non_sme_target);
1446 else
1447 Diag(FD->getLocation(),
1448 diag::err_sme_definition_using_za_in_non_sme_target);
1449 }
1450 }
1451 if (UsesZT0) {
1452 llvm::StringMap<bool> FeatureMap;
1453 Context.getFunctionFeatureMap(FeatureMap, FD);
1454 if (!FeatureMap.contains("sme2")) {
1455 Diag(FD->getLocation(),
1456 diag::err_sme_definition_using_zt0_in_non_sme2_target);
1457 }
1458 }
1459}
1460
1461/// getSVETypeSize - Return SVE vector or predicate register size.
1462static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty,
1463 bool IsStreaming) {
1464 assert(Ty->isSveVLSBuiltinType() && "Invalid SVE Type");
1465 uint64_t VScale = IsStreaming ? Context.getLangOpts().VScaleStreamingMin
1466 : Context.getLangOpts().VScaleMin;
1467 if (Ty->getKind() == BuiltinType::SveBool ||
1468 Ty->getKind() == BuiltinType::SveCount)
1469 return (VScale * 128) / Context.getCharWidth();
1470 return VScale * 128;
1471}
1472
1474 bool IsStreaming = false;
1475 if (getLangOpts().VScaleMin != getLangOpts().VScaleStreamingMin ||
1476 getLangOpts().VScaleMax != getLangOpts().VScaleStreamingMax) {
1477 if (const FunctionDecl *FD =
1478 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
1479 // For streaming-compatible functions, we don't know vector length.
1480 if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
1481 if (T->getAArch64SMEAttributes() &
1483 return false;
1484 }
1485
1486 if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
1487 IsStreaming = true;
1488 }
1489 }
1490
1491 auto IsValidCast = [&](QualType FirstType, QualType SecondType) {
1492 if (const auto *BT = FirstType->getAs<BuiltinType>()) {
1493 if (const auto *VT = SecondType->getAs<VectorType>()) {
1494 // Predicates have the same representation as uint8 so we also have to
1495 // check the kind to make these types incompatible.
1496 ASTContext &Context = getASTContext();
1497 if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate)
1498 return BT->getKind() == BuiltinType::SveBool;
1499 else if (VT->getVectorKind() == VectorKind::SveFixedLengthData)
1500 return VT->getElementType().getCanonicalType() ==
1501 FirstType->getSveEltType(Context);
1502 else if (VT->getVectorKind() == VectorKind::Generic)
1503 return Context.getTypeSize(SecondType) ==
1504 getSVETypeSize(Context, BT, IsStreaming) &&
1505 Context.hasSameType(
1506 VT->getElementType(),
1507 Context.getBuiltinVectorTypeInfo(BT).ElementType);
1508 }
1509 }
1510 return false;
1511 };
1512
1513 return IsValidCast(FirstType, SecondType) ||
1514 IsValidCast(SecondType, FirstType);
1515}
1516
1518 QualType SecondType) {
1519 bool IsStreaming = false;
1520 if (getLangOpts().VScaleMin != getLangOpts().VScaleStreamingMin ||
1521 getLangOpts().VScaleMax != getLangOpts().VScaleStreamingMax) {
1522 if (const FunctionDecl *FD =
1523 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
1524 // For streaming-compatible functions, we don't know vector length.
1525 if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
1526 if (T->getAArch64SMEAttributes() &
1528 return false;
1529
1530 if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
1531 IsStreaming = true;
1532 }
1533 }
1534
1535 auto IsLaxCompatible = [&](QualType FirstType, QualType SecondType) {
1536 const auto *BT = FirstType->getAs<BuiltinType>();
1537 if (!BT)
1538 return false;
1539
1540 const auto *VecTy = SecondType->getAs<VectorType>();
1541 if (VecTy && (VecTy->getVectorKind() == VectorKind::SveFixedLengthData ||
1542 VecTy->getVectorKind() == VectorKind::Generic)) {
1544 getLangOpts().getLaxVectorConversions();
1545 ASTContext &Context = getASTContext();
1546
1547 // Can not convert between sve predicates and sve vectors because of
1548 // different size.
1549 if (BT->getKind() == BuiltinType::SveBool &&
1550 VecTy->getVectorKind() == VectorKind::SveFixedLengthData)
1551 return false;
1552
1553 // If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion.
1554 // "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly
1555 // converts to VLAT and VLAT implicitly converts to GNUT."
1556 // ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and
1557 // predicates.
1558 if (VecTy->getVectorKind() == VectorKind::Generic &&
1559 Context.getTypeSize(SecondType) !=
1560 getSVETypeSize(Context, BT, IsStreaming))
1561 return false;
1562
1563 // If -flax-vector-conversions=all is specified, the types are
1564 // certainly compatible.
1566 return true;
1567
1568 // If -flax-vector-conversions=integer is specified, the types are
1569 // compatible if the elements are integer types.
1571 return VecTy->getElementType().getCanonicalType()->isIntegerType() &&
1572 FirstType->getSveEltType(Context)->isIntegerType();
1573 }
1574
1575 return false;
1576 };
1577
1578 return IsLaxCompatible(FirstType, SecondType) ||
1579 IsLaxCompatible(SecondType, FirstType);
1580}
1581
1582bool SemaARM::checkTargetVersionAttr(const StringRef Param,
1583 const SourceLocation Loc) {
1584 using namespace DiagAttrParams;
1585
1587 Param.split(Features, '+');
1588 for (StringRef Feat : Features) {
1589 Feat = Feat.trim();
1590 if (Feat == "default")
1591 continue;
1592 if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
1593 return Diag(Loc, diag::warn_unsupported_target_attribute)
1594 << Unsupported << None << Feat << TargetVersion;
1595 }
1596 return false;
1597}
1598
1601 SmallVectorImpl<SmallString<64>> &NewParams) {
1602 using namespace DiagAttrParams;
1603
1604 if (!getASTContext().getTargetInfo().hasFeature("fmv"))
1605 return true;
1606
1607 assert(Params.size() == Locs.size() &&
1608 "Mismatch between number of string parameters and locations");
1609
1610 bool HasDefault = false;
1611 bool HasNonDefault = false;
1612 for (unsigned I = 0, E = Params.size(); I < E; ++I) {
1613 const StringRef Param = Params[I].trim();
1614 const SourceLocation &Loc = Locs[I];
1615
1616 if (Param.empty())
1617 return Diag(Loc, diag::warn_unsupported_target_attribute)
1618 << Unsupported << None << "" << TargetClones;
1619
1620 if (Param == "default") {
1621 if (HasDefault)
1622 Diag(Loc, diag::warn_target_clone_duplicate_options);
1623 else {
1624 NewParams.push_back(Param);
1625 HasDefault = true;
1626 }
1627 continue;
1628 }
1629
1630 bool HasCodeGenImpact = false;
1632 llvm::SmallVector<StringRef, 8> ValidFeatures;
1633 Param.split(Features, '+');
1634 for (StringRef Feat : Features) {
1635 Feat = Feat.trim();
1636 if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
1637 Diag(Loc, diag::warn_unsupported_target_attribute)
1638 << Unsupported << None << Feat << TargetClones;
1639 continue;
1640 }
1641 if (getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat))
1642 HasCodeGenImpact = true;
1643 ValidFeatures.push_back(Feat);
1644 }
1645
1646 // Ignore features that don't impact code generation.
1647 if (!HasCodeGenImpact) {
1648 Diag(Loc, diag::warn_target_clone_no_impact_options);
1649 continue;
1650 }
1651
1652 if (ValidFeatures.empty())
1653 continue;
1654
1655 // Canonicalize attribute parameter.
1656 llvm::sort(ValidFeatures);
1657 SmallString<64> NewParam(llvm::join(ValidFeatures, "+"));
1658 if (llvm::is_contained(NewParams, NewParam)) {
1659 Diag(Loc, diag::warn_target_clone_duplicate_options);
1660 continue;
1661 }
1662
1663 // Valid non-default argument.
1664 NewParams.push_back(NewParam);
1665 HasNonDefault = true;
1666 }
1667 if (!HasNonDefault)
1668 return true;
1669
1670 return false;
1671}
1672
1673} // namespace clang
StringRef P
const Decl * D
enum clang::sema::@1840::IndirectLocalPathEntry::EntryKind Kind
Expr * E
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, const TargetInfo &Target)
Determine whether a translation unit built using the current language options has the given feature.
Definition: Module.cpp:95
OffloadArch Arch
Definition: OffloadArch.cpp:10
uint32_t Id
Definition: SemaARM.cpp:1179
int32_t ShortName
Definition: SemaARM.cpp:1181
int32_t FullName
Definition: SemaARM.cpp:1180
This file declares semantic analysis functions specific to ARM.
SourceLocation Loc
Definition: SemaObjC.cpp:754
Enumerates target-specific builtins in their own namespaces within namespace clang.
__device__ int
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
CanQualType LongTy
Definition: ASTContext.h:1231
CanQualType FloatTy
Definition: ASTContext.h:1234
CanQualType DoubleTy
Definition: ASTContext.h:1234
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
Builtin::Context & BuiltinInfo
Definition: ASTContext.h:742
const LangOptions & getLangOpts() const
Definition: ASTContext.h:894
CanQualType UnsignedLongTy
Definition: ASTContext.h:1232
CanQualType IntTy
Definition: ASTContext.h:1231
CanQualType SignedCharTy
Definition: ASTContext.h:1231
CanQualType UnsignedCharTy
Definition: ASTContext.h:1232
CanQualType UnsignedIntTy
Definition: ASTContext.h:1232
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:1233
CanQualType UnsignedShortTy
Definition: ASTContext.h:1232
CanQualType ShortTy
Definition: ASTContext.h:1231
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:859
CanQualType BFloat16Ty
Definition: ASTContext.h:1247
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
CanQualType LongLongTy
Definition: ASTContext.h:1231
CanQualType HalfTy
Definition: ASTContext.h:1246
uint64_t getCharWidth() const
Return the size of the character type, in bits.
Definition: ASTContext.h:2629
PtrTy get() const
Definition: Ownership.h:171
bool isInvalid() const
Definition: Ownership.h:167
Attr - This represents one attribute.
Definition: Attr.h:44
SourceLocation getLoc() const
This class is used for builtin types like 'int'.
Definition: TypeBase.h:3182
Kind getKind() const
Definition: TypeBase.h:3230
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
Definition: Builtins.h:420
const char * getRequiredFeatures(unsigned ID) const
Definition: Builtins.cpp:102
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3083
SourceLocation getBeginLoc() const
Definition: Expr.h:3213
void setArg(unsigned Arg, Expr *ArgExpr)
setArg - Set the specified argument.
Definition: Expr.h:3096
Expr * getCallee()
Definition: Expr.h:3026
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3070
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1272
SourceLocation getBeginLoc() const
Definition: Expr.h:1351
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:573
SourceLocation getLocation() const
Definition: DeclBase.h:439
bool hasAttr() const
Definition: DeclBase.h:577
This represents one expression.
Definition: Expr.h:112
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3078
void setType(QualType t)
Definition: Expr.h:145
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:177
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:194
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3073
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Definition: Expr.h:837
QualType getType() const
Definition: Expr.h:144
Represents a function declaration or definition.
Definition: Decl.h:1999
QualType getReturnType() const
Definition: Decl.h:2838
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2767
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
unsigned getAArch64SMEAttributes() const
Return a bitmask describing the SME attributes on the function type, see AArch64SMETypeAttributes for...
Definition: TypeBase.h:5779
static ArmStateValue getArmZT0State(unsigned AttrBits)
Definition: TypeBase.h:4787
static ArmStateValue getArmZAState(unsigned AttrBits)
Definition: TypeBase.h:4783
One of these records is kept for each identifier that is lexed.
unsigned getBuiltinID() const
Return a value indicating whether this is a builtin function.
IdentifierInfo * getIdentifierInfo() const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition: Expr.h:3789
Describes an entity that is being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
@ Integer
Permit vector bitcasts between integer vectors with different numbers of elements but the same total ...
@ All
Permit vector bitcasts between all vectors with the same total bit-width.
Flags to identify the types for overloaded Neon builtins.
bool isUnsigned() const
unsigned getEltSizeInBits() const
EltType getEltType() const
Represents a parameter to a function.
Definition: Decl.h:1789
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:119
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition: ParsedAttr.h:389
void setInvalid(bool b=true) const
Definition: ParsedAttr.h:345
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:371
bool isArgIdent(unsigned Arg) const
Definition: ParsedAttr.h:385
bool isInvalid() const
Definition: ParsedAttr.h:344
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: TypeBase.h:3346
A (possibly-)qualified type.
Definition: TypeBase.h:937
QualType withConst() const
Definition: TypeBase.h:1159
void addConst()
Add the const type qualifier to this QualType.
Definition: TypeBase.h:1156
QualType withVolatile() const
Definition: TypeBase.h:1167
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition: TypeBase.h:1438
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: TypeBase.h:8437
const Type * getTypePtrOrNull() const
Definition: TypeBase.h:8347
bool isAtLeastAsQualifiedAs(QualType Other, const ASTContext &Ctx) const
Determine whether this type is at least as qualified as the other given type, requiring exact equalit...
Definition: TypeBase.h:8508
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition: TypeBase.h:361
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition: TypeBase.h:354
@ OCL_None
There is no lifetime qualification on this type.
Definition: TypeBase.h:350
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition: TypeBase.h:364
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition: TypeBase.h:367
void CheckSMEFunctionDefAttributes(const FunctionDecl *FD)
Definition: SemaARM.cpp:1403
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:1012
void handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1378
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:642
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE)
Definition: SemaARM.cpp:824
bool checkTargetVersionAttr(const StringRef Str, const SourceLocation Loc)
Definition: SemaARM.cpp:1582
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:683
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:712
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:808
bool PerformNeonImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int, int > > &ImmChecks, int OverloadType=-1)
Definition: SemaARM.cpp:513
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:799
void handleInterruptAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1346
bool PerformSVEImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int > > &ImmChecks)
Definition: SemaARM.cpp:532
void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1231
@ ArmStreaming
Intrinsic is only available in normal mode.
Definition: SemaARM.h:37
@ ArmNonStreaming
Definition: SemaARM.h:36
@ VerifyRuntimeMode
Intrinsic is available both in normal and Streaming-SVE mode.
Definition: SemaARM.h:40
@ ArmStreamingCompatible
Intrinsic is only available in Streaming-SVE mode.
Definition: SemaARM.h:38
void handleNewAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1278
bool CheckARMBuiltinExclusiveCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:849
bool areCompatibleSveTypes(QualType FirstType, QualType SecondType)
Return true if the given types are an SVE builtin and a VectorType that is a fixed-length representat...
Definition: SemaARM.cpp:1473
bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1217
bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType)
Return true if the given vector types are lax-compatible SVE vector types, false otherwise.
Definition: SemaARM.cpp:1517
bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:1093
bool MveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1204
bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall)
BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions.
Definition: SemaARM.cpp:26
void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1331
bool CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, unsigned ArgIdx, unsigned EltBitWidth, unsigned VecBitWidth)
Definition: SemaARM.cpp:375
bool BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, int ArgNum, unsigned ExpectedFieldNum, bool AllowName)
BuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr TheCall is an ARM/AArch64 specia...
Definition: SemaARM.cpp:188
bool SmeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1224
bool checkTargetClonesAttr(SmallVectorImpl< StringRef > &Params, SmallVectorImpl< SourceLocation > &Locs, SmallVectorImpl< SmallString< 64 > > &NewParams)
Definition: SemaARM.cpp:1599
bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1212
SemaARM(Sema &S)
Definition: SemaARM.cpp:23
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:61
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
bool BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, unsigned Multiple)
BuiltinConstantArgMultiple - Handle a check if argument ArgNum of CallExpr TheCall is a constant expr...
AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, bool Diagnose=true, bool DiagnoseCFAudited=false, bool ConvertRHS=true)
Check assignment constraints for an assignment of RHS to LHSType.
Definition: SemaExpr.cpp:9762
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
Definition: Sema.cpp:1647
ASTContext & Context
Definition: Sema.h:1276
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:748
ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, ExprValueKind VK=VK_PRValue, const CXXCastPath *BasePath=nullptr, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
Definition: Sema.cpp:756
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:633
bool BuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result)
BuiltinConstantArg - Handle a check if argument ArgNum of CallExpr TheCall is a constant expression.
bool isConstantEvaluatedContext() const
Definition: Sema.h:2584
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)
Definition: SemaInit.cpp:9874
bool DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, QualType DstType, QualType SrcType, Expr *SrcExpr, AssignmentAction Action, bool *Complained=nullptr)
DiagnoseAssignmentResult - Emit a diagnostic, if required, for the assignment conversion type specifi...
Definition: SemaExpr.cpp:17077
bool BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, bool RangeIsError=true)
BuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr TheCall is a constant express...
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
SemaARM & ARM()
Definition: Sema.h:1418
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
Exposes information about the current target.
Definition: TargetInfo.h:226
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1288
IntType getInt64Type() const
Definition: TargetInfo.h:419
virtual unsigned getARMLDREXMask() const
Definition: TargetInfo.h:1085
uint32_t getARMCDECoprocMask() const
For ARM targets returns a mask defining which coprocessors are configured as Custom Datapath.
Definition: TargetInfo.h:1074
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
Definition: TargetInfo.h:1526
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isBlockPointerType() const
Definition: TypeBase.h:8600
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: TypeBase.h:8980
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
Definition: Type.cpp:2612
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
QualType getSveEltType(const ASTContext &Ctx) const
Returns the representative type for the element of an SVE builtin type.
Definition: Type.cpp:2651
bool isFloatingType() const
Definition: Type.cpp:2308
bool isAnyPointerType() const
Definition: TypeBase.h:8588
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isSizelessVectorType() const
Returns true for all scalable vector types.
Definition: Type.cpp:2574
QualType getType() const
Definition: Decl.h:722
Represents a GCC generic vector type.
Definition: TypeBase.h:4191
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.
const AstTypeMatcher< PointerType > pointerType
Matches pointer types, but does not match Objective-C object pointer types.
The JSON file list parser is used to communicate input to InstallAPI.
@ CPlusPlus
Definition: LangStandard.h:55
static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, ArrayRef< IntrinToName > Map, const char *IntrinNames)
Definition: SemaARM.cpp:1185
static ArmSMEState getSMEState(unsigned BuiltinID)
Definition: SemaARM.cpp:632
static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, SemaARM::ArmStreamingType BuiltinType, unsigned BuiltinID)
Definition: SemaARM.cpp:561
ArmSMEState
Definition: SemaARM.cpp:361
@ ArmInOutZA
Definition: SemaARM.cpp:366
@ ArmZT0Mask
Definition: SemaARM.cpp:372
@ ArmInOutZT0
Definition: SemaARM.cpp:371
@ ArmInZA
Definition: SemaARM.cpp:364
@ ArmInZT0
Definition: SemaARM.cpp:369
@ ArmZAMask
Definition: SemaARM.cpp:367
@ ArmOutZA
Definition: SemaARM.cpp:365
@ ArmOutZT0
Definition: SemaARM.cpp:370
@ ArmNoState
Definition: SemaARM.cpp:362
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)
Definition: SemaARM.cpp:545
static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty, bool IsStreaming)
getSVETypeSize - Return SVE vector or predicate register size.
Definition: SemaARM.cpp:1462
@ AANT_ArgumentIdentifier
Definition: ParsedAttr.h:1067
@ Result
The result type of a method or function.
AssignConvertType
AssignConvertType - All of the 'assignment' semantic checks return this enum to indicate whether the ...
Definition: Sema.h:687
bool hasArmZT0State(const FunctionDecl *FD)
Returns whether the given FunctionDecl has Arm ZT0 state.
Definition: Decl.cpp:5984
CastKind
CastKind - The kind of operation required for a conversion.
const FunctionProtoType * T
static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, bool IsPolyUnsigned, bool IsInt64Long)
getNeonEltType - Return the QualType corresponding to the elements of the vector type specified by th...
Definition: SemaARM.cpp:321
static bool checkNewAttrMutualExclusion(Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT, FunctionType::ArmStateValue CurrentState, StringRef StateName)
Definition: SemaARM.cpp:1255
@ SveFixedLengthData
is AArch64 SVE fixed-length data vector
@ Generic
not a target-specific vector type
@ SveFixedLengthPredicate
is AArch64 SVE fixed-length predicate vector
@ None
The alignment was not explicit in code.
bool IsArmStreamingFunction(const FunctionDecl *FD, bool IncludeLocallyStreaming)
Returns whether the given FunctionDecl has an __arm[_locally]_streaming attribute.
Definition: Decl.cpp:5963
bool hasArmZAState(const FunctionDecl *FD)
Returns whether the given FunctionDecl has Arm ZA state.
Definition: Decl.cpp:5977
Extra information about a function prototype.
Definition: TypeBase.h:5367