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