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// Get the valid immediate range for the specified NEON type code.
319static unsigned RFT(unsigned t, bool shift = false, bool ForceQuad = false) {
321 int IsQuad = ForceQuad ? true : Type.isQuad();
322 switch (Type.getEltType()) {
325 return shift ? 7 : (8 << IsQuad) - 1;
328 return shift ? 15 : (4 << IsQuad) - 1;
330 return shift ? 31 : (2 << IsQuad) - 1;
333 return shift ? 63 : (1 << IsQuad) - 1;
335 return shift ? 127 : (1 << IsQuad) - 1;
337 assert(!shift && "cannot shift float types!");
338 return (4 << IsQuad) - 1;
340 assert(!shift && "cannot shift float types!");
341 return (2 << IsQuad) - 1;
343 assert(!shift && "cannot shift float types!");
344 return (1 << IsQuad) - 1;
346 assert(!shift && "cannot shift float types!");
347 return (4 << IsQuad) - 1;
348 }
349 llvm_unreachable("Invalid NeonTypeFlag!");
350}
351
352/// getNeonEltType - Return the QualType corresponding to the elements of
353/// the vector type specified by the NeonTypeFlags. This is used to check
354/// the pointer arguments for Neon load/store intrinsics.
356 bool IsPolyUnsigned, bool IsInt64Long) {
357 switch (Flags.getEltType()) {
359 return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
361 return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
363 return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
365 if (IsInt64Long)
366 return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
367 else
368 return Flags.isUnsigned() ? Context.UnsignedLongLongTy
369 : Context.LongLongTy;
371 return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
373 return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
375 if (IsInt64Long)
376 return Context.UnsignedLongTy;
377 else
378 return Context.UnsignedLongLongTy;
380 break;
382 return Context.HalfTy;
384 return Context.FloatTy;
386 return Context.DoubleTy;
388 return Context.BFloat16Ty;
389 }
390 llvm_unreachable("Invalid NeonTypeFlag!");
391}
392
393enum ArmSMEState : unsigned {
395
396 ArmInZA = 0b01,
397 ArmOutZA = 0b10,
399 ArmZAMask = 0b11,
400
401 ArmInZT0 = 0b01 << 2,
402 ArmOutZT0 = 0b10 << 2,
403 ArmInOutZT0 = 0b11 << 2,
404 ArmZT0Mask = 0b11 << 2
406
408 CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) {
409 // Perform all the immediate checks for this builtin call.
410 bool HasError = false;
411 for (auto &I : ImmChecks) {
412 int ArgNum, CheckTy, ElementSizeInBits;
413 std::tie(ArgNum, CheckTy, ElementSizeInBits) = I;
414
415 typedef bool (*OptionSetCheckFnTy)(int64_t Value);
416
417 // Function that checks whether the operand (ArgNum) is an immediate
418 // that is one of the predefined values.
419 auto CheckImmediateInSet = [&](OptionSetCheckFnTy CheckImm,
420 int ErrDiag) -> bool {
421 // We can't check the value of a dependent argument.
422 Expr *Arg = TheCall->getArg(ArgNum);
423 if (Arg->isTypeDependent() || Arg->isValueDependent())
424 return false;
425
426 // Check constant-ness first.
427 llvm::APSInt Imm;
428 if (SemaRef.BuiltinConstantArg(TheCall, ArgNum, Imm))
429 return true;
430
431 if (!CheckImm(Imm.getSExtValue()))
432 return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
433 return false;
434 };
435
436 switch ((SVETypeFlags::ImmCheckType)CheckTy) {
437 case SVETypeFlags::ImmCheck0_31:
438 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 31))
439 HasError = true;
440 break;
441 case SVETypeFlags::ImmCheck0_13:
442 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 13))
443 HasError = true;
444 break;
445 case SVETypeFlags::ImmCheck1_16:
446 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1, 16))
447 HasError = true;
448 break;
449 case SVETypeFlags::ImmCheck0_7:
450 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 7))
451 HasError = true;
452 break;
453 case SVETypeFlags::ImmCheck1_1:
454 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1, 1))
455 HasError = true;
456 break;
457 case SVETypeFlags::ImmCheck1_3:
458 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1, 3))
459 HasError = true;
460 break;
461 case SVETypeFlags::ImmCheck1_7:
462 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1, 7))
463 HasError = true;
464 break;
465 case SVETypeFlags::ImmCheckExtract:
466 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
467 (2048 / ElementSizeInBits) - 1))
468 HasError = true;
469 break;
470 case SVETypeFlags::ImmCheckShiftRight:
471 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1,
472 ElementSizeInBits))
473 HasError = true;
474 break;
475 case SVETypeFlags::ImmCheckShiftRightNarrow:
476 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 1,
477 ElementSizeInBits / 2))
478 HasError = true;
479 break;
480 case SVETypeFlags::ImmCheckShiftLeft:
481 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
482 ElementSizeInBits - 1))
483 HasError = true;
484 break;
485 case SVETypeFlags::ImmCheckLaneIndex:
486 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
487 (128 / (1 * ElementSizeInBits)) - 1))
488 HasError = true;
489 break;
490 case SVETypeFlags::ImmCheckLaneIndexCompRotate:
491 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
492 (128 / (2 * ElementSizeInBits)) - 1))
493 HasError = true;
494 break;
495 case SVETypeFlags::ImmCheckLaneIndexDot:
496 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0,
497 (128 / (4 * ElementSizeInBits)) - 1))
498 HasError = true;
499 break;
500 case SVETypeFlags::ImmCheckComplexRot90_270:
501 if (CheckImmediateInSet([](int64_t V) { return V == 90 || V == 270; },
502 diag::err_rotation_argument_to_cadd))
503 HasError = true;
504 break;
505 case SVETypeFlags::ImmCheckComplexRotAll90:
506 if (CheckImmediateInSet(
507 [](int64_t V) {
508 return V == 0 || V == 90 || V == 180 || V == 270;
509 },
510 diag::err_rotation_argument_to_cmla))
511 HasError = true;
512 break;
513 case SVETypeFlags::ImmCheck0_1:
514 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 1))
515 HasError = true;
516 break;
517 case SVETypeFlags::ImmCheck0_2:
518 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 2))
519 HasError = true;
520 break;
521 case SVETypeFlags::ImmCheck0_3:
522 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 3))
523 HasError = true;
524 break;
525 case SVETypeFlags::ImmCheck0_0:
526 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 0))
527 HasError = true;
528 break;
529 case SVETypeFlags::ImmCheck0_15:
530 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 15))
531 HasError = true;
532 break;
533 case SVETypeFlags::ImmCheck0_255:
534 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 0, 255))
535 HasError = true;
536 break;
537 case SVETypeFlags::ImmCheck2_4_Mul2:
538 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgNum, 2, 4) ||
539 SemaRef.BuiltinConstantArgMultiple(TheCall, ArgNum, 2))
540 HasError = true;
541 break;
542 }
543 }
544
545 return HasError;
546}
547
549 if (FD->hasAttr<ArmLocallyStreamingAttr>())
551 if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
552 if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
553 if (FPT->getAArch64SMEAttributes() &
556 if (FPT->getAArch64SMEAttributes() &
559 }
560 }
562}
563
564static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
565 const FunctionDecl *FD,
567 unsigned BuiltinID) {
569
570 // Check if the intrinsic is available in the right mode, i.e.
571 // * When compiling for SME only, the caller must be in streaming mode.
572 // * When compiling for SVE only, the caller must be in non-streaming mode.
573 // * When compiling for both SVE and SME, the caller can be in either mode.
575 auto DisableFeatures = [](llvm::StringMap<bool> &Map, StringRef S) {
576 for (StringRef K : Map.keys())
577 if (K.starts_with(S))
578 Map[K] = false;
579 };
580
581 llvm::StringMap<bool> CallerFeatureMapWithoutSVE;
582 S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSVE, FD);
583 DisableFeatures(CallerFeatureMapWithoutSVE, "sve");
584
585 // Avoid emitting diagnostics for a function that can never compile.
586 if (FnType == SemaARM::ArmStreaming && !CallerFeatureMapWithoutSVE["sme"])
587 return false;
588
589 llvm::StringMap<bool> CallerFeatureMapWithoutSME;
590 S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSME, FD);
591 DisableFeatures(CallerFeatureMapWithoutSME, "sme");
592
593 // We know the builtin requires either some combination of SVE flags, or
594 // some combination of SME flags, but we need to figure out which part
595 // of the required features is satisfied by the target features.
596 //
597 // For a builtin with target guard 'sve2p1|sme2', if we compile with
598 // '+sve2p1,+sme', then we know that it satisfies the 'sve2p1' part if we
599 // evaluate the features for '+sve2p1,+sme,+nosme'.
600 //
601 // Similarly, if we compile with '+sve2,+sme2', then we know it satisfies
602 // the 'sme2' part if we evaluate the features for '+sve2,+sme2,+nosve'.
603 StringRef BuiltinTargetGuards(
605 bool SatisfiesSVE = Builtin::evaluateRequiredTargetFeatures(
606 BuiltinTargetGuards, CallerFeatureMapWithoutSME);
607 bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures(
608 BuiltinTargetGuards, CallerFeatureMapWithoutSVE);
609
610 if ((SatisfiesSVE && SatisfiesSME) ||
611 (SatisfiesSVE && FnType == SemaARM::ArmStreamingCompatible))
612 return false;
613 else if (SatisfiesSVE)
615 else if (SatisfiesSME)
617 else
618 // This should be diagnosed by CodeGen
619 return false;
620 }
621
622 if (FnType != SemaARM::ArmNonStreaming &&
624 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
625 << TheCall->getSourceRange() << "non-streaming";
626 else if (FnType != SemaARM::ArmStreaming &&
628 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
629 << TheCall->getSourceRange() << "streaming";
630 else
631 return false;
632
633 return true;
634}
635
636static bool hasArmZAState(const FunctionDecl *FD) {
637 const auto *T = FD->getType()->getAs<FunctionProtoType>();
640 (FD->hasAttr<ArmNewAttr>() && FD->getAttr<ArmNewAttr>()->isNewZA());
641}
642
643static bool hasArmZT0State(const FunctionDecl *FD) {
644 const auto *T = FD->getType()->getAs<FunctionProtoType>();
647 (FD->hasAttr<ArmNewAttr>() && FD->getAttr<ArmNewAttr>()->isNewZT0());
648}
649
650static ArmSMEState getSMEState(unsigned BuiltinID) {
651 switch (BuiltinID) {
652 default:
653 return ArmNoState;
654#define GET_SME_BUILTIN_GET_STATE
655#include "clang/Basic/arm_sme_builtins_za_state.inc"
656#undef GET_SME_BUILTIN_GET_STATE
657 }
658}
659
661 CallExpr *TheCall) {
662 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
663 std::optional<ArmStreamingType> BuiltinType;
664
665 switch (BuiltinID) {
666#define GET_SME_STREAMING_ATTRS
667#include "clang/Basic/arm_sme_streaming_attrs.inc"
668#undef GET_SME_STREAMING_ATTRS
669 }
670
671 if (BuiltinType &&
672 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
673 return true;
674
675 if ((getSMEState(BuiltinID) & ArmZAMask) && !hasArmZAState(FD))
676 Diag(TheCall->getBeginLoc(),
677 diag::warn_attribute_arm_za_builtin_no_za_state)
678 << TheCall->getSourceRange();
679
680 if ((getSMEState(BuiltinID) & ArmZT0Mask) && !hasArmZT0State(FD))
681 Diag(TheCall->getBeginLoc(),
682 diag::warn_attribute_arm_zt0_builtin_no_zt0_state)
683 << TheCall->getSourceRange();
684 }
685
686 // Range check SME intrinsics that take immediate values.
688
689 switch (BuiltinID) {
690 default:
691 return false;
692#define GET_SME_IMMEDIATE_CHECK
693#include "clang/Basic/arm_sme_sema_rangechecks.inc"
694#undef GET_SME_IMMEDIATE_CHECK
695 }
696
697 return ParseSVEImmChecks(TheCall, ImmChecks);
698}
699
701 CallExpr *TheCall) {
702 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
703 std::optional<ArmStreamingType> BuiltinType;
704
705 switch (BuiltinID) {
706#define GET_SVE_STREAMING_ATTRS
707#include "clang/Basic/arm_sve_streaming_attrs.inc"
708#undef GET_SVE_STREAMING_ATTRS
709 }
710 if (BuiltinType &&
711 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
712 return true;
713 }
714 // Range check SVE intrinsics that take immediate values.
716
717 switch (BuiltinID) {
718 default:
719 return false;
720#define GET_SVE_IMMEDIATE_CHECK
721#include "clang/Basic/arm_sve_sema_rangechecks.inc"
722#undef GET_SVE_IMMEDIATE_CHECK
723 }
724
725 return ParseSVEImmChecks(TheCall, ImmChecks);
726}
727
729 unsigned BuiltinID,
730 CallExpr *TheCall) {
731 if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
732
733 switch (BuiltinID) {
734 default:
735 break;
736#define GET_NEON_BUILTINS
737#define TARGET_BUILTIN(id, ...) case NEON::BI##id:
738#define BUILTIN(id, ...) case NEON::BI##id:
739#include "clang/Basic/arm_neon.inc"
741 BuiltinID))
742 return true;
743 break;
744#undef TARGET_BUILTIN
745#undef BUILTIN
746#undef GET_NEON_BUILTINS
747 }
748 }
749
750 llvm::APSInt Result;
751 uint64_t mask = 0;
752 unsigned TV = 0;
753 int PtrArgNum = -1;
754 bool HasConstPtr = false;
755 switch (BuiltinID) {
756#define GET_NEON_OVERLOAD_CHECK
757#include "clang/Basic/arm_fp16.inc"
758#include "clang/Basic/arm_neon.inc"
759#undef GET_NEON_OVERLOAD_CHECK
760 }
761
762 // For NEON intrinsics which are overloaded on vector element type, validate
763 // the immediate which specifies which variant to emit.
764 unsigned ImmArg = TheCall->getNumArgs() - 1;
765 if (mask) {
766 if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result))
767 return true;
768
769 TV = Result.getLimitedValue(64);
770 if ((TV > 63) || (mask & (1ULL << TV)) == 0)
771 return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
772 << TheCall->getArg(ImmArg)->getSourceRange();
773 }
774
775 if (PtrArgNum >= 0) {
776 // Check that pointer arguments have the specified type.
777 Expr *Arg = TheCall->getArg(PtrArgNum);
778 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
779 Arg = ICE->getSubExpr();
781 QualType RHSTy = RHS.get()->getType();
782
783 llvm::Triple::ArchType Arch = TI.getTriple().getArch();
784 bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
785 Arch == llvm::Triple::aarch64_32 ||
786 Arch == llvm::Triple::aarch64_be;
787 bool IsInt64Long = TI.getInt64Type() == TargetInfo::SignedLong;
789 IsPolyUnsigned, IsInt64Long);
790 if (HasConstPtr)
791 EltTy = EltTy.withConst();
792 QualType LHSTy = getASTContext().getPointerType(EltTy);
794 ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);
795 if (RHS.isInvalid())
796 return true;
797 if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy,
798 RHSTy, RHS.get(), Sema::AA_Assigning))
799 return true;
800 }
801
802 // For NEON intrinsics which take an immediate value as part of the
803 // instruction, range check them here.
804 unsigned i = 0, l = 0, u = 0;
805 switch (BuiltinID) {
806 default:
807 return false;
808#define GET_NEON_IMMEDIATE_CHECK
809#include "clang/Basic/arm_fp16.inc"
810#include "clang/Basic/arm_neon.inc"
811#undef GET_NEON_IMMEDIATE_CHECK
812 }
813
814 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
815}
816
818 CallExpr *TheCall) {
819 switch (BuiltinID) {
820 default:
821 return false;
822#include "clang/Basic/arm_mve_builtin_sema.inc"
823 }
824}
825
827 unsigned BuiltinID,
828 CallExpr *TheCall) {
829 bool Err = false;
830 switch (BuiltinID) {
831 default:
832 return false;
833#include "clang/Basic/arm_cde_builtin_sema.inc"
834 }
835
836 if (Err)
837 return true;
838
839 return CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), /*WantCDE*/ true);
840}
841
843 const Expr *CoprocArg,
844 bool WantCDE) {
845 ASTContext &Context = getASTContext();
847 return false;
848
849 // We can't check the value of a dependent argument.
850 if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
851 return false;
852
853 llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context);
854 int64_t CoprocNo = CoprocNoAP.getExtValue();
855 assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
856
857 uint32_t CDECoprocMask = TI.getARMCDECoprocMask();
858 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
859
860 if (IsCDECoproc != WantCDE)
861 return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
862 << (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange();
863
864 return false;
865}
866
868 CallExpr *TheCall,
869 unsigned MaxWidth) {
870 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
871 BuiltinID == ARM::BI__builtin_arm_ldaex ||
872 BuiltinID == ARM::BI__builtin_arm_strex ||
873 BuiltinID == ARM::BI__builtin_arm_stlex ||
874 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
875 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
876 BuiltinID == AArch64::BI__builtin_arm_strex ||
877 BuiltinID == AArch64::BI__builtin_arm_stlex) &&
878 "unexpected ARM builtin");
879 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
880 BuiltinID == ARM::BI__builtin_arm_ldaex ||
881 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
882 BuiltinID == AArch64::BI__builtin_arm_ldaex;
883
884 ASTContext &Context = getASTContext();
885 DeclRefExpr *DRE =
886 cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
887
888 // Ensure that we have the proper number of arguments.
889 if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))
890 return true;
891
892 // Inspect the pointer argument of the atomic builtin. This should always be
893 // a pointer type, whose element is an integral scalar or pointer type.
894 // Because it is a pointer type, we don't have to worry about any implicit
895 // casts here.
896 Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
897 ExprResult PointerArgRes =
899 if (PointerArgRes.isInvalid())
900 return true;
901 PointerArg = PointerArgRes.get();
902
903 const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
904 if (!pointerType) {
905 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
906 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
907 return true;
908 }
909
910 // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next
911 // task is to insert the appropriate casts into the AST. First work out just
912 // what the appropriate type is.
913 QualType ValType = pointerType->getPointeeType();
914 QualType AddrType = ValType.getUnqualifiedType().withVolatile();
915 if (IsLdrex)
916 AddrType.addConst();
917
918 // Issue a warning if the cast is dodgy.
919 CastKind CastNeeded = CK_NoOp;
920 if (!AddrType.isAtLeastAsQualifiedAs(ValType)) {
921 CastNeeded = CK_BitCast;
922 Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
923 << PointerArg->getType() << Context.getPointerType(AddrType)
924 << Sema::AA_Passing << PointerArg->getSourceRange();
925 }
926
927 // Finally, do the cast and replace the argument with the corrected version.
928 AddrType = Context.getPointerType(AddrType);
929 PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);
930 if (PointerArgRes.isInvalid())
931 return true;
932 PointerArg = PointerArgRes.get();
933
934 TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
935
936 // In general, we allow ints, floats and pointers to be loaded and stored.
937 if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
938 !ValType->isBlockPointerType() && !ValType->isFloatingType()) {
939 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
940 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
941 return true;
942 }
943
944 // But ARM doesn't have instructions to deal with 128-bit versions.
945 if (Context.getTypeSize(ValType) > MaxWidth) {
946 assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate");
947 Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size)
948 << PointerArg->getType() << PointerArg->getSourceRange();
949 return true;
950 }
951
952 switch (ValType.getObjCLifetime()) {
955 // okay
956 break;
957
961 Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
962 << ValType << PointerArg->getSourceRange();
963 return true;
964 }
965
966 if (IsLdrex) {
967 TheCall->setType(ValType);
968 return false;
969 }
970
971 // Initialize the argument to be stored.
972 ExprResult ValArg = TheCall->getArg(0);
974 Context, ValType, /*consume*/ false);
975 ValArg = SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg);
976 if (ValArg.isInvalid())
977 return true;
978 TheCall->setArg(0, ValArg.get());
979
980 // __builtin_arm_strex always returns an int. It's marked as such in the .def,
981 // but the custom checker bypasses all default analysis.
982 TheCall->setType(Context.IntTy);
983 return false;
984}
985
987 unsigned BuiltinID,
988 CallExpr *TheCall) {
989 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
990 BuiltinID == ARM::BI__builtin_arm_ldaex ||
991 BuiltinID == ARM::BI__builtin_arm_strex ||
992 BuiltinID == ARM::BI__builtin_arm_stlex) {
993 return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64);
994 }
995
996 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
997 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
998 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
999 }
1000
1001 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
1002 BuiltinID == ARM::BI__builtin_arm_wsr64)
1003 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);
1004
1005 if (BuiltinID == ARM::BI__builtin_arm_rsr ||
1006 BuiltinID == ARM::BI__builtin_arm_rsrp ||
1007 BuiltinID == ARM::BI__builtin_arm_wsr ||
1008 BuiltinID == ARM::BI__builtin_arm_wsrp)
1009 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1010
1011 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1012 return true;
1013 if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall))
1014 return true;
1015 if (CheckCDEBuiltinFunctionCall(TI, BuiltinID, TheCall))
1016 return true;
1017
1018 // For intrinsics which take an immediate value as part of the instruction,
1019 // range check them here.
1020 // FIXME: VFP Intrinsics should error if VFP not present.
1021 switch (BuiltinID) {
1022 default:
1023 return false;
1024 case ARM::BI__builtin_arm_ssat:
1025 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);
1026 case ARM::BI__builtin_arm_usat:
1027 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1028 case ARM::BI__builtin_arm_ssat16:
1029 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
1030 case ARM::BI__builtin_arm_usat16:
1031 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
1032 case ARM::BI__builtin_arm_vcvtr_f:
1033 case ARM::BI__builtin_arm_vcvtr_d:
1034 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
1035 case ARM::BI__builtin_arm_dmb:
1036 case ARM::BI__builtin_arm_dsb:
1037 case ARM::BI__builtin_arm_isb:
1038 case ARM::BI__builtin_arm_dbg:
1039 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
1040 case ARM::BI__builtin_arm_cdp:
1041 case ARM::BI__builtin_arm_cdp2:
1042 case ARM::BI__builtin_arm_mcr:
1043 case ARM::BI__builtin_arm_mcr2:
1044 case ARM::BI__builtin_arm_mrc:
1045 case ARM::BI__builtin_arm_mrc2:
1046 case ARM::BI__builtin_arm_mcrr:
1047 case ARM::BI__builtin_arm_mcrr2:
1048 case ARM::BI__builtin_arm_mrrc:
1049 case ARM::BI__builtin_arm_mrrc2:
1050 case ARM::BI__builtin_arm_ldc:
1051 case ARM::BI__builtin_arm_ldcl:
1052 case ARM::BI__builtin_arm_ldc2:
1053 case ARM::BI__builtin_arm_ldc2l:
1054 case ARM::BI__builtin_arm_stc:
1055 case ARM::BI__builtin_arm_stcl:
1056 case ARM::BI__builtin_arm_stc2:
1057 case ARM::BI__builtin_arm_stc2l:
1058 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
1059 CheckARMCoprocessorImmediate(TI, TheCall->getArg(0),
1060 /*WantCDE*/ false);
1061 }
1062}
1063
1065 unsigned BuiltinID,
1066 CallExpr *TheCall) {
1067 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1068 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1069 BuiltinID == AArch64::BI__builtin_arm_strex ||
1070 BuiltinID == AArch64::BI__builtin_arm_stlex) {
1071 return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128);
1072 }
1073
1074 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
1075 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1076 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
1077 SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
1078 SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);
1079 }
1080
1081 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
1082 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
1083 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
1084 BuiltinID == AArch64::BI__builtin_arm_wsr128)
1085 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1086
1087 // Memory Tagging Extensions (MTE) Intrinsics
1088 if (BuiltinID == AArch64::BI__builtin_arm_irg ||
1089 BuiltinID == AArch64::BI__builtin_arm_addg ||
1090 BuiltinID == AArch64::BI__builtin_arm_gmi ||
1091 BuiltinID == AArch64::BI__builtin_arm_ldg ||
1092 BuiltinID == AArch64::BI__builtin_arm_stg ||
1093 BuiltinID == AArch64::BI__builtin_arm_subp) {
1094 return BuiltinARMMemoryTaggingCall(BuiltinID, TheCall);
1095 }
1096
1097 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
1098 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
1099 BuiltinID == AArch64::BI__builtin_arm_wsr ||
1100 BuiltinID == AArch64::BI__builtin_arm_wsrp)
1101 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1102
1103 // Only check the valid encoding range. Any constant in this range would be
1104 // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
1105 // an exception for incorrect registers. This matches MSVC behavior.
1106 if (BuiltinID == AArch64::BI_ReadStatusReg ||
1107 BuiltinID == AArch64::BI_WriteStatusReg)
1108 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
1109
1110 if (BuiltinID == AArch64::BI__getReg)
1111 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
1112
1113 if (BuiltinID == AArch64::BI__break)
1114 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1115
1116 if (BuiltinID == AArch64::BI__hlt)
1117 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1118
1119 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1120 return true;
1121
1122 if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall))
1123 return true;
1124
1125 if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall))
1126 return true;
1127
1128 // For intrinsics which take an immediate value as part of the instruction,
1129 // range check them here.
1130 unsigned i = 0, l = 0, u = 0;
1131 switch (BuiltinID) {
1132 default: return false;
1133 case AArch64::BI__builtin_arm_dmb:
1134 case AArch64::BI__builtin_arm_dsb:
1135 case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break;
1136 case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break;
1137 }
1138
1139 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
1140}
1141
1142namespace {
1143struct IntrinToName {
1144 uint32_t Id;
1145 int32_t FullName;
1146 int32_t ShortName;
1147};
1148} // unnamed namespace
1149
1150static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
1152 const char *IntrinNames) {
1153 AliasName.consume_front("__arm_");
1154 const IntrinToName *It =
1155 llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
1156 return L.Id < Id;
1157 });
1158 if (It == Map.end() || It->Id != BuiltinID)
1159 return false;
1160 StringRef FullName(&IntrinNames[It->FullName]);
1161 if (AliasName == FullName)
1162 return true;
1163 if (It->ShortName == -1)
1164 return false;
1165 StringRef ShortName(&IntrinNames[It->ShortName]);
1166 return AliasName == ShortName;
1167}
1168
1169bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1170#include "clang/Basic/arm_mve_builtin_aliases.inc"
1171 // The included file defines:
1172 // - ArrayRef<IntrinToName> Map
1173 // - const char IntrinNames[]
1174 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1175}
1176
1177bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1178#include "clang/Basic/arm_cde_builtin_aliases.inc"
1179 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1180}
1181
1182bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1183 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1184 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1185 return BuiltinID >= AArch64::FirstSVEBuiltin &&
1186 BuiltinID <= AArch64::LastSVEBuiltin;
1187}
1188
1189bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1190 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1191 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1192 return BuiltinID >= AArch64::FirstSMEBuiltin &&
1193 BuiltinID <= AArch64::LastSMEBuiltin;
1194}
1195
1197 ASTContext &Context = getASTContext();
1198 if (!AL.isArgIdent(0)) {
1199 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
1200 << AL << 1 << AANT_ArgumentIdentifier;
1201 return;
1202 }
1203
1204 IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
1205 unsigned BuiltinID = Ident->getBuiltinID();
1206 StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
1207
1208 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
1209 if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) &&
1210 !SmeAliasValid(BuiltinID, AliasName)) ||
1211 (!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) &&
1212 !CdeAliasValid(BuiltinID, AliasName))) {
1213 Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
1214 return;
1215 }
1216
1217 D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
1218}
1219
1221 Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT,
1222 FunctionType::ArmStateValue CurrentState, StringRef StateName) {
1223 auto CheckForIncompatibleAttr =
1224 [&](FunctionType::ArmStateValue IncompatibleState,
1225 StringRef IncompatibleStateName) {
1226 if (CurrentState == IncompatibleState) {
1227 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
1228 << (std::string("'__arm_new(\"") + StateName.str() + "\")'")
1229 << (std::string("'") + IncompatibleStateName.str() + "(\"" +
1230 StateName.str() + "\")'")
1231 << true;
1232 AL.setInvalid();
1233 }
1234 };
1235
1236 CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in");
1237 CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out");
1238 CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout");
1239 CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves");
1240 return AL.isInvalid();
1241}
1242
1244 if (!AL.getNumArgs()) {
1245 Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
1246 AL.setInvalid();
1247 return;
1248 }
1249
1250 std::vector<StringRef> NewState;
1251 if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) {
1252 for (StringRef S : ExistingAttr->newArgs())
1253 NewState.push_back(S);
1254 }
1255
1256 bool HasZA = false;
1257 bool HasZT0 = false;
1258 for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1259 StringRef StateName;
1260 SourceLocation LiteralLoc;
1261 if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
1262 return;
1263
1264 if (StateName == "za")
1265 HasZA = true;
1266 else if (StateName == "zt0")
1267 HasZT0 = true;
1268 else {
1269 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
1270 AL.setInvalid();
1271 return;
1272 }
1273
1274 if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates.
1275 NewState.push_back(StateName);
1276 }
1277
1278 if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) {
1280 FunctionType::getArmZAState(FPT->getAArch64SMEAttributes());
1281 if (HasZA && ZAState != FunctionType::ARM_None &&
1282 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za"))
1283 return;
1285 FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes());
1286 if (HasZT0 && ZT0State != FunctionType::ARM_None &&
1287 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0"))
1288 return;
1289 }
1290
1291 D->dropAttr<ArmNewAttr>();
1292 D->addAttr(::new (getASTContext()) ArmNewAttr(
1293 getASTContext(), AL, NewState.data(), NewState.size()));
1294}
1295
1297 if (getLangOpts().CPlusPlus && !D->getDeclContext()->isExternCContext()) {
1298 Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
1299 return;
1300 }
1301
1302 const auto *FD = cast<FunctionDecl>(D);
1303 if (!FD->isExternallyVisible()) {
1304 Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
1305 return;
1306 }
1307
1308 D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL));
1309}
1310
1312 // Check the attribute arguments.
1313 if (AL.getNumArgs() > 1) {
1314 Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
1315 return;
1316 }
1317
1318 StringRef Str;
1319 SourceLocation ArgLoc;
1320
1321 if (AL.getNumArgs() == 0)
1322 Str = "";
1323 else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1324 return;
1325
1326 ARMInterruptAttr::InterruptType Kind;
1327 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
1328 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1329 << AL << Str << ArgLoc;
1330 return;
1331 }
1332
1333 const TargetInfo &TI = getASTContext().getTargetInfo();
1334 if (TI.hasFeature("vfp"))
1335 Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1336
1337 D->addAttr(::new (getASTContext())
1338 ARMInterruptAttr(getASTContext(), AL, Kind));
1339}
1340
1341} // namespace clang
#define V(N, I)
Definition: ASTContext.h:3341
static constexpr Builtin::Info BuiltinInfo[]
Definition: Builtins.cpp:32
const Decl * D
enum clang::sema::@1655::IndirectLocalPathEntry::EntryKind Kind
Expr * E
uint32_t Id
Definition: SemaARM.cpp:1144
int32_t ShortName
Definition: SemaARM.cpp:1146
int32_t FullName
Definition: SemaARM.cpp:1145
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:407
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:986
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:660
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE)
Definition: SemaARM.cpp:842
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:700
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:728
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:826
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:817
void handleInterruptAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1311
void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1196
@ ArmStreaming
Intrinsic is only available in normal mode.
Definition: SemaARM.h:35
@ ArmNonStreaming
Definition: SemaARM.h:34
@ VerifyRuntimeMode
Intrinsic is available both in normal and Streaming-SVE mode.
Definition: SemaARM.h:38
@ ArmStreamingCompatible
Intrinsic is only available in Streaming-SVE mode.
Definition: SemaARM.h:36
void handleNewAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaARM.cpp:1243
bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, unsigned MaxWidth)
Definition: SemaARM.cpp:867
bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1182
bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaARM.cpp:1064
bool MveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1169
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:1296
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:1189
bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition: SemaARM.cpp:1177
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:493
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:1567
ASTContext & Context
Definition: Sema.h:962
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:702
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:9557
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:7599
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:6496
@ AA_Passing
Definition: Sema.h:6497
bool isConstantEvaluatedContext() const
Definition: Sema.h:2182
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:9656
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:16607
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
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:56
static bool hasArmZAState(const FunctionDecl *FD)
Definition: SemaARM.cpp:636
static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, ArrayRef< IntrinToName > Map, const char *IntrinNames)
Definition: SemaARM.cpp:1150
static unsigned RFT(unsigned t, bool shift=false, bool ForceQuad=false)
Definition: SemaARM.cpp:319
static ArmSMEState getSMEState(unsigned BuiltinID)
Definition: SemaARM.cpp:650
static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, SemaARM::ArmStreamingType BuiltinType, unsigned BuiltinID)
Definition: SemaARM.cpp:564
ArmSMEState
Definition: SemaARM.cpp:393
@ ArmInOutZA
Definition: SemaARM.cpp:398
@ ArmZT0Mask
Definition: SemaARM.cpp:404
@ ArmInOutZT0
Definition: SemaARM.cpp:403
@ ArmInZA
Definition: SemaARM.cpp:396
@ ArmInZT0
Definition: SemaARM.cpp:401
@ ArmZAMask
Definition: SemaARM.cpp:399
@ ArmOutZA
Definition: SemaARM.cpp:397
@ ArmOutZT0
Definition: SemaARM.cpp:402
@ ArmNoState
Definition: SemaARM.cpp:394
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)
Definition: SemaARM.cpp:548
@ AANT_ArgumentIdentifier
Definition: ParsedAttr.h:1083
@ Result
The result type of a method or function.
static bool hasArmZT0State(const FunctionDecl *FD)
Definition: SemaARM.cpp:643
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:355
static bool checkNewAttrMutualExclusion(Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT, FunctionType::ArmStateValue CurrentState, StringRef StateName)
Definition: SemaARM.cpp:1220
#define true
Definition: stdbool.h:25
#define bool
Definition: stdbool.h:24
IdentifierInfo * Ident
Definition: ParsedAttr.h:105