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"
18#include "clang/Sema/Sema.h"
19
20namespace clang {
21
23
24/// BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions
26 CallExpr *TheCall) {
27 ASTContext &Context = getASTContext();
28
29 if (BuiltinID == AArch64::BI__builtin_arm_irg) {
30 if (SemaRef.checkArgCount(TheCall, 2))
31 return true;
32 Expr *Arg0 = TheCall->getArg(0);
33 Expr *Arg1 = TheCall->getArg(1);
34
36 if (FirstArg.isInvalid())
37 return true;
38 QualType FirstArgType = FirstArg.get()->getType();
39 if (!FirstArgType->isAnyPointerType())
40 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
41 << "first" << FirstArgType << Arg0->getSourceRange();
42 TheCall->setArg(0, FirstArg.get());
43
45 if (SecArg.isInvalid())
46 return true;
47 QualType SecArgType = SecArg.get()->getType();
48 if (!SecArgType->isIntegerType())
49 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
50 << "second" << SecArgType << Arg1->getSourceRange();
51
52 // Derive the return type from the pointer argument.
53 TheCall->setType(FirstArgType);
54 return false;
55 }
56
57 if (BuiltinID == AArch64::BI__builtin_arm_addg) {
58 if (SemaRef.checkArgCount(TheCall, 2))
59 return true;
60
61 Expr *Arg0 = TheCall->getArg(0);
63 if (FirstArg.isInvalid())
64 return true;
65 QualType FirstArgType = FirstArg.get()->getType();
66 if (!FirstArgType->isAnyPointerType())
67 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
68 << "first" << FirstArgType << Arg0->getSourceRange();
69 TheCall->setArg(0, FirstArg.get());
70
71 // Derive the return type from the pointer argument.
72 TheCall->setType(FirstArgType);
73
74 // Second arg must be an constant in range [0,15]
75 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
76 }
77
78 if (BuiltinID == AArch64::BI__builtin_arm_gmi) {
79 if (SemaRef.checkArgCount(TheCall, 2))
80 return true;
81 Expr *Arg0 = TheCall->getArg(0);
82 Expr *Arg1 = TheCall->getArg(1);
83
85 if (FirstArg.isInvalid())
86 return true;
87 QualType FirstArgType = FirstArg.get()->getType();
88 if (!FirstArgType->isAnyPointerType())
89 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
90 << "first" << FirstArgType << Arg0->getSourceRange();
91
92 QualType SecArgType = Arg1->getType();
93 if (!SecArgType->isIntegerType())
94 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
95 << "second" << SecArgType << Arg1->getSourceRange();
96 TheCall->setType(Context.IntTy);
97 return false;
98 }
99
100 if (BuiltinID == AArch64::BI__builtin_arm_ldg ||
101 BuiltinID == AArch64::BI__builtin_arm_stg) {
102 if (SemaRef.checkArgCount(TheCall, 1))
103 return true;
104 Expr *Arg0 = TheCall->getArg(0);
106 if (FirstArg.isInvalid())
107 return true;
108
109 QualType FirstArgType = FirstArg.get()->getType();
110 if (!FirstArgType->isAnyPointerType())
111 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
112 << "first" << FirstArgType << Arg0->getSourceRange();
113 TheCall->setArg(0, FirstArg.get());
114
115 // Derive the return type from the pointer argument.
116 if (BuiltinID == AArch64::BI__builtin_arm_ldg)
117 TheCall->setType(FirstArgType);
118 return false;
119 }
120
121 if (BuiltinID == AArch64::BI__builtin_arm_subp) {
122 Expr *ArgA = TheCall->getArg(0);
123 Expr *ArgB = TheCall->getArg(1);
124
127
128 if (ArgExprA.isInvalid() || ArgExprB.isInvalid())
129 return true;
130
131 QualType ArgTypeA = ArgExprA.get()->getType();
132 QualType ArgTypeB = ArgExprB.get()->getType();
133
134 auto isNull = [&](Expr *E) -> bool {
135 return E->isNullPointerConstant(Context,
137 };
138
139 // argument should be either a pointer or null
140 if (!ArgTypeA->isAnyPointerType() && !isNull(ArgA))
141 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
142 << "first" << ArgTypeA << ArgA->getSourceRange();
143
144 if (!ArgTypeB->isAnyPointerType() && !isNull(ArgB))
145 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
146 << "second" << ArgTypeB << ArgB->getSourceRange();
147
148 // Ensure Pointee types are compatible
149 if (ArgTypeA->isAnyPointerType() && !isNull(ArgA) &&
150 ArgTypeB->isAnyPointerType() && !isNull(ArgB)) {
151 QualType pointeeA = ArgTypeA->getPointeeType();
152 QualType pointeeB = ArgTypeB->getPointeeType();
153 if (!Context.typesAreCompatible(
154 Context.getCanonicalType(pointeeA).getUnqualifiedType(),
155 Context.getCanonicalType(pointeeB).getUnqualifiedType())) {
156 return Diag(TheCall->getBeginLoc(),
157 diag::err_typecheck_sub_ptr_compatible)
158 << ArgTypeA << ArgTypeB << ArgA->getSourceRange()
159 << ArgB->getSourceRange();
160 }
161 }
162
163 // at least one argument should be pointer type
164 if (!ArgTypeA->isAnyPointerType() && !ArgTypeB->isAnyPointerType())
165 return Diag(TheCall->getBeginLoc(), diag::err_memtag_any2arg_pointer)
166 << ArgTypeA << ArgTypeB << ArgA->getSourceRange();
167
168 if (isNull(ArgA)) // adopt type of the other pointer
169 ArgExprA =
170 SemaRef.ImpCastExprToType(ArgExprA.get(), ArgTypeB, CK_NullToPointer);
171
172 if (isNull(ArgB))
173 ArgExprB =
174 SemaRef.ImpCastExprToType(ArgExprB.get(), ArgTypeA, CK_NullToPointer);
175
176 TheCall->setArg(0, ArgExprA.get());
177 TheCall->setArg(1, ArgExprB.get());
178 TheCall->setType(Context.LongLongTy);
179 return false;
180 }
181 assert(false && "Unhandled ARM MTE intrinsic");
182 return true;
183}
184
185/// BuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr
186/// TheCall is an ARM/AArch64 special register string literal.
187bool SemaARM::BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
188 int ArgNum, unsigned ExpectedFieldNum,
189 bool AllowName) {
190 bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
191 BuiltinID == ARM::BI__builtin_arm_wsr64 ||
192 BuiltinID == ARM::BI__builtin_arm_rsr ||
193 BuiltinID == ARM::BI__builtin_arm_rsrp ||
194 BuiltinID == ARM::BI__builtin_arm_wsr ||
195 BuiltinID == ARM::BI__builtin_arm_wsrp;
196 bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
197 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
198 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
199 BuiltinID == AArch64::BI__builtin_arm_wsr128 ||
200 BuiltinID == AArch64::BI__builtin_arm_rsr ||
201 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
202 BuiltinID == AArch64::BI__builtin_arm_wsr ||
203 BuiltinID == AArch64::BI__builtin_arm_wsrp;
204 assert((IsARMBuiltin || IsAArch64Builtin) && "Unexpected ARM builtin.");
205
206 // We can't check the value of a dependent argument.
207 Expr *Arg = TheCall->getArg(ArgNum);
208 if (Arg->isTypeDependent() || Arg->isValueDependent())
209 return false;
210
211 // Check if the argument is a string literal.
212 if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
213 return Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
214 << Arg->getSourceRange();
215
216 // Check the type of special register given.
217 StringRef Reg = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
219 Reg.split(Fields, ":");
220
221 if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
222 return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
223 << Arg->getSourceRange();
224
225 // If the string is the name of a register then we cannot check that it is
226 // valid here but if the string is of one the forms described in ACLE then we
227 // can check that the supplied fields are integers and within the valid
228 // ranges.
229 if (Fields.size() > 1) {
230 bool FiveFields = Fields.size() == 5;
231
232 bool ValidString = true;
233 if (IsARMBuiltin) {
234 ValidString &= Fields[0].starts_with_insensitive("cp") ||
235 Fields[0].starts_with_insensitive("p");
236 if (ValidString)
237 Fields[0] = Fields[0].drop_front(
238 Fields[0].starts_with_insensitive("cp") ? 2 : 1);
239
240 ValidString &= Fields[2].starts_with_insensitive("c");
241 if (ValidString)
242 Fields[2] = Fields[2].drop_front(1);
243
244 if (FiveFields) {
245 ValidString &= Fields[3].starts_with_insensitive("c");
246 if (ValidString)
247 Fields[3] = Fields[3].drop_front(1);
248 }
249 }
250
251 SmallVector<int, 5> Ranges;
252 if (FiveFields)
253 Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 15, 15, 7});
254 else
255 Ranges.append({15, 7, 15});
256
257 for (unsigned i = 0; i < Fields.size(); ++i) {
258 int IntField;
259 ValidString &= !Fields[i].getAsInteger(10, IntField);
260 ValidString &= (IntField >= 0 && IntField <= Ranges[i]);
261 }
262
263 if (!ValidString)
264 return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
265 << Arg->getSourceRange();
266 } else if (IsAArch64Builtin && Fields.size() == 1) {
267 // This code validates writes to PSTATE registers.
268
269 // Not a write.
270 if (TheCall->getNumArgs() != 2)
271 return false;
272
273 // The 128-bit system register accesses do not touch PSTATE.
274 if (BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
275 BuiltinID == AArch64::BI__builtin_arm_wsr128)
276 return false;
277
278 // These are the named PSTATE accesses using "MSR (immediate)" instructions,
279 // along with the upper limit on the immediates allowed.
280 auto MaxLimit = llvm::StringSwitch<std::optional<unsigned>>(Reg)
281 .CaseLower("spsel", 15)
282 .CaseLower("daifclr", 15)
283 .CaseLower("daifset", 15)
284 .CaseLower("pan", 15)
285 .CaseLower("uao", 15)
286 .CaseLower("dit", 15)
287 .CaseLower("ssbs", 15)
288 .CaseLower("tco", 15)
289 .CaseLower("allint", 1)
290 .CaseLower("pm", 1)
291 .Default(std::nullopt);
292
293 // If this is not a named PSTATE, just continue without validating, as this
294 // will be lowered to an "MSR (register)" instruction directly
295 if (!MaxLimit)
296 return false;
297
298 // Here we only allow constants in the range for that pstate, as required by
299 // the ACLE.
300 //
301 // While clang also accepts the names of system registers in its ACLE
302 // intrinsics, we prevent this with the PSTATE names used in MSR (immediate)
303 // as the value written via a register is different to the value used as an
304 // immediate to have the same effect. e.g., for the instruction `msr tco,
305 // x0`, it is bit 25 of register x0 that is written into PSTATE.TCO, but
306 // with `msr tco, #imm`, it is bit 0 of xN that is written into PSTATE.TCO.
307 //
308 // If a programmer wants to codegen the MSR (register) form of `msr tco,
309 // xN`, they can still do so by specifying the register using five
310 // colon-separated numbers in a string.
311 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit);
312 }
313
314 return false;
315}
316
317// Get the valid immediate range for the specified NEON type code.
318static unsigned RFT(unsigned t, bool shift = false, bool ForceQuad = false) {
320 int IsQuad = ForceQuad ? true : Type.isQuad();
321 switch (Type.getEltType()) {
324 return shift ? 7 : (8 << IsQuad) - 1;
327 return shift ? 15 : (4 << IsQuad) - 1;
329 return shift ? 31 : (2 << IsQuad) - 1;
332 return shift ? 63 : (1 << IsQuad) - 1;
334 return shift ? 127 : (1 << IsQuad) - 1;
336 assert(!shift && "cannot shift float types!");
337 return (4 << IsQuad) - 1;
339 assert(!shift && "cannot shift float types!");
340 return (2 << IsQuad) - 1;
342 assert(!shift && "cannot shift float types!");
343 return (1 << IsQuad) - 1;
345 assert(!shift && "cannot shift float types!");
346 return (4 << IsQuad) - 1;
347 }
348 llvm_unreachable("Invalid NeonTypeFlag!");
349}
350
351/// getNeonEltType - Return the QualType corresponding to the elements of
352/// the vector type specified by the NeonTypeFlags. This is used to check
353/// the pointer arguments for Neon load/store intrinsics.
355 bool IsPolyUnsigned, bool IsInt64Long) {
356 switch (Flags.getEltType()) {
358 return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
360 return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
362 return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
364 if (IsInt64Long)
365 return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
366 else
367 return Flags.isUnsigned() ? Context.UnsignedLongLongTy
368 : Context.LongLongTy;
370 return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
372 return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
374 if (IsInt64Long)
375 return Context.UnsignedLongTy;
376 else
377 return Context.UnsignedLongLongTy;
379 break;
381 return Context.HalfTy;
383 return Context.FloatTy;
385 return Context.DoubleTy;
387 return Context.BFloat16Ty;
388 }
389 llvm_unreachable("Invalid NeonTypeFlag!");
390}
391
392enum ArmSMEState : unsigned {
394
395 ArmInZA = 0b01,
396 ArmOutZA = 0b10,
398 ArmZAMask = 0b11,
399
400 ArmInZT0 = 0b01 << 2,
401 ArmOutZT0 = 0b10 << 2,
402 ArmInOutZT0 = 0b11 << 2,
403 ArmZT0Mask = 0b11 << 2
405
407 CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) {
408 // Perform all the immediate checks for this builtin call.
409 bool HasError = false;
410 for (auto &I : ImmChecks) {
411 int ArgNum, CheckTy, ElementSizeInBits;
412 std::tie(ArgNum, CheckTy, ElementSizeInBits) = I;
413
414 typedef bool (*OptionSetCheckFnTy)(int64_t Value);
415
416 // Function that checks whether the operand (ArgNum) is an immediate
417 // that is one of the predefined values.
418 auto CheckImmediateInSet = [&](OptionSetCheckFnTy CheckImm,
419 int ErrDiag) -> bool {
420 // We can't check the value of a dependent argument.
421 Expr *Arg = TheCall->getArg(ArgNum);
422 if (Arg->isTypeDependent() || Arg->isValueDependent())
423 return false;
424
425 // Check constant-ness first.
426 llvm::APSInt Imm;
427 if (SemaRef.BuiltinConstantArg(TheCall, ArgNum, Imm))
428 return true;
429
430 if (!CheckImm(Imm.getSExtValue()))
431 return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
432 return false;
433 };
434
435 switch ((SVETypeFlags::ImmCheckType)CheckTy) {
436 case SVETypeFlags::ImmCheck0_31:
437 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 31))
438 HasError = true;
439 break;
440 case SVETypeFlags::ImmCheck0_13:
441 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 13))
442 HasError = true;
443 break;
444 case SVETypeFlags::ImmCheck1_16:
445 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1, 16))
446 HasError = true;
447 break;
448 case SVETypeFlags::ImmCheck0_7:
449 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 7))
450 HasError = true;
451 break;
452 case SVETypeFlags::ImmCheck1_1:
453 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1, 1))
454 HasError = true;
455 break;
456 case SVETypeFlags::ImmCheck1_3:
457 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1, 3))
458 HasError = true;
459 break;
460 case SVETypeFlags::ImmCheck1_7:
461 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1, 7))
462 HasError = true;
463 break;
464 case SVETypeFlags::ImmCheckExtract:
465 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
466 (2048 / ElementSizeInBits) - 1))
467 HasError = true;
468 break;
469 case SVETypeFlags::ImmCheckShiftRight:
470 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1,
471 ElementSizeInBits))
472 HasError = true;
473 break;
474 case SVETypeFlags::ImmCheckShiftRightNarrow:
475 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1,
476 ElementSizeInBits / 2))
477 HasError = true;
478 break;
479 case SVETypeFlags::ImmCheckShiftLeft:
480 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
481 ElementSizeInBits - 1))
482 HasError = true;
483 break;
484 case SVETypeFlags::ImmCheckLaneIndex:
485 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
486 (128 / (1 * ElementSizeInBits)) - 1))
487 HasError = true;
488 break;
489 case SVETypeFlags::ImmCheckLaneIndexCompRotate:
490 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
491 (128 / (2 * ElementSizeInBits)) - 1))
492 HasError = true;
493 break;
494 case SVETypeFlags::ImmCheckLaneIndexDot:
495 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
496 (128 / (4 * ElementSizeInBits)) - 1))
497 HasError = true;
498 break;
499 case SVETypeFlags::ImmCheckComplexRot90_270:
500 if (CheckImmediateInSet([](int64_t V) { return V == 90 || V == 270; },
501 diag::err_rotation_argument_to_cadd))
502 HasError = true;
503 break;
504 case SVETypeFlags::ImmCheckComplexRotAll90:
505 if (CheckImmediateInSet(
506 [](int64_t V) {
507 return V == 0 || V == 90 || V == 180 || V == 270;
508 },
509 diag::err_rotation_argument_to_cmla))
510 HasError = true;
511 break;
512 case SVETypeFlags::ImmCheck0_1:
513 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 1))
514 HasError = true;
515 break;
516 case SVETypeFlags::ImmCheck0_2:
517 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 2))
518 HasError = true;
519 break;
520 case SVETypeFlags::ImmCheck0_3:
521 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 3))
522 HasError = true;
523 break;
524 case SVETypeFlags::ImmCheck0_0:
525 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 0))
526 HasError = true;
527 break;
528 case SVETypeFlags::ImmCheck0_15:
529 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 15))
530 HasError = true;
531 break;
532 case SVETypeFlags::ImmCheck0_255:
533 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 255))
534 HasError = true;
535 break;
536 case SVETypeFlags::ImmCheck2_4_Mul2:
537 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 2, 4) ||
538 SemaRef.BuiltinConstantArgMultiple(TheCall, ArgNum, 2))
539 HasError = true;
540 break;
541 }
542 }
543
544 return HasError;
545}
546
548 if (FD->hasAttr<ArmLocallyStreamingAttr>())
550 if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
551 if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
552 if (FPT->getAArch64SMEAttributes() &
555 if (FPT->getAArch64SMEAttributes() &
558 }
559 }
561}
562
563static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
564 const FunctionDecl *FD,
566 unsigned BuiltinID) {
568
569 // Check if the intrinsic is available in the right mode, i.e.
570 // * When compiling for SME only, the caller must be in streaming mode.
571 // * When compiling for SVE only, the caller must be in non-streaming mode.
572 // * When compiling for both SVE and SME, the caller can be in either mode.
574 auto DisableFeatures = [](llvm::StringMap<bool> &Map, StringRef S) {
575 for (StringRef K : Map.keys())
576 if (K.starts_with(S))
577 Map[K] = false;
578 };
579
580 llvm::StringMap<bool> CallerFeatureMapWithoutSVE;
581 S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSVE, FD);
582 DisableFeatures(CallerFeatureMapWithoutSVE, "sve");
583
584 // Avoid emitting diagnostics for a function that can never compile.
585 if (FnType == SemaARM::ArmStreaming && !CallerFeatureMapWithoutSVE["sme"])
586 return false;
587
588 llvm::StringMap<bool> CallerFeatureMapWithoutSME;
589 S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSME, FD);
590 DisableFeatures(CallerFeatureMapWithoutSME, "sme");
591
592 // We know the builtin requires either some combination of SVE flags, or
593 // some combination of SME flags, but we need to figure out which part
594 // of the required features is satisfied by the target features.
595 //
596 // For a builtin with target guard 'sve2p1|sme2', if we compile with
597 // '+sve2p1,+sme', then we know that it satisfies the 'sve2p1' part if we
598 // evaluate the features for '+sve2p1,+sme,+nosme'.
599 //
600 // Similarly, if we compile with '+sve2,+sme2', then we know it satisfies
601 // the 'sme2' part if we evaluate the features for '+sve2,+sme2,+nosve'.
602 StringRef BuiltinTargetGuards(
604 bool SatisfiesSVE = Builtin::evaluateRequiredTargetFeatures(
605 BuiltinTargetGuards, CallerFeatureMapWithoutSME);
606 bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures(
607 BuiltinTargetGuards, CallerFeatureMapWithoutSVE);
608
609 if ((SatisfiesSVE && SatisfiesSME) ||
610 (SatisfiesSVE && FnType == SemaARM::ArmStreamingCompatible))
611 return false;
612 else if (SatisfiesSVE)
614 else if (SatisfiesSME)
616 else
617 // This should be diagnosed by CodeGen
618 return false;
619 }
620
621 if (FnType != SemaARM::ArmNonStreaming &&
623 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
624 << TheCall->getSourceRange() << "non-streaming";
625 else if (FnType != SemaARM::ArmStreaming &&
627 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
628 << TheCall->getSourceRange() << "streaming";
629 else
630 return false;
631
632 return true;
633}
634
635static bool hasArmZAState(const FunctionDecl *FD) {
636 const auto *T = FD->getType()->getAs<FunctionProtoType>();
639 (FD->hasAttr<ArmNewAttr>() && FD->getAttr<ArmNewAttr>()->isNewZA());
640}
641
642static bool hasArmZT0State(const FunctionDecl *FD) {
643 const auto *T = FD->getType()->getAs<FunctionProtoType>();
646 (FD->hasAttr<ArmNewAttr>() && FD->getAttr<ArmNewAttr>()->isNewZT0());
647}
648
649static ArmSMEState getSMEState(unsigned BuiltinID) {
650 switch (BuiltinID) {
651 default:
652 return ArmNoState;
653#define GET_SME_BUILTIN_GET_STATE
654#include "clang/Basic/arm_sme_builtins_za_state.inc"
655#undef GET_SME_BUILTIN_GET_STATE
656 }
657}
658
660 CallExpr *TheCall) {
661 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
662 std::optional<ArmStreamingType> BuiltinType;
663
664 switch (BuiltinID) {
665#define GET_SME_STREAMING_ATTRS
666#include "clang/Basic/arm_sme_streaming_attrs.inc"
667#undef GET_SME_STREAMING_ATTRS
668 }
669
670 if (BuiltinType &&
671 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
672 return true;
673
674 if ((getSMEState(BuiltinID) & ArmZAMask) && !hasArmZAState(FD))
675 Diag(TheCall->getBeginLoc(),
676 diag::warn_attribute_arm_za_builtin_no_za_state)
677 << TheCall->getSourceRange();
678
679 if ((getSMEState(BuiltinID) & ArmZT0Mask) && !hasArmZT0State(FD))
680 Diag(TheCall->getBeginLoc(),
681 diag::warn_attribute_arm_zt0_builtin_no_zt0_state)
682 << TheCall->getSourceRange();
683 }
684
685 // Range check SME intrinsics that take immediate values.
687
688 switch (BuiltinID) {
689 default:
690 return false;
691#define GET_SME_IMMEDIATE_CHECK
692#include "clang/Basic/arm_sme_sema_rangechecks.inc"
693#undef GET_SME_IMMEDIATE_CHECK
694 }
695
696 return ParseSVEImmChecks(TheCall, ImmChecks);
697}
698
700 CallExpr *TheCall) {
701 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
702 std::optional<ArmStreamingType> BuiltinType;
703
704 switch (BuiltinID) {
705#define GET_SVE_STREAMING_ATTRS
706#include "clang/Basic/arm_sve_streaming_attrs.inc"
707#undef GET_SVE_STREAMING_ATTRS
708 }
709 if (BuiltinType &&
710 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
711 return true;
712 }
713 // Range check SVE intrinsics that take immediate values.
715
716 switch (BuiltinID) {
717 default:
718 return false;
719#define GET_SVE_IMMEDIATE_CHECK
720#include "clang/Basic/arm_sve_sema_rangechecks.inc"
721#undef GET_SVE_IMMEDIATE_CHECK
722 }
723
724 return ParseSVEImmChecks(TheCall, ImmChecks);
725}
726
728 unsigned BuiltinID,
729 CallExpr *TheCall) {
730 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
731
732 switch (BuiltinID) {
733 default:
734 break;
735#define GET_NEON_BUILTINS
736#define TARGET_BUILTIN(id, ...) case NEON::BI##id:
737#define BUILTIN(id, ...) case NEON::BI##id:
738#include "clang/Basic/arm_neon.inc"
740 BuiltinID))
741 return true;
742 break;
743#undef TARGET_BUILTIN
744#undef BUILTIN
745#undef GET_NEON_BUILTINS
746 }
747 }
748
749 llvm::APSInt Result;
750 uint64_t mask = 0;
751 unsigned TV = 0;
752 int PtrArgNum = -1;
753 bool HasConstPtr = false;
754 switch (BuiltinID) {
755#define GET_NEON_OVERLOAD_CHECK
756#include "clang/Basic/arm_fp16.inc"
757#include "clang/Basic/arm_neon.inc"
758#undef GET_NEON_OVERLOAD_CHECK
759 }
760
761 // For NEON intrinsics which are overloaded on vector element type, validate
762 // the immediate which specifies which variant to emit.
763 unsigned ImmArg = TheCall->getNumArgs() - 1;
764 if (mask) {
765 if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result))
766 return true;
767
768 TV = Result.getLimitedValue(64);
769 if ((TV > 63) || (mask & (1ULL << TV)) == 0)
770 return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
771 << TheCall->getArg(ImmArg)->getSourceRange();
772 }
773
774 if (PtrArgNum >= 0) {
775 // Check that pointer arguments have the specified type.
776 Expr *Arg = TheCall->getArg(PtrArgNum);
777 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
778 Arg = ICE->getSubExpr();
780 QualType RHSTy = RHS.get()->getType();
781
782 llvm::Triple::ArchType Arch = TI.getTriple().getArch();
783 bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
784 Arch == llvm::Triple::aarch64_32 ||
785 Arch == llvm::Triple::aarch64_be;
786 bool IsInt64Long = TI.getInt64Type() == TargetInfo::SignedLong;
788 IsPolyUnsigned, IsInt64Long);
789 if (HasConstPtr)
790 EltTy = EltTy.withConst();
791 QualType LHSTy = getASTContext().getPointerType(EltTy);
793 ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);
794 if (RHS.isInvalid())
795 return true;
796 if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy,
797 RHSTy, RHS.get(), Sema::AA_Assigning))
798 return true;
799 }
800
801 // For NEON intrinsics which take an immediate value as part of the
802 // instruction, range check them here.
803 unsigned i = 0, l = 0, u = 0;
804 switch (BuiltinID) {
805 default:
806 return false;
807#define GET_NEON_IMMEDIATE_CHECK
808#include "clang/Basic/arm_fp16.inc"
809#include "clang/Basic/arm_neon.inc"
810#undef GET_NEON_IMMEDIATE_CHECK
811 }
812
813 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
814}
815
817 CallExpr *TheCall) {
818 switch (BuiltinID) {
819 default:
820 return false;
821#include "clang/Basic/arm_mve_builtin_sema.inc"
822 }
823}
824
826 unsigned BuiltinID,
827 CallExpr *TheCall) {
828 bool Err = false;
829 switch (BuiltinID) {
830 default:
831 return false;
832#include "clang/Basic/arm_cde_builtin_sema.inc"
833 }
834
835 if (Err)
836 return true;
837
838 return CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), /*WantCDE*/ true);
839}
840
842 const Expr *CoprocArg,
843 bool WantCDE) {
844 ASTContext &Context = getASTContext();
846 return false;
847
848 // We can't check the value of a dependent argument.
849 if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
850 return false;
851
852 llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context);
853 int64_t CoprocNo = CoprocNoAP.getExtValue();
854 assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
855
856 uint32_t CDECoprocMask = TI.getARMCDECoprocMask();
857 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
858
859 if (IsCDECoproc != WantCDE)
860 return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
861 << (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange();
862
863 return false;
864}
865
867 CallExpr *TheCall,
868 unsigned MaxWidth) {
869 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
870 BuiltinID == ARM::BI__builtin_arm_ldaex ||
871 BuiltinID == ARM::BI__builtin_arm_strex ||
872 BuiltinID == ARM::BI__builtin_arm_stlex ||
873 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
874 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
875 BuiltinID == AArch64::BI__builtin_arm_strex ||
876 BuiltinID == AArch64::BI__builtin_arm_stlex) &&
877 "unexpected ARM builtin");
878 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
879 BuiltinID == ARM::BI__builtin_arm_ldaex ||
880 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
881 BuiltinID == AArch64::BI__builtin_arm_ldaex;
882
883 ASTContext &Context = getASTContext();
884 DeclRefExpr *DRE =
885 cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
886
887 // Ensure that we have the proper number of arguments.
888 if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))
889 return true;
890
891 // Inspect the pointer argument of the atomic builtin. This should always be
892 // a pointer type, whose element is an integral scalar or pointer type.
893 // Because it is a pointer type, we don't have to worry about any implicit
894 // casts here.
895 Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
896 ExprResult PointerArgRes =
898 if (PointerArgRes.isInvalid())
899 return true;
900 PointerArg = PointerArgRes.get();
901
902 const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
903 if (!pointerType) {
904 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
905 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
906 return true;
907 }
908
909 // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next
910 // task is to insert the appropriate casts into the AST. First work out just
911 // what the appropriate type is.
912 QualType ValType = pointerType->getPointeeType();
913 QualType AddrType = ValType.getUnqualifiedType().withVolatile();
914 if (IsLdrex)
915 AddrType.addConst();
916
917 // Issue a warning if the cast is dodgy.
918 CastKind CastNeeded = CK_NoOp;
919 if (!AddrType.isAtLeastAsQualifiedAs(ValType)) {
920 CastNeeded = CK_BitCast;
921 Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
922 << PointerArg->getType() << Context.getPointerType(AddrType)
923 << Sema::AA_Passing << PointerArg->getSourceRange();
924 }
925
926 // Finally, do the cast and replace the argument with the corrected version.
927 AddrType = Context.getPointerType(AddrType);
928 PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);
929 if (PointerArgRes.isInvalid())
930 return true;
931 PointerArg = PointerArgRes.get();
932
933 TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
934
935 // In general, we allow ints, floats and pointers to be loaded and stored.
936 if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
937 !ValType->isBlockPointerType() && !ValType->isFloatingType()) {
938 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
939 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
940 return true;
941 }
942
943 // But ARM doesn't have instructions to deal with 128-bit versions.
944 if (Context.getTypeSize(ValType) > MaxWidth) {
945 assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate");
946 Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size)
947 << PointerArg->getType() << PointerArg->getSourceRange();
948 return true;
949 }
950
951 switch (ValType.getObjCLifetime()) {
954 // okay
955 break;
956
960 Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
961 << ValType << PointerArg->getSourceRange();
962 return true;
963 }
964
965 if (IsLdrex) {
966 TheCall->setType(ValType);
967 return false;
968 }
969
970 // Initialize the argument to be stored.
971 ExprResult ValArg = TheCall->getArg(0);
973 Context, ValType, /*consume*/ false);
974 ValArg = SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg);
975 if (ValArg.isInvalid())
976 return true;
977 TheCall->setArg(0, ValArg.get());
978
979 // __builtin_arm_strex always returns an int. It's marked as such in the .def,
980 // but the custom checker bypasses all default analysis.
981 TheCall->setType(Context.IntTy);
982 return false;
983}
984
986 unsigned BuiltinID,
987 CallExpr *TheCall) {
988 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
989 BuiltinID == ARM::BI__builtin_arm_ldaex ||
990 BuiltinID == ARM::BI__builtin_arm_strex ||
991 BuiltinID == ARM::BI__builtin_arm_stlex) {
992 return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64);
993 }
994
995 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
996 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
997 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
998 }
999
1000 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
1001 BuiltinID == ARM::BI__builtin_arm_wsr64)
1002 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);
1003
1004 if (BuiltinID == ARM::BI__builtin_arm_rsr ||
1005 BuiltinID == ARM::BI__builtin_arm_rsrp ||
1006 BuiltinID == ARM::BI__builtin_arm_wsr ||
1007 BuiltinID == ARM::BI__builtin_arm_wsrp)
1008 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1009
1010 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1011 return true;
1012 if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall))
1013 return true;
1014 if (CheckCDEBuiltinFunctionCall(TI, BuiltinID, TheCall))
1015 return true;
1016
1017 // For intrinsics which take an immediate value as part of the instruction,
1018 // range check them here.
1019 // FIXME: VFP Intrinsics should error if VFP not present.
1020 switch (BuiltinID) {
1021 default:
1022 return false;
1023 case ARM::BI__builtin_arm_ssat:
1024 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);
1025 case ARM::BI__builtin_arm_usat:
1026 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1027 case ARM::BI__builtin_arm_ssat16:
1028 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
1029 case ARM::BI__builtin_arm_usat16:
1030 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
1031 case ARM::BI__builtin_arm_vcvtr_f:
1032 case ARM::BI__builtin_arm_vcvtr_d:
1033 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
1034 case ARM::BI__builtin_arm_dmb:
1035 case ARM::BI__builtin_arm_dsb:
1036 case ARM::BI__builtin_arm_isb:
1037 case ARM::BI__builtin_arm_dbg:
1038 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
1039 case ARM::BI__builtin_arm_cdp:
1040 case ARM::BI__builtin_arm_cdp2:
1041 case ARM::BI__builtin_arm_mcr:
1042 case ARM::BI__builtin_arm_mcr2:
1043 case ARM::BI__builtin_arm_mrc:
1044 case ARM::BI__builtin_arm_mrc2:
1045 case ARM::BI__builtin_arm_mcrr:
1046 case ARM::BI__builtin_arm_mcrr2:
1047 case ARM::BI__builtin_arm_mrrc:
1048 case ARM::BI__builtin_arm_mrrc2:
1049 case ARM::BI__builtin_arm_ldc:
1050 case ARM::BI__builtin_arm_ldcl:
1051 case ARM::BI__builtin_arm_ldc2:
1052 case ARM::BI__builtin_arm_ldc2l:
1053 case ARM::BI__builtin_arm_stc:
1054 case ARM::BI__builtin_arm_stcl:
1055 case ARM::BI__builtin_arm_stc2:
1056 case ARM::BI__builtin_arm_stc2l:
1057 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
1058 CheckARMCoprocessorImmediate(TI, TheCall->getArg(0),
1059 /*WantCDE*/ false);
1060 }
1061}
1062
1064 unsigned BuiltinID,
1065 CallExpr *TheCall) {
1066 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1067 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1068 BuiltinID == AArch64::BI__builtin_arm_strex ||
1069 BuiltinID == AArch64::BI__builtin_arm_stlex) {
1070 return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128);
1071 }
1072
1073 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
1074 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1075 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
1076 SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
1077 SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);
1078 }
1079
1080 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
1081 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
1082 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
1083 BuiltinID == AArch64::BI__builtin_arm_wsr128)
1084 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1085
1086 // Memory Tagging Extensions (MTE) Intrinsics
1087 if (BuiltinID == AArch64::BI__builtin_arm_irg ||
1088 BuiltinID == AArch64::BI__builtin_arm_addg ||
1089 BuiltinID == AArch64::BI__builtin_arm_gmi ||
1090 BuiltinID == AArch64::BI__builtin_arm_ldg ||
1091 BuiltinID == AArch64::BI__builtin_arm_stg ||
1092 BuiltinID == AArch64::BI__builtin_arm_subp) {
1093 return BuiltinARMMemoryTaggingCall(BuiltinID, TheCall);
1094 }
1095
1096 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
1097 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
1098 BuiltinID == AArch64::BI__builtin_arm_wsr ||
1099 BuiltinID == AArch64::BI__builtin_arm_wsrp)
1100 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1101
1102 // Only check the valid encoding range. Any constant in this range would be
1103 // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
1104 // an exception for incorrect registers. This matches MSVC behavior.
1105 if (BuiltinID == AArch64::BI_ReadStatusReg ||
1106 BuiltinID == AArch64::BI_WriteStatusReg)
1107 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
1108
1109 if (BuiltinID == AArch64::BI__getReg)
1110 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
1111
1112 if (BuiltinID == AArch64::BI__break)
1113 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1114
1115 if (BuiltinID == AArch64::BI__hlt)
1116 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1117
1118 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1119 return true;
1120
1121 if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall))
1122 return true;
1123
1124 if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall))
1125 return true;
1126
1127 // For intrinsics which take an immediate value as part of the instruction,
1128 // range check them here.
1129 unsigned i = 0, l = 0, u = 0;
1130 switch (BuiltinID) {
1131 default: return false;
1132 case AArch64::BI__builtin_arm_dmb:
1133 case AArch64::BI__builtin_arm_dsb:
1134 case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break;
1135 case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break;
1136 }
1137
1138 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
1139}
1140
1141namespace {
1142struct IntrinToName {
1143 uint32_t Id;
1144 int32_t FullName;
1145 int32_t ShortName;
1146};
1147} // unnamed namespace
1148
1149static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
1151 const char *IntrinNames) {
1152 AliasName.consume_front("__arm_");
1153 const IntrinToName *It =
1154 llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
1155 return L.Id < Id;
1156 });
1157 if (It == Map.end() || It->Id != BuiltinID)
1158 return false;
1159 StringRef FullName(&IntrinNames[It->FullName]);
1160 if (AliasName == FullName)
1161 return true;
1162 if (It->ShortName == -1)
1163 return false;
1164 StringRef ShortName(&IntrinNames[It->ShortName]);
1165 return AliasName == ShortName;
1166}
1167
1168bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1169#include "clang/Basic/arm_mve_builtin_aliases.inc"
1170 // The included file defines:
1171 // - ArrayRef<IntrinToName> Map
1172 // - const char IntrinNames[]
1173 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1174}
1175
1176bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1177#include "clang/Basic/arm_cde_builtin_aliases.inc"
1178 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1179}
1180
1181bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1182 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1183 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1184 return BuiltinID >= AArch64::FirstSVEBuiltin &&
1185 BuiltinID <= AArch64::LastSVEBuiltin;
1186}
1187
1188bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1189 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1190 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1191 return BuiltinID >= AArch64::FirstSMEBuiltin &&
1192 BuiltinID <= AArch64::LastSMEBuiltin;
1193}
1194
1196 ASTContext &Context = getASTContext();
1197 if (!AL.isArgIdent(0)) {
1198 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
1199 << AL << 1 << AANT_ArgumentIdentifier;
1200 return;
1201 }
1202
1203 IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
1204 unsigned BuiltinID = Ident->getBuiltinID();
1205 StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
1206
1207 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
1208 if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) &&
1209 !SmeAliasValid(BuiltinID, AliasName)) ||
1210 (!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) &&
1211 !CdeAliasValid(BuiltinID, AliasName))) {
1212 Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
1213 return;
1214 }
1215
1216 D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
1217}
1218
1220 Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT,
1221 FunctionType::ArmStateValue CurrentState, StringRef StateName) {
1222 auto CheckForIncompatibleAttr =
1223 [&](FunctionType::ArmStateValue IncompatibleState,
1224 StringRef IncompatibleStateName) {
1225 if (CurrentState == IncompatibleState) {
1226 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
1227 << (std::string("'__arm_new(\"") + StateName.str() + "\")'")
1228 << (std::string("'") + IncompatibleStateName.str() + "(\"" +
1229 StateName.str() + "\")'")
1230 << true;
1231 AL.setInvalid();
1232 }
1233 };
1234
1235 CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in");
1236 CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out");
1237 CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout");
1238 CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves");
1239 return AL.isInvalid();
1240}
1241
1243 if (!AL.getNumArgs()) {
1244 Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
1245 AL.setInvalid();
1246 return;
1247 }
1248
1249 std::vector<StringRef> NewState;
1250 if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) {
1251 for (StringRef S : ExistingAttr->newArgs())
1252 NewState.push_back(S);
1253 }
1254
1255 bool HasZA = false;
1256 bool HasZT0 = false;
1257 for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1258 StringRef StateName;
1259 SourceLocation LiteralLoc;
1260 if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
1261 return;
1262
1263 if (StateName == "za")
1264 HasZA = true;
1265 else if (StateName == "zt0")
1266 HasZT0 = true;
1267 else {
1268 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
1269 AL.setInvalid();
1270 return;
1271 }
1272
1273 if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates.
1274 NewState.push_back(StateName);
1275 }
1276
1277 if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) {
1279 FunctionType::getArmZAState(FPT->getAArch64SMEAttributes());
1280 if (HasZA && ZAState != FunctionType::ARM_None &&
1281 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za"))
1282 return;
1284 FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes());
1285 if (HasZT0 && ZT0State != FunctionType::ARM_None &&
1286 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0"))
1287 return;
1288 }
1289
1290 D->dropAttr<ArmNewAttr>();
1291 D->addAttr(::new (getASTContext()) ArmNewAttr(
1292 getASTContext(), AL, NewState.data(), NewState.size()));
1293}
1294
1296 if (getLangOpts().CPlusPlus && !D->getDeclContext()->isExternCContext()) {
1297 Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
1298 return;
1299 }
1300
1301 const auto *FD = cast<FunctionDecl>(D);
1302 if (!FD->isExternallyVisible()) {
1303 Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
1304 return;
1305 }
1306
1307 D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL));
1308}
1309
1311 // Check the attribute arguments.
1312 if (AL.getNumArgs() > 1) {
1313 Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
1314 return;
1315 }
1316
1317 StringRef Str;
1318 SourceLocation ArgLoc;
1319
1320 if (AL.getNumArgs() == 0)
1321 Str = "";
1322 else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1323 return;
1324
1325 ARMInterruptAttr::InterruptType Kind;
1326 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
1327 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1328 << AL << Str << ArgLoc;
1329 return;
1330 }
1331
1332 const TargetInfo &TI = getASTContext().getTargetInfo();
1333 if (TI.hasFeature("vfp"))
1334 Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1335
1336 D->addAttr(::new (getASTContext())
1337 ARMInterruptAttr(getASTContext(), AL, Kind));
1338}
1339
1340} // namespace clang
#define V(N, I)
Definition: ASTContext.h:3341
static constexpr Builtin::Info BuiltinInfo[]
Definition: Builtins.cpp:32
const Decl * D
Expr * E
enum clang::sema::@1658::IndirectLocalPathEntry::EntryKind Kind
uint32_t Id
Definition: SemaARM.cpp:1143
int32_t ShortName
Definition: SemaARM.cpp:1145
int32_t FullName
Definition: SemaARM.cpp:1144
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:187
CanQualType LongTy
Definition: ASTContext.h:1128
CanQualType FloatTy
Definition: ASTContext.h:1131
CanQualType DoubleTy
Definition: ASTContext.h:1131
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:662
CanQualType UnsignedLongTy
Definition: ASTContext.h:1129
CanQualType IntTy
Definition: ASTContext.h:1128
CanQualType SignedCharTy
Definition: ASTContext.h:1128
CanQualType UnsignedCharTy
Definition: ASTContext.h:1129
CanQualType UnsignedIntTy
Definition: ASTContext.h:1129
CanQualType UnsignedLongLongTy
Definition: ASTContext.h:1130
CanQualType UnsignedShortTy
Definition: ASTContext.h:1129
CanQualType ShortTy
Definition: ASTContext.h:1128
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:779
CanQualType BFloat16Ty
Definition: ASTContext.h:1144
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
CanQualType LongLongTy
Definition: ASTContext.h:1128
CanQualType HalfTy
Definition: ASTContext.h:1143
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:3023
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
Definition: Builtins.h:268
const char * getRequiredFeatures(unsigned ID) const
Definition: Builtins.h:255
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2830
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3021
void setArg(unsigned Arg, Expr *ArgExpr)
setArg - Set the specified argument.
Definition: Expr.h:3034
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1638
Expr * getCallee()
Definition: Expr.h:2980
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3008
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:580
bool hasAttr() const
Definition: DeclBase.h:584
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:3075
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:3070
@ 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:1932
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5002
unsigned getAArch64SMEAttributes() const
Return a bitmask describing the SME attributes on the function type, see AArch64SMETypeAttributes for...
Definition: Type.h:5461
static ArmStateValue getArmZT0State(unsigned AttrBits)
Definition: Type.h:4600
static ArmStateValue getArmZAState(unsigned AttrBits)
Definition: Type.h:4596
@ SME_PStateSMEnabledMask
Definition: Type.h:4574
@ SME_PStateSMCompatibleMask
Definition: Type.h:4575
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:3675
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
EltType getEltType() const
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition: ParsedAttr.h:406
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:402
bool isInvalid() const
Definition: ParsedAttr.h:359
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3187
A (possibly-)qualified type.
Definition: Type.h:941
QualType withConst() const
Definition: Type.h:1166
void addConst()
Add the const type qualifier to this QualType.
Definition: Type.h:1163
bool isAtLeastAsQualifiedAs(QualType Other) const
Determine whether this type is at least as qualified as the other given type, requiring exact equalit...
Definition: Type.h:7932
QualType withVolatile() const
Definition: Type.h:1174
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition: Type.h:1444
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7844
const Type * getTypePtrOrNull() const
Definition: Type.h:7754
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition: Type.h:348
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition: Type.h:341
@ OCL_None
There is no lifetime qualification on this type.
Definition: Type.h:337
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition: Type.h:351
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition: Type.h:354
bool ParseSVEImmChecks(CallExpr *TheCall, llvm::SmallVector< std::tuple< int, int, int >, 3 > &ImmChecks)
Definition: SemaARM.cpp:406
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:985
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:659
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE)
Definition: SemaARM.cpp:841
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:699
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:727
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:825
bool MveAliasValid(unsigned BuiltinID, StringRef AliasName)
Definition: SemaARM.cpp:1168
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:816
void handleInterruptAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1310
bool CdeAliasValid(unsigned BuiltinID, StringRef AliasName)
Definition: SemaARM.cpp:1176
void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1195
@ ArmStreaming
Intrinsic is only available in normal mode.
Definition: SemaARM.h:32
@ ArmNonStreaming
Definition: SemaARM.h:31
@ VerifyRuntimeMode
Intrinsic is available both in normal and Streaming-SVE mode.
Definition: SemaARM.h:35
@ ArmStreamingCompatible
Intrinsic is only available in Streaming-SVE mode.
Definition: SemaARM.h:33
void handleNewAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1242
bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, unsigned MaxWidth)
Definition: SemaARM.cpp:866
bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:1063
bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall)
BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions.
Definition: SemaARM.cpp:25
void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1295
bool SmeAliasValid(unsigned BuiltinID, StringRef AliasName)
Definition: SemaARM.cpp:1188
bool SveAliasValid(unsigned BuiltinID, StringRef AliasName)
Definition: SemaARM.cpp:1181
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:187
SemaARM(Sema &S)
Definition: SemaARM.cpp:22
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:535
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:1566
ASTContext & Context
Definition: Sema.h:1004
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:751
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:701
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:9549
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:639
AssignConvertType
AssignConvertType - All of the 'assignment' semantic checks return this enum to indicate whether the ...
Definition: Sema.h:7641
bool BuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result)
BuiltinConstantArg - Handle a check if argument ArgNum of CallExpr TheCall is a constant expression.
@ AA_Assigning
Definition: Sema.h:6538
@ AA_Passing
Definition: Sema.h:6539
bool isConstantEvaluatedContext() const
Definition: Sema.h:2224
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:9655
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:16599
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:326
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
Exposes information about the current target.
Definition: TargetInfo.h:218
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1256
IntType getInt64Type() const
Definition: TargetInfo.h:405
uint32_t getARMCDECoprocMask() const
For ARM targets returns a mask defining which coprocessors are configured as Custom Datapath.
Definition: TargetInfo.h:1052
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
Definition: TargetInfo.h:1487
The base class of the type hierarchy.
Definition: Type.h:1829
bool isBlockPointerType() const
Definition: Type.h:8017
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8359
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isFloatingType() const
Definition: Type.cpp:2249
bool isAnyPointerType() const
Definition: Type.h:8011
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8540
QualType getType() const
Definition: Decl.h:678
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:56
static bool hasArmZAState(const FunctionDecl *FD)
Definition: SemaARM.cpp:635
static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, ArrayRef< IntrinToName > Map, const char *IntrinNames)
Definition: SemaARM.cpp:1149
static unsigned RFT(unsigned t, bool shift=false, bool ForceQuad=false)
Definition: SemaARM.cpp:318
static ArmSMEState getSMEState(unsigned BuiltinID)
Definition: SemaARM.cpp:649
static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, SemaARM::ArmStreamingType BuiltinType, unsigned BuiltinID)
Definition: SemaARM.cpp:563
ArmSMEState
Definition: SemaARM.cpp:392
@ ArmInOutZA
Definition: SemaARM.cpp:397
@ ArmZT0Mask
Definition: SemaARM.cpp:403
@ ArmInOutZT0
Definition: SemaARM.cpp:402
@ ArmInZA
Definition: SemaARM.cpp:395
@ ArmInZT0
Definition: SemaARM.cpp:400
@ ArmZAMask
Definition: SemaARM.cpp:398
@ ArmOutZA
Definition: SemaARM.cpp:396
@ ArmOutZT0
Definition: SemaARM.cpp:401
@ ArmNoState
Definition: SemaARM.cpp:393
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)
Definition: SemaARM.cpp:547
@ AANT_ArgumentIdentifier
Definition: ParsedAttr.h:1083
@ Result
The result type of a method or function.
static bool hasArmZT0State(const FunctionDecl *FD)
Definition: SemaARM.cpp:642
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:354
static bool checkNewAttrMutualExclusion(Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT, FunctionType::ArmStateValue CurrentState, StringRef StateName)
Definition: SemaARM.cpp:1219
#define true
Definition: stdbool.h:25
#define bool
Definition: stdbool.h:24
IdentifierInfo * Ident
Definition: ParsedAttr.h:105