clang 20.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> Ranges;
253 if (FiveFields)
254 Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 15, 15, 7});
255 else
256 Ranges.append({15, 7, 15});
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 <= Ranges[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;
355 }
356 llvm_unreachable("Invalid NeonTypeFlag!");
357}
358
359enum ArmSMEState : unsigned {
361
362 ArmInZA = 0b01,
363 ArmOutZA = 0b10,
365 ArmZAMask = 0b11,
366
367 ArmInZT0 = 0b01 << 2,
368 ArmOutZT0 = 0b10 << 2,
369 ArmInOutZT0 = 0b11 << 2,
370 ArmZT0Mask = 0b11 << 2
372
373bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy,
374 unsigned ArgIdx, unsigned EltBitWidth,
375 unsigned VecBitWidth) {
376 // Function that checks whether the operand (ArgIdx) is an immediate
377 // that is one of a given set of values.
378 auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set,
379 int ErrDiag) -> bool {
380 // We can't check the value of a dependent argument.
381 Expr *Arg = TheCall->getArg(ArgIdx);
382 if (Arg->isTypeDependent() || Arg->isValueDependent())
383 return false;
384
385 // Check constant-ness first.
386 llvm::APSInt Imm;
387 if (SemaRef.BuiltinConstantArg(TheCall, ArgIdx, Imm))
388 return true;
389
390 if (std::find(Set.begin(), Set.end(), Imm.getSExtValue()) == Set.end())
391 return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
392 return false;
393 };
394
395 switch ((ImmCheckType)CheckTy) {
396 case ImmCheckType::ImmCheck0_31:
397 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 31))
398 return true;
399 break;
400 case ImmCheckType::ImmCheck0_13:
401 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 13))
402 return true;
403 break;
404 case ImmCheckType::ImmCheck0_63:
405 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63))
406 return true;
407 break;
408 case ImmCheckType::ImmCheck1_16:
409 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16))
410 return true;
411 break;
412 case ImmCheckType::ImmCheck0_7:
413 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7))
414 return true;
415 break;
416 case ImmCheckType::ImmCheck1_1:
417 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 1))
418 return true;
419 break;
420 case ImmCheckType::ImmCheck1_3:
421 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 3))
422 return true;
423 break;
424 case ImmCheckType::ImmCheck1_7:
425 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 7))
426 return true;
427 break;
428 case ImmCheckType::ImmCheckExtract:
429 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
430 (2048 / EltBitWidth) - 1))
431 return true;
432 break;
433 case ImmCheckType::ImmCheckCvt:
434 case ImmCheckType::ImmCheckShiftRight:
435 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth))
436 return true;
437 break;
438 case ImmCheckType::ImmCheckShiftRightNarrow:
439 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth / 2))
440 return true;
441 break;
442 case ImmCheckType::ImmCheckShiftLeft:
443 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1))
444 return true;
445 break;
446 case ImmCheckType::ImmCheckLaneIndex:
447 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
448 (VecBitWidth / EltBitWidth) - 1))
449 return true;
450 break;
451 case ImmCheckType::ImmCheckLaneIndexCompRotate:
452 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
453 (VecBitWidth / (2 * EltBitWidth)) - 1))
454 return true;
455 break;
456 case ImmCheckType::ImmCheckLaneIndexDot:
457 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
458 (VecBitWidth / (4 * EltBitWidth)) - 1))
459 return true;
460 break;
461 case ImmCheckType::ImmCheckComplexRot90_270:
462 if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd))
463 return true;
464 break;
465 case ImmCheckType::ImmCheckComplexRotAll90:
466 if (CheckImmediateInSet({0, 90, 180, 270},
467 diag::err_rotation_argument_to_cmla))
468 return true;
469 break;
470 case ImmCheckType::ImmCheck0_1:
471 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 1))
472 return true;
473 break;
474 case ImmCheckType::ImmCheck0_2:
475 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 2))
476 return true;
477 break;
478 case ImmCheckType::ImmCheck0_3:
479 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3))
480 return true;
481 break;
482 case ImmCheckType::ImmCheck0_0:
483 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 0))
484 return true;
485 break;
486 case ImmCheckType::ImmCheck0_15:
487 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 15))
488 return true;
489 break;
490 case ImmCheckType::ImmCheck0_255:
491 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 255))
492 return true;
493 break;
494 case ImmCheckType::ImmCheck1_32:
495 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32))
496 return true;
497 break;
498 case ImmCheckType::ImmCheck1_64:
499 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64))
500 return true;
501 break;
502 case ImmCheckType::ImmCheck2_4_Mul2:
503 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 2, 4) ||
504 SemaRef.BuiltinConstantArgMultiple(TheCall, ArgIdx, 2))
505 return true;
506 break;
507 }
508 return false;
509}
510
512 CallExpr *TheCall,
513 SmallVectorImpl<std::tuple<int, int, int, int>> &ImmChecks,
514 int OverloadType) {
515 bool HasError = false;
516
517 for (const auto &I : ImmChecks) {
518 auto [ArgIdx, CheckTy, ElementSizeInBits, VecSizeInBits] = I;
519
520 if (OverloadType >= 0)
521 ElementSizeInBits = NeonTypeFlags(OverloadType).getEltSizeInBits();
522
523 HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementSizeInBits,
524 VecSizeInBits);
525 }
526
527 return HasError;
528}
529
531 CallExpr *TheCall, SmallVectorImpl<std::tuple<int, int, int>> &ImmChecks) {
532 bool HasError = false;
533
534 for (const auto &I : ImmChecks) {
535 auto [ArgIdx, CheckTy, ElementSizeInBits] = I;
536 HasError |=
537 CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementSizeInBits, 128);
538 }
539
540 return HasError;
541}
542
544 if (FD->hasAttr<ArmLocallyStreamingAttr>())
546 if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
547 if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
548 if (FPT->getAArch64SMEAttributes() &
551 if (FPT->getAArch64SMEAttributes() &
554 }
555 }
557}
558
559static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
560 const FunctionDecl *FD,
562 unsigned BuiltinID) {
564
565 // Check if the intrinsic is available in the right mode, i.e.
566 // * When compiling for SME only, the caller must be in streaming mode.
567 // * When compiling for SVE only, the caller must be in non-streaming mode.
568 // * When compiling for both SVE and SME, the caller can be in either mode.
570 llvm::StringMap<bool> CallerFeatureMapWithoutSVE;
571 S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSVE, FD);
572 CallerFeatureMapWithoutSVE["sve"] = false;
573
574 // Avoid emitting diagnostics for a function that can never compile.
575 if (FnType == SemaARM::ArmStreaming && !CallerFeatureMapWithoutSVE["sme"])
576 return false;
577
578 llvm::StringMap<bool> CallerFeatureMapWithoutSME;
579 S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSME, FD);
580 CallerFeatureMapWithoutSME["sme"] = false;
581
582 // We know the builtin requires either some combination of SVE flags, or
583 // some combination of SME flags, but we need to figure out which part
584 // of the required features is satisfied by the target features.
585 //
586 // For a builtin with target guard 'sve2p1|sme2', if we compile with
587 // '+sve2p1,+sme', then we know that it satisfies the 'sve2p1' part if we
588 // evaluate the features for '+sve2p1,+sme,+nosme'.
589 //
590 // Similarly, if we compile with '+sve2,+sme2', then we know it satisfies
591 // the 'sme2' part if we evaluate the features for '+sve2,+sme2,+nosve'.
592 StringRef BuiltinTargetGuards(
594 bool SatisfiesSVE = Builtin::evaluateRequiredTargetFeatures(
595 BuiltinTargetGuards, CallerFeatureMapWithoutSME);
596 bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures(
597 BuiltinTargetGuards, CallerFeatureMapWithoutSVE);
598
599 if ((SatisfiesSVE && SatisfiesSME) ||
600 (SatisfiesSVE && FnType == SemaARM::ArmStreamingCompatible))
601 return false;
602 else if (SatisfiesSVE)
604 else if (SatisfiesSME)
606 else
607 // This should be diagnosed by CodeGen
608 return false;
609 }
610
611 if (FnType != SemaARM::ArmNonStreaming &&
613 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
614 << TheCall->getSourceRange() << "non-streaming";
615 else if (FnType != SemaARM::ArmStreaming &&
617 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
618 << TheCall->getSourceRange() << "streaming";
619 else
620 return false;
621
622 return true;
623}
624
625static bool hasArmZAState(const FunctionDecl *FD) {
626 const auto *T = FD->getType()->getAs<FunctionProtoType>();
629 (FD->hasAttr<ArmNewAttr>() && FD->getAttr<ArmNewAttr>()->isNewZA());
630}
631
632static bool hasArmZT0State(const FunctionDecl *FD) {
633 const auto *T = FD->getType()->getAs<FunctionProtoType>();
636 (FD->hasAttr<ArmNewAttr>() && FD->getAttr<ArmNewAttr>()->isNewZT0());
637}
638
639static ArmSMEState getSMEState(unsigned BuiltinID) {
640 switch (BuiltinID) {
641 default:
642 return ArmNoState;
643#define GET_SME_BUILTIN_GET_STATE
644#include "clang/Basic/arm_sme_builtins_za_state.inc"
645#undef GET_SME_BUILTIN_GET_STATE
646 }
647}
648
650 CallExpr *TheCall) {
651 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
652 std::optional<ArmStreamingType> BuiltinType;
653
654 switch (BuiltinID) {
655#define GET_SME_STREAMING_ATTRS
656#include "clang/Basic/arm_sme_streaming_attrs.inc"
657#undef GET_SME_STREAMING_ATTRS
658 }
659
660 if (BuiltinType &&
661 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
662 return true;
663
664 if ((getSMEState(BuiltinID) & ArmZAMask) && !hasArmZAState(FD))
665 Diag(TheCall->getBeginLoc(),
666 diag::warn_attribute_arm_za_builtin_no_za_state)
667 << TheCall->getSourceRange();
668
669 if ((getSMEState(BuiltinID) & ArmZT0Mask) && !hasArmZT0State(FD))
670 Diag(TheCall->getBeginLoc(),
671 diag::warn_attribute_arm_zt0_builtin_no_zt0_state)
672 << TheCall->getSourceRange();
673 }
674
675 // Range check SME intrinsics that take immediate values.
677
678 switch (BuiltinID) {
679 default:
680 return false;
681#define GET_SME_IMMEDIATE_CHECK
682#include "clang/Basic/arm_sme_sema_rangechecks.inc"
683#undef GET_SME_IMMEDIATE_CHECK
684 }
685
686 return PerformSVEImmChecks(TheCall, ImmChecks);
687}
688
690 CallExpr *TheCall) {
691 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
692 std::optional<ArmStreamingType> BuiltinType;
693
694 switch (BuiltinID) {
695#define GET_SVE_STREAMING_ATTRS
696#include "clang/Basic/arm_sve_streaming_attrs.inc"
697#undef GET_SVE_STREAMING_ATTRS
698 }
699 if (BuiltinType &&
700 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
701 return true;
702 }
703 // Range check SVE intrinsics that take immediate values.
705
706 switch (BuiltinID) {
707 default:
708 return false;
709#define GET_SVE_IMMEDIATE_CHECK
710#include "clang/Basic/arm_sve_sema_rangechecks.inc"
711#undef GET_SVE_IMMEDIATE_CHECK
712 }
713
714 return PerformSVEImmChecks(TheCall, ImmChecks);
715}
716
718 unsigned BuiltinID,
719 CallExpr *TheCall) {
720 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
721
722 switch (BuiltinID) {
723 default:
724 break;
725#define GET_NEON_BUILTINS
726#define TARGET_BUILTIN(id, ...) case NEON::BI##id:
727#define BUILTIN(id, ...) case NEON::BI##id:
728#include "clang/Basic/arm_neon.inc"
730 BuiltinID))
731 return true;
732 break;
733#undef TARGET_BUILTIN
734#undef BUILTIN
735#undef GET_NEON_BUILTINS
736 }
737 }
738
739 llvm::APSInt Result;
740 uint64_t mask = 0;
741 int TV = -1;
742 int PtrArgNum = -1;
743 bool HasConstPtr = false;
744 switch (BuiltinID) {
745#define GET_NEON_OVERLOAD_CHECK
746#include "clang/Basic/arm_fp16.inc"
747#include "clang/Basic/arm_neon.inc"
748#undef GET_NEON_OVERLOAD_CHECK
749 }
750
751 // For NEON intrinsics which are overloaded on vector element type, validate
752 // the immediate which specifies which variant to emit.
753 unsigned ImmArg = TheCall->getNumArgs() - 1;
754 if (mask) {
755 if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result))
756 return true;
757
758 TV = Result.getLimitedValue(64);
759 if ((TV > 63) || (mask & (1ULL << TV)) == 0)
760 return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
761 << TheCall->getArg(ImmArg)->getSourceRange();
762 }
763
764 if (PtrArgNum >= 0) {
765 // Check that pointer arguments have the specified type.
766 Expr *Arg = TheCall->getArg(PtrArgNum);
767 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
768 Arg = ICE->getSubExpr();
770 QualType RHSTy = RHS.get()->getType();
771
772 llvm::Triple::ArchType Arch = TI.getTriple().getArch();
773 bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
774 Arch == llvm::Triple::aarch64_32 ||
775 Arch == llvm::Triple::aarch64_be;
776 bool IsInt64Long = TI.getInt64Type() == TargetInfo::SignedLong;
778 IsPolyUnsigned, IsInt64Long);
779 if (HasConstPtr)
780 EltTy = EltTy.withConst();
781 QualType LHSTy = getASTContext().getPointerType(EltTy);
783 ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);
784 if (RHS.isInvalid())
785 return true;
786 if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy,
787 RHSTy, RHS.get(),
789 return true;
790 }
791
792 // For NEON intrinsics which take an immediate value as part of the
793 // instruction, range check them here.
795 switch (BuiltinID) {
796 default:
797 return false;
798#define GET_NEON_IMMEDIATE_CHECK
799#include "clang/Basic/arm_fp16.inc"
800#include "clang/Basic/arm_neon.inc"
801#undef GET_NEON_IMMEDIATE_CHECK
802 }
803
804 return PerformNeonImmChecks(TheCall, ImmChecks, TV);
805}
806
808 CallExpr *TheCall) {
809 switch (BuiltinID) {
810 default:
811 return false;
812#include "clang/Basic/arm_mve_builtin_sema.inc"
813 }
814}
815
817 unsigned BuiltinID,
818 CallExpr *TheCall) {
819 bool Err = false;
820 switch (BuiltinID) {
821 default:
822 return false;
823#include "clang/Basic/arm_cde_builtin_sema.inc"
824 }
825
826 if (Err)
827 return true;
828
829 return CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), /*WantCDE*/ true);
830}
831
833 const Expr *CoprocArg,
834 bool WantCDE) {
835 ASTContext &Context = getASTContext();
837 return false;
838
839 // We can't check the value of a dependent argument.
840 if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
841 return false;
842
843 llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context);
844 int64_t CoprocNo = CoprocNoAP.getExtValue();
845 assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
846
847 uint32_t CDECoprocMask = TI.getARMCDECoprocMask();
848 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
849
850 if (IsCDECoproc != WantCDE)
851 return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
852 << (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange();
853
854 return false;
855}
856
858 CallExpr *TheCall,
859 unsigned MaxWidth) {
860 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
861 BuiltinID == ARM::BI__builtin_arm_ldaex ||
862 BuiltinID == ARM::BI__builtin_arm_strex ||
863 BuiltinID == ARM::BI__builtin_arm_stlex ||
864 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
865 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
866 BuiltinID == AArch64::BI__builtin_arm_strex ||
867 BuiltinID == AArch64::BI__builtin_arm_stlex) &&
868 "unexpected ARM builtin");
869 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
870 BuiltinID == ARM::BI__builtin_arm_ldaex ||
871 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
872 BuiltinID == AArch64::BI__builtin_arm_ldaex;
873
874 ASTContext &Context = getASTContext();
875 DeclRefExpr *DRE =
876 cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
877
878 // Ensure that we have the proper number of arguments.
879 if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))
880 return true;
881
882 // Inspect the pointer argument of the atomic builtin. This should always be
883 // a pointer type, whose element is an integral scalar or pointer type.
884 // Because it is a pointer type, we don't have to worry about any implicit
885 // casts here.
886 Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
887 ExprResult PointerArgRes =
889 if (PointerArgRes.isInvalid())
890 return true;
891 PointerArg = PointerArgRes.get();
892
893 const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
894 if (!pointerType) {
895 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
896 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
897 return true;
898 }
899
900 // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next
901 // task is to insert the appropriate casts into the AST. First work out just
902 // what the appropriate type is.
903 QualType ValType = pointerType->getPointeeType();
904 QualType AddrType = ValType.getUnqualifiedType().withVolatile();
905 if (IsLdrex)
906 AddrType.addConst();
907
908 // Issue a warning if the cast is dodgy.
909 CastKind CastNeeded = CK_NoOp;
910 if (!AddrType.isAtLeastAsQualifiedAs(ValType, getASTContext())) {
911 CastNeeded = CK_BitCast;
912 Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
913 << PointerArg->getType() << Context.getPointerType(AddrType)
914 << AssignmentAction::Passing << PointerArg->getSourceRange();
915 }
916
917 // Finally, do the cast and replace the argument with the corrected version.
918 AddrType = Context.getPointerType(AddrType);
919 PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);
920 if (PointerArgRes.isInvalid())
921 return true;
922 PointerArg = PointerArgRes.get();
923
924 TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
925
926 // In general, we allow ints, floats and pointers to be loaded and stored.
927 if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
928 !ValType->isBlockPointerType() && !ValType->isFloatingType()) {
929 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
930 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
931 return true;
932 }
933
934 // But ARM doesn't have instructions to deal with 128-bit versions.
935 if (Context.getTypeSize(ValType) > MaxWidth) {
936 assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate");
937 Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size)
938 << PointerArg->getType() << PointerArg->getSourceRange();
939 return true;
940 }
941
942 switch (ValType.getObjCLifetime()) {
945 // okay
946 break;
947
951 Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
952 << ValType << PointerArg->getSourceRange();
953 return true;
954 }
955
956 if (IsLdrex) {
957 TheCall->setType(ValType);
958 return false;
959 }
960
961 // Initialize the argument to be stored.
962 ExprResult ValArg = TheCall->getArg(0);
964 Context, ValType, /*consume*/ false);
965 ValArg = SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg);
966 if (ValArg.isInvalid())
967 return true;
968 TheCall->setArg(0, ValArg.get());
969
970 // __builtin_arm_strex always returns an int. It's marked as such in the .def,
971 // but the custom checker bypasses all default analysis.
972 TheCall->setType(Context.IntTy);
973 return false;
974}
975
977 unsigned BuiltinID,
978 CallExpr *TheCall) {
979 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
980 BuiltinID == ARM::BI__builtin_arm_ldaex ||
981 BuiltinID == ARM::BI__builtin_arm_strex ||
982 BuiltinID == ARM::BI__builtin_arm_stlex) {
983 return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64);
984 }
985
986 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
987 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
988 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
989 }
990
991 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
992 BuiltinID == ARM::BI__builtin_arm_wsr64)
993 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);
994
995 if (BuiltinID == ARM::BI__builtin_arm_rsr ||
996 BuiltinID == ARM::BI__builtin_arm_rsrp ||
997 BuiltinID == ARM::BI__builtin_arm_wsr ||
998 BuiltinID == ARM::BI__builtin_arm_wsrp)
999 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1000
1001 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1002 return true;
1003 if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall))
1004 return true;
1005 if (CheckCDEBuiltinFunctionCall(TI, BuiltinID, TheCall))
1006 return true;
1007
1008 // For intrinsics which take an immediate value as part of the instruction,
1009 // range check them here.
1010 // FIXME: VFP Intrinsics should error if VFP not present.
1011 switch (BuiltinID) {
1012 default:
1013 return false;
1014 case ARM::BI__builtin_arm_ssat:
1015 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);
1016 case ARM::BI__builtin_arm_usat:
1017 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1018 case ARM::BI__builtin_arm_ssat16:
1019 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
1020 case ARM::BI__builtin_arm_usat16:
1021 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
1022 case ARM::BI__builtin_arm_vcvtr_f:
1023 case ARM::BI__builtin_arm_vcvtr_d:
1024 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
1025 case ARM::BI__builtin_arm_dmb:
1026 case ARM::BI__builtin_arm_dsb:
1027 case ARM::BI__builtin_arm_isb:
1028 case ARM::BI__builtin_arm_dbg:
1029 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
1030 case ARM::BI__builtin_arm_cdp:
1031 case ARM::BI__builtin_arm_cdp2:
1032 case ARM::BI__builtin_arm_mcr:
1033 case ARM::BI__builtin_arm_mcr2:
1034 case ARM::BI__builtin_arm_mrc:
1035 case ARM::BI__builtin_arm_mrc2:
1036 case ARM::BI__builtin_arm_mcrr:
1037 case ARM::BI__builtin_arm_mcrr2:
1038 case ARM::BI__builtin_arm_mrrc:
1039 case ARM::BI__builtin_arm_mrrc2:
1040 case ARM::BI__builtin_arm_ldc:
1041 case ARM::BI__builtin_arm_ldcl:
1042 case ARM::BI__builtin_arm_ldc2:
1043 case ARM::BI__builtin_arm_ldc2l:
1044 case ARM::BI__builtin_arm_stc:
1045 case ARM::BI__builtin_arm_stcl:
1046 case ARM::BI__builtin_arm_stc2:
1047 case ARM::BI__builtin_arm_stc2l:
1048 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
1049 CheckARMCoprocessorImmediate(TI, TheCall->getArg(0),
1050 /*WantCDE*/ false);
1051 }
1052}
1053
1055 unsigned BuiltinID,
1056 CallExpr *TheCall) {
1057 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1058 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1059 BuiltinID == AArch64::BI__builtin_arm_strex ||
1060 BuiltinID == AArch64::BI__builtin_arm_stlex) {
1061 return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128);
1062 }
1063
1064 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
1065 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1066 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
1067 SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
1068 SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);
1069 }
1070
1071 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
1072 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
1073 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
1074 BuiltinID == AArch64::BI__builtin_arm_wsr128)
1075 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1076
1077 // Memory Tagging Extensions (MTE) Intrinsics
1078 if (BuiltinID == AArch64::BI__builtin_arm_irg ||
1079 BuiltinID == AArch64::BI__builtin_arm_addg ||
1080 BuiltinID == AArch64::BI__builtin_arm_gmi ||
1081 BuiltinID == AArch64::BI__builtin_arm_ldg ||
1082 BuiltinID == AArch64::BI__builtin_arm_stg ||
1083 BuiltinID == AArch64::BI__builtin_arm_subp) {
1084 return BuiltinARMMemoryTaggingCall(BuiltinID, TheCall);
1085 }
1086
1087 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
1088 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
1089 BuiltinID == AArch64::BI__builtin_arm_wsr ||
1090 BuiltinID == AArch64::BI__builtin_arm_wsrp)
1091 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1092
1093 // Only check the valid encoding range. Any constant in this range would be
1094 // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
1095 // an exception for incorrect registers. This matches MSVC behavior.
1096 if (BuiltinID == AArch64::BI_ReadStatusReg ||
1097 BuiltinID == AArch64::BI_WriteStatusReg)
1098 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
1099
1100 if (BuiltinID == AArch64::BI__getReg)
1101 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
1102
1103 if (BuiltinID == AArch64::BI__break)
1104 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1105
1106 if (BuiltinID == AArch64::BI__hlt)
1107 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1108
1109 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1110 return true;
1111
1112 if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall))
1113 return true;
1114
1115 if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall))
1116 return true;
1117
1118 // For intrinsics which take an immediate value as part of the instruction,
1119 // range check them here.
1120 unsigned i = 0, l = 0, u = 0;
1121 switch (BuiltinID) {
1122 default: return false;
1123 case AArch64::BI__builtin_arm_dmb:
1124 case AArch64::BI__builtin_arm_dsb:
1125 case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break;
1126 case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break;
1127 }
1128
1129 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
1130}
1131
1132namespace {
1133struct IntrinToName {
1134 uint32_t Id;
1135 int32_t FullName;
1136 int32_t ShortName;
1137};
1138} // unnamed namespace
1139
1140static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
1142 const char *IntrinNames) {
1143 AliasName.consume_front("__arm_");
1144 const IntrinToName *It =
1145 llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
1146 return L.Id < Id;
1147 });
1148 if (It == Map.end() || It->Id != BuiltinID)
1149 return false;
1150 StringRef FullName(&IntrinNames[It->FullName]);
1151 if (AliasName == FullName)
1152 return true;
1153 if (It->ShortName == -1)
1154 return false;
1155 StringRef ShortName(&IntrinNames[It->ShortName]);
1156 return AliasName == ShortName;
1157}
1158
1159bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1160#include "clang/Basic/arm_mve_builtin_aliases.inc"
1161 // The included file defines:
1162 // - ArrayRef<IntrinToName> Map
1163 // - const char IntrinNames[]
1164 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1165}
1166
1167bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1168#include "clang/Basic/arm_cde_builtin_aliases.inc"
1169 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1170}
1171
1172bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1173 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1174 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1175 return BuiltinID >= AArch64::FirstSVEBuiltin &&
1176 BuiltinID <= AArch64::LastSVEBuiltin;
1177}
1178
1179bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1180 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1181 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1182 return BuiltinID >= AArch64::FirstSMEBuiltin &&
1183 BuiltinID <= AArch64::LastSMEBuiltin;
1184}
1185
1187 ASTContext &Context = getASTContext();
1188 if (!AL.isArgIdent(0)) {
1189 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
1190 << AL << 1 << AANT_ArgumentIdentifier;
1191 return;
1192 }
1193
1194 IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
1195 unsigned BuiltinID = Ident->getBuiltinID();
1196 StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
1197
1198 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
1199 if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) &&
1200 !SmeAliasValid(BuiltinID, AliasName)) ||
1201 (!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) &&
1202 !CdeAliasValid(BuiltinID, AliasName))) {
1203 Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
1204 return;
1205 }
1206
1207 D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
1208}
1209
1211 Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT,
1212 FunctionType::ArmStateValue CurrentState, StringRef StateName) {
1213 auto CheckForIncompatibleAttr =
1214 [&](FunctionType::ArmStateValue IncompatibleState,
1215 StringRef IncompatibleStateName) {
1216 if (CurrentState == IncompatibleState) {
1217 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
1218 << (std::string("'__arm_new(\"") + StateName.str() + "\")'")
1219 << (std::string("'") + IncompatibleStateName.str() + "(\"" +
1220 StateName.str() + "\")'")
1221 << true;
1222 AL.setInvalid();
1223 }
1224 };
1225
1226 CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in");
1227 CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out");
1228 CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout");
1229 CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves");
1230 return AL.isInvalid();
1231}
1232
1234 if (!AL.getNumArgs()) {
1235 Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
1236 AL.setInvalid();
1237 return;
1238 }
1239
1240 std::vector<StringRef> NewState;
1241 if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) {
1242 for (StringRef S : ExistingAttr->newArgs())
1243 NewState.push_back(S);
1244 }
1245
1246 bool HasZA = false;
1247 bool HasZT0 = false;
1248 for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1249 StringRef StateName;
1250 SourceLocation LiteralLoc;
1251 if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
1252 return;
1253
1254 if (StateName == "za")
1255 HasZA = true;
1256 else if (StateName == "zt0")
1257 HasZT0 = true;
1258 else {
1259 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
1260 AL.setInvalid();
1261 return;
1262 }
1263
1264 if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates.
1265 NewState.push_back(StateName);
1266 }
1267
1268 if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) {
1270 FunctionType::getArmZAState(FPT->getAArch64SMEAttributes());
1271 if (HasZA && ZAState != FunctionType::ARM_None &&
1272 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za"))
1273 return;
1275 FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes());
1276 if (HasZT0 && ZT0State != FunctionType::ARM_None &&
1277 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0"))
1278 return;
1279 }
1280
1281 D->dropAttr<ArmNewAttr>();
1282 D->addAttr(::new (getASTContext()) ArmNewAttr(
1283 getASTContext(), AL, NewState.data(), NewState.size()));
1284}
1285
1287 if (getLangOpts().CPlusPlus && !D->getDeclContext()->isExternCContext()) {
1288 Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
1289 return;
1290 }
1291
1292 const auto *FD = cast<FunctionDecl>(D);
1293 if (!FD->isExternallyVisible()) {
1294 Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
1295 return;
1296 }
1297
1298 D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL));
1299}
1300
1302 // Check the attribute arguments.
1303 if (AL.getNumArgs() > 1) {
1304 Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
1305 return;
1306 }
1307
1308 StringRef Str;
1309 SourceLocation ArgLoc;
1310
1311 if (AL.getNumArgs() == 0)
1312 Str = "";
1313 else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1314 return;
1315
1316 ARMInterruptAttr::InterruptType Kind;
1317 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
1318 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1319 << AL << Str << ArgLoc;
1320 return;
1321 }
1322
1323 const TargetInfo &TI = getASTContext().getTargetInfo();
1324 if (TI.hasFeature("vfp"))
1325 Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1326
1327 D->addAttr(::new (getASTContext())
1328 ARMInterruptAttr(getASTContext(), AL, Kind));
1329}
1330
1331} // namespace clang
static constexpr Builtin::Info BuiltinInfo[]
Definition: Builtins.cpp:32
const Decl * D
Expr * E
enum clang::sema::@1712::IndirectLocalPathEntry::EntryKind Kind
uint32_t Id
Definition: SemaARM.cpp:1134
int32_t ShortName
Definition: SemaARM.cpp:1136
int32_t FullName
Definition: SemaARM.cpp:1135
This file declares semantic analysis functions specific to ARM.
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:1169
CanQualType FloatTy
Definition: ASTContext.h:1172
CanQualType DoubleTy
Definition: ASTContext.h:1172
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:682
CanQualType UnsignedLongTy
Definition: ASTContext.h:1170
CanQualType IntTy
Definition: ASTContext.h:1169
CanQualType SignedCharTy
Definition: ASTContext.h:1169
CanQualType UnsignedCharTy
Definition: ASTContext.h:1170
CanQualType UnsignedIntTy
Definition: ASTContext.h:1170
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:1171
CanQualType UnsignedShortTy
Definition: ASTContext.h:1170
CanQualType ShortTy
Definition: ASTContext.h:1169
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:799
CanQualType BFloat16Ty
Definition: ASTContext.h:1185
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
CanQualType LongLongTy
Definition: ASTContext.h:1169
CanQualType HalfTy
Definition: ASTContext.h:1184
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
SourceLocation getLoc() const
This class is used for builtin types like 'int'.
Definition: Type.h:3034
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
Definition: Builtins.h:266
const char * getRequiredFeatures(unsigned ID) const
Definition: Builtins.h:253
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2874
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3068
void setArg(unsigned Arg, Expr *ArgExpr)
setArg - Set the specified argument.
Definition: Expr.h:3081
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1638
Expr * getCallee()
Definition: Expr.h:3024
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3055
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1265
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:551
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:576
bool hasAttr() const
Definition: DeclBase.h:580
This represents one expression.
Definition: Expr.h:110
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3095
void setType(QualType t)
Definition: Expr.h:143
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3090
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Definition: Expr.h:830
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition: Expr.h:142
Represents a function declaration or definition.
Definition: Decl.h:1935
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5102
unsigned getAArch64SMEAttributes() const
Return a bitmask describing the SME attributes on the function type, see AArch64SMETypeAttributes for...
Definition: Type.h:5561
static ArmStateValue getArmZT0State(unsigned AttrBits)
Definition: Type.h:4613
static ArmStateValue getArmZAState(unsigned AttrBits)
Definition: Type.h:4609
@ SME_PStateSMEnabledMask
Definition: Type.h:4587
@ SME_PStateSMCompatibleMask
Definition: Type.h:4588
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.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition: Expr.h:3724
Describes an entity that is being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
Flags to identify the types for overloaded Neon builtins.
bool isUnsigned() const
unsigned getEltSizeInBits() const
EltType getEltType() const
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition: ParsedAttr.h:404
void setInvalid(bool b=true) const
Definition: ParsedAttr.h:360
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:386
bool isArgIdent(unsigned Arg) const
Definition: ParsedAttr.h:400
bool isInvalid() const
Definition: ParsedAttr.h:359
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3198
A (possibly-)qualified type.
Definition: Type.h:929
QualType withConst() const
Definition: Type.h:1154
void addConst()
Add the const type qualifier to this QualType.
Definition: Type.h:1151
QualType withVolatile() const
Definition: Type.h:1162
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition: Type.h:1433
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:8025
const Type * getTypePtrOrNull() const
Definition: Type.h:7935
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: Type.h:8114
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition: Type.h:354
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition: Type.h:347
@ OCL_None
There is no lifetime qualification on this type.
Definition: Type.h:343
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition: Type.h:357
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition: Type.h:360
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:976
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:649
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE)
Definition: SemaARM.cpp:832
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:689
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:717
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:816
bool PerformNeonImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int, int > > &ImmChecks, int OverloadType=-1)
Definition: SemaARM.cpp:511
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:807
void handleInterruptAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1301
bool PerformSVEImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int > > &ImmChecks)
Definition: SemaARM.cpp:530
void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1186
@ 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:1233
bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, unsigned MaxWidth)
Definition: SemaARM.cpp:857
bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1172
bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:1054
bool MveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1159
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:1286
bool CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, unsigned ArgIdx, unsigned EltBitWidth, unsigned VecBitWidth)
Definition: SemaARM.cpp:373
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:1179
bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1167
SemaARM(Sema &S)
Definition: SemaARM.cpp:23
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
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:463
bool BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, unsigned Multiple)
BuiltinConstantArgMultiple - Handle a check if argument ArgNum of CallExpr TheCall is a constant expr...
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:1568
ASTContext & Context
Definition: Sema.h:908
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:752
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:690
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:9634
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:640
AssignConvertType
AssignConvertType - All of the 'assignment' semantic checks return this enum to indicate whether the ...
Definition: Sema.h:7573
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:2144
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:9718
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:16805
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.
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:324
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:336
Exposes information about the current target.
Definition: TargetInfo.h:220
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1255
IntType getInt64Type() const
Definition: TargetInfo.h:404
uint32_t getARMCDECoprocMask() const
For ARM targets returns a mask defining which coprocessors are configured as Custom Datapath.
Definition: TargetInfo.h:1051
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
Definition: TargetInfo.h:1486
The base class of the type hierarchy.
Definition: Type.h:1828
bool isBlockPointerType() const
Definition: Type.h:8200
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8550
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:738
bool isFloatingType() const
Definition: Type.cpp:2283
bool isAnyPointerType() const
Definition: Type.h:8194
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8731
QualType getType() const
Definition: Decl.h:682
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 hasArmZAState(const FunctionDecl *FD)
Definition: SemaARM.cpp:625
static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, ArrayRef< IntrinToName > Map, const char *IntrinNames)
Definition: SemaARM.cpp:1140
static ArmSMEState getSMEState(unsigned BuiltinID)
Definition: SemaARM.cpp:639
static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, SemaARM::ArmStreamingType BuiltinType, unsigned BuiltinID)
Definition: SemaARM.cpp:559
ArmSMEState
Definition: SemaARM.cpp:359
@ ArmInOutZA
Definition: SemaARM.cpp:364
@ ArmZT0Mask
Definition: SemaARM.cpp:370
@ ArmInOutZT0
Definition: SemaARM.cpp:369
@ ArmInZA
Definition: SemaARM.cpp:362
@ ArmInZT0
Definition: SemaARM.cpp:367
@ ArmZAMask
Definition: SemaARM.cpp:365
@ ArmOutZA
Definition: SemaARM.cpp:363
@ ArmOutZT0
Definition: SemaARM.cpp:368
@ ArmNoState
Definition: SemaARM.cpp:360
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)
Definition: SemaARM.cpp:543
@ AANT_ArgumentIdentifier
Definition: ParsedAttr.h:1081
@ Result
The result type of a method or function.
static bool hasArmZT0State(const FunctionDecl *FD)
Definition: SemaARM.cpp:632
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:1210
IdentifierInfo * Ident
Definition: ParsedAttr.h:105