clang 24.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#include "llvm/Support/AArch64MemoryHints.h"
21
22namespace clang {
23
25
26/// BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions
28 CallExpr *TheCall) {
29 ASTContext &Context = getASTContext();
30
31 if (BuiltinID == AArch64::BI__builtin_arm_irg) {
32 if (SemaRef.checkArgCount(TheCall, 2))
33 return true;
34 Expr *Arg0 = TheCall->getArg(0);
35 Expr *Arg1 = TheCall->getArg(1);
36
37 ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);
38 if (FirstArg.isInvalid())
39 return true;
40 QualType FirstArgType = FirstArg.get()->getType();
41 if (!FirstArgType->isAnyPointerType())
42 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
43 << "first" << FirstArgType << Arg0->getSourceRange();
44 TheCall->setArg(0, FirstArg.get());
45
47 Context, Context.getIntTypeForBitwidth(64, /*Signed=*/false),
48 /*Consumed=*/false);
49 ExprResult SecArg =
50 SemaRef.PerformCopyInitialization(Entity,
51 /*EqualLoc=*/SourceLocation(), Arg1);
52 if (SecArg.isInvalid())
53 return true;
54 TheCall->setArg(1, SecArg.get());
55
56 // Derive the return type from the pointer argument.
57 TheCall->setType(FirstArgType);
58 return false;
59 }
60
61 if (BuiltinID == AArch64::BI__builtin_arm_addg) {
62 if (SemaRef.checkArgCount(TheCall, 2))
63 return true;
64
65 Expr *Arg0 = TheCall->getArg(0);
66 ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);
67 if (FirstArg.isInvalid())
68 return true;
69 QualType FirstArgType = FirstArg.get()->getType();
70 if (!FirstArgType->isAnyPointerType())
71 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
72 << "first" << FirstArgType << Arg0->getSourceRange();
73 TheCall->setArg(0, FirstArg.get());
74
75 // Derive the return type from the pointer argument.
76 TheCall->setType(FirstArgType);
77
78 // Second arg must be an constant in range [0,15]
79 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
80 }
81
82 if (BuiltinID == AArch64::BI__builtin_arm_gmi) {
83 if (SemaRef.checkArgCount(TheCall, 2))
84 return true;
85 Expr *Arg0 = TheCall->getArg(0);
86 Expr *Arg1 = TheCall->getArg(1);
87
88 ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);
89 if (FirstArg.isInvalid())
90 return true;
91 QualType FirstArgType = FirstArg.get()->getType();
92 if (!FirstArgType->isAnyPointerType())
93 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
94 << "first" << FirstArgType << Arg0->getSourceRange();
95 TheCall->setArg(0, FirstArg.get());
96
98 Context, Context.getIntTypeForBitwidth(64, /*Signed=*/false),
99 /*Consumed=*/false);
100 ExprResult SecArg =
101 SemaRef.PerformCopyInitialization(Entity,
102 /*EqualLoc=*/SourceLocation(), Arg1);
103 if (SecArg.isInvalid())
104 return true;
105 TheCall->setArg(1, SecArg.get());
106
107 return false;
108 }
109
110 if (BuiltinID == AArch64::BI__builtin_arm_ldg ||
111 BuiltinID == AArch64::BI__builtin_arm_stg) {
112 if (SemaRef.checkArgCount(TheCall, 1))
113 return true;
114 Expr *Arg0 = TheCall->getArg(0);
115 ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);
116 if (FirstArg.isInvalid())
117 return true;
118
119 QualType FirstArgType = FirstArg.get()->getType();
120 if (!FirstArgType->isAnyPointerType())
121 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
122 << "first" << FirstArgType << Arg0->getSourceRange();
123 TheCall->setArg(0, FirstArg.get());
124
125 // Derive the return type from the pointer argument.
126 if (BuiltinID == AArch64::BI__builtin_arm_ldg)
127 TheCall->setType(FirstArgType);
128 return false;
129 }
130
131 if (BuiltinID == AArch64::BI__builtin_arm_subp) {
132 Expr *ArgA = TheCall->getArg(0);
133 Expr *ArgB = TheCall->getArg(1);
134
135 ExprResult ArgExprA = SemaRef.DefaultFunctionArrayLvalueConversion(ArgA);
136 ExprResult ArgExprB = SemaRef.DefaultFunctionArrayLvalueConversion(ArgB);
137
138 if (ArgExprA.isInvalid() || ArgExprB.isInvalid())
139 return true;
140
141 QualType ArgTypeA = ArgExprA.get()->getType();
142 QualType ArgTypeB = ArgExprB.get()->getType();
143
144 auto isNull = [&](Expr *E) -> bool {
145 return E->isNullPointerConstant(Context,
147 };
148
149 // argument should be either a pointer or null
150 if (!ArgTypeA->isAnyPointerType() && !isNull(ArgA))
151 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
152 << "first" << ArgTypeA << ArgA->getSourceRange();
153
154 if (!ArgTypeB->isAnyPointerType() && !isNull(ArgB))
155 return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
156 << "second" << ArgTypeB << ArgB->getSourceRange();
157
158 // Ensure Pointee types are compatible
159 if (ArgTypeA->isAnyPointerType() && !isNull(ArgA) &&
160 ArgTypeB->isAnyPointerType() && !isNull(ArgB)) {
161 QualType pointeeA = ArgTypeA->getPointeeType();
162 QualType pointeeB = ArgTypeB->getPointeeType();
163 if (!Context.typesAreCompatible(
164 Context.getCanonicalType(pointeeA).getUnqualifiedType(),
165 Context.getCanonicalType(pointeeB).getUnqualifiedType())) {
166 return Diag(TheCall->getBeginLoc(),
167 diag::err_typecheck_sub_ptr_compatible)
168 << ArgTypeA << ArgTypeB << ArgA->getSourceRange()
169 << ArgB->getSourceRange();
170 }
171 }
172
173 // at least one argument should be pointer type
174 if (!ArgTypeA->isAnyPointerType() && !ArgTypeB->isAnyPointerType())
175 return Diag(TheCall->getBeginLoc(), diag::err_memtag_any2arg_pointer)
176 << ArgTypeA << ArgTypeB << ArgA->getSourceRange();
177
178 if (isNull(ArgA)) // adopt type of the other pointer
179 ArgExprA =
180 SemaRef.ImpCastExprToType(ArgExprA.get(), ArgTypeB, CK_NullToPointer);
181
182 if (isNull(ArgB))
183 ArgExprB =
184 SemaRef.ImpCastExprToType(ArgExprB.get(), ArgTypeA, CK_NullToPointer);
185
186 TheCall->setArg(0, ArgExprA.get());
187 TheCall->setArg(1, ArgExprB.get());
188 return false;
189 }
190 assert(false && "Unhandled ARM MTE intrinsic");
191 return true;
192}
193
194/// BuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr
195/// TheCall is an ARM/AArch64 special register string literal.
196bool SemaARM::BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
197 int ArgNum, unsigned ExpectedFieldNum,
198 bool AllowName) {
199 bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
200 BuiltinID == ARM::BI__builtin_arm_wsr64 ||
201 BuiltinID == ARM::BI__builtin_arm_rsr ||
202 BuiltinID == ARM::BI__builtin_arm_rsrp ||
203 BuiltinID == ARM::BI__builtin_arm_wsr ||
204 BuiltinID == ARM::BI__builtin_arm_wsrp;
205 bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
206 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
207 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
208 BuiltinID == AArch64::BI__builtin_arm_wsr128 ||
209 BuiltinID == AArch64::BI__builtin_arm_rsr ||
210 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
211 BuiltinID == AArch64::BI__builtin_arm_wsr ||
212 BuiltinID == AArch64::BI__builtin_arm_wsrp;
213 assert((IsARMBuiltin || IsAArch64Builtin) && "Unexpected ARM builtin.");
214
215 // We can't check the value of a dependent argument.
216 Expr *Arg = TheCall->getArg(ArgNum);
217 if (Arg->isTypeDependent() || Arg->isValueDependent())
218 return false;
219
220 // Check if the argument is a string literal.
222 return Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
223 << Arg->getSourceRange();
224
225 // Check the type of special register given.
226 StringRef Reg = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
228 Reg.split(Fields, ":");
229
230 if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
231 return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
232 << Arg->getSourceRange();
233
234 // If the string is the name of a register then we cannot check that it is
235 // valid here but if the string is of one the forms described in ACLE then we
236 // can check that the supplied fields are integers and within the valid
237 // ranges.
238 if (Fields.size() > 1) {
239 bool FiveFields = Fields.size() == 5;
240
241 bool ValidString = true;
242 if (IsARMBuiltin) {
243 ValidString &= Fields[0].starts_with_insensitive("cp") ||
244 Fields[0].starts_with_insensitive("p");
245 if (ValidString)
246 Fields[0] = Fields[0].drop_front(
247 Fields[0].starts_with_insensitive("cp") ? 2 : 1);
248
249 ValidString &= Fields[2].starts_with_insensitive("c");
250 if (ValidString)
251 Fields[2] = Fields[2].drop_front(1);
252
253 if (FiveFields) {
254 ValidString &= Fields[3].starts_with_insensitive("c");
255 if (ValidString)
256 Fields[3] = Fields[3].drop_front(1);
257 }
258 }
259
260 SmallVector<int, 5> FieldBitWidths;
261 if (FiveFields)
262 FieldBitWidths.append({IsAArch64Builtin ? 2 : 4, 3, 4, 4, 3});
263 else
264 FieldBitWidths.append({4, 3, 4});
265
266 for (unsigned i = 0; i < Fields.size(); ++i) {
267 int IntField;
268 ValidString &= !Fields[i].getAsInteger(10, IntField);
269 ValidString &= (IntField >= 0 && IntField < (1 << FieldBitWidths[i]));
270 }
271
272 if (!ValidString)
273 return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
274 << Arg->getSourceRange();
275 } else if (IsAArch64Builtin && Fields.size() == 1) {
276 // This code validates writes to PSTATE registers.
277
278 // Not a write.
279 if (TheCall->getNumArgs() != 2)
280 return false;
281
282 // The 128-bit system register accesses do not touch PSTATE.
283 if (BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
284 BuiltinID == AArch64::BI__builtin_arm_wsr128)
285 return false;
286
287 // These are the named PSTATE accesses using "MSR (immediate)" instructions,
288 // along with the upper limit on the immediates allowed.
289 auto MaxLimit = llvm::StringSwitch<std::optional<unsigned>>(Reg)
290 .CaseLower("spsel", 15)
291 .CaseLower("daifclr", 15)
292 .CaseLower("daifset", 15)
293 .CaseLower("pan", 15)
294 .CaseLower("uao", 15)
295 .CaseLower("dit", 15)
296 .CaseLower("ssbs", 15)
297 .CaseLower("tco", 15)
298 .CaseLower("allint", 1)
299 .CaseLower("pm", 1)
300 .Default(std::nullopt);
301
302 // If this is not a named PSTATE, just continue without validating, as this
303 // will be lowered to an "MSR (register)" instruction directly
304 if (!MaxLimit)
305 return false;
306
307 // Here we only allow constants in the range for that pstate, as required by
308 // the ACLE.
309 //
310 // While clang also accepts the names of system registers in its ACLE
311 // intrinsics, we prevent this with the PSTATE names used in MSR (immediate)
312 // as the value written via a register is different to the value used as an
313 // immediate to have the same effect. e.g., for the instruction `msr tco,
314 // x0`, it is bit 25 of register x0 that is written into PSTATE.TCO, but
315 // with `msr tco, #imm`, it is bit 0 of xN that is written into PSTATE.TCO.
316 //
317 // If a programmer wants to codegen the MSR (register) form of `msr tco,
318 // xN`, they can still do so by specifying the register using five
319 // colon-separated numbers in a string.
320 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit);
321 }
322
323 return false;
324}
325
326bool SemaARM::BuiltinARMAtomicHintCall(unsigned BuiltinID, CallExpr *TheCall) {
327 if (SemaRef.checkArgCount(TheCall, 4))
328 return true;
329
330 bool IsStore = BuiltinID == AArch64::BI__builtin_arm_atomic_store_with_hint;
331 ASTContext &Context = getASTContext();
332
333 // Arg 0 should be the pointer type. The pointee type must be a
334 // scalar integral type of 8, 16, 32 or 64 bits. Stores also support
335 // floating-point types.
336 auto PtrArgRes =
337 SemaRef.DefaultFunctionArrayLvalueConversion(TheCall->getArg(0));
338 if (PtrArgRes.isInvalid())
339 return true;
340 auto *PtrArg = PtrArgRes.get();
341 auto *PtrTy = PtrArg->getType()->getAs<PointerType>();
342 if (!PtrTy)
343 return Diag(TheCall->getBeginLoc(),
344 diag::err_atomic_hint_builtin_must_be_pointer)
345 << PtrArg->getType() << IsStore << PtrArg->getSourceRange();
346 TheCall->setArg(0, PtrArg);
347
348 QualType PtrQT = Context.getCanonicalType(PtrTy->getPointeeType());
349 if (PtrQT.isConstQualified())
350 return Diag(TheCall->getBeginLoc(),
351 diag::err_atomic_op_needs_non_const_pointer)
352 << PtrQT << PtrArg->getSourceRange();
353
354 PtrQT = PtrQT.getUnqualifiedType();
355 if (!PtrQT->isIntegralType(Context) &&
356 !(IsStore && (PtrQT->isFloatingType() || PtrQT->isMFloat8Type())))
357 return Diag(TheCall->getBeginLoc(),
358 IsStore ? diag::err_atomic_op_needs_atomic_int_or_fp
359 : diag::err_atomic_op_needs_atomic_int)
360 << 0 << PtrQT << PtrArg->getSourceRange();
361
362 if (PtrQT->isBitIntType())
363 return Diag(TheCall->getBeginLoc(),
364 diag::err_atomic_builtin_bit_int_prohibit)
365 << PtrQT << PtrArg->getSourceRange();
366
367 unsigned TySize = Context.getTypeSize(PtrQT);
368 if (TySize != 8 && TySize != 16 && TySize != 32 && TySize != 64)
369 return Diag(TheCall->getBeginLoc(), diag::err_atomic_op_hint_data_size)
370 << IsStore << PtrArg->getSourceRange();
371
372 if (!IsStore)
373 TheCall->setType(PtrQT);
374
375 // Arg 1 is the data operand. The type must match the pointee
376 // type found above.
377 auto DataArgRes =
378 SemaRef.DefaultFunctionArrayLvalueConversion(TheCall->getArg(1));
379 if (DataArgRes.isInvalid())
380 return true;
381 auto *DataArg = DataArgRes.get();
382 QualType DataQT =
383 Context.getCanonicalType(DataArg->getType()).getUnqualifiedType();
384 TheCall->setArg(1, DataArg);
385
386 if (PtrQT != DataQT)
387 return Diag(TheCall->getBeginLoc(),
388 diag::err_typecheck_call_different_arg_types)
389 << PtrQT << DataQT;
390
391 // Arg 2 is the memory order. Stores only allow relaxed, release or seq_cst.
392 auto MemOrdArg =
393 SemaRef.DefaultFunctionArrayLvalueConversion(TheCall->getArg(2));
394 if (MemOrdArg.isInvalid())
395 return true;
396 auto *MemOrd = MemOrdArg.get();
397 if (SemaRef.convertArgumentToType(MemOrd, Context.IntTy))
398 return true;
399 TheCall->setArg(2, MemOrd);
400
401 if (!MemOrd->isValueDependent()) {
402 std::optional<llvm::APSInt> MemOrdAP =
403 MemOrd->getIntegerConstantExpr(Context);
404 if (!MemOrdAP)
405 return Diag(TheCall->getBeginLoc(),
406 diag::err_atomic_hint_has_invalid_memory_order)
407 << MemOrd->getType() << MemOrd->getSourceRange();
408
409 unsigned Ordering = MemOrdAP->getZExtValue();
410 if (!llvm::isValidAtomicOrderingCABI(Ordering))
411 return Diag(TheCall->getBeginLoc(),
412 diag::err_atomic_hint_has_invalid_memory_order)
413 << *MemOrdAP << MemOrd->getSourceRange();
414
415 auto AtomicOrdering = static_cast<llvm::AtomicOrderingCABI>(Ordering);
416 if (IsStore && AtomicOrdering != llvm::AtomicOrderingCABI::relaxed &&
417 AtomicOrdering != llvm::AtomicOrderingCABI::release &&
418 AtomicOrdering != llvm::AtomicOrderingCABI::seq_cst)
419 return Diag(TheCall->getBeginLoc(),
420 diag::err_atomic_hint_has_invalid_memory_order)
421 << *MemOrdAP << MemOrd->getSourceRange();
422 }
423
424 // Arg 3 is the hint type. Only values represented by AArch64MemoryHint
425 // are valid. Fetch operations only allow HINT_SHUH and HINT_SHUH_PH.
426 auto HintArg =
427 SemaRef.DefaultFunctionArrayLvalueConversion(TheCall->getArg(3));
428 if (HintArg.isInvalid())
429 return true;
430 auto Hint = HintArg.get();
431 if (SemaRef.convertArgumentToType(Hint, Context.IntTy))
432 return true;
433 TheCall->setArg(3, Hint);
434
435 if (!Hint->isValueDependent()) {
436 std::optional<llvm::APSInt> HintAP = Hint->getIntegerConstantExpr(Context);
437 if (!HintAP)
438 return Diag(TheCall->getBeginLoc(),
439 diag::err_atomic_hint_has_invalid_hint_type)
440 << Hint->getType() << Hint->getSourceRange();
441
442 auto MemoryHint = llvm::toAArch64MemoryHint(HintAP->getZExtValue());
443 if (MemoryHint == llvm::AArch64MemoryHint::NONE ||
444 (!IsStore && MemoryHint != llvm::AArch64MemoryHint::SHUH &&
445 MemoryHint != llvm::AArch64MemoryHint::SHUH_PH)) {
446 Diag(TheCall->getBeginLoc(), diag::warn_atomic_hint_has_invalid_hint_type)
447 << *HintAP << Hint->getSourceRange();
448 return false;
449 }
450 }
451 return false;
452}
453
454/// getNeonEltType - Return the QualType corresponding to the elements of
455/// the vector type specified by the NeonTypeFlags. This is used to check
456/// the pointer arguments for Neon load/store intrinsics.
458 bool IsPolyUnsigned, bool IsInt64Long) {
459 switch (Flags.getEltType()) {
461 return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
463 return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
465 return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
467 if (IsInt64Long)
468 return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
469 else
470 return Flags.isUnsigned() ? Context.UnsignedLongLongTy
471 : Context.LongLongTy;
473 return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
475 return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
477 if (IsInt64Long)
478 return Context.UnsignedLongTy;
479 else
480 return Context.UnsignedLongLongTy;
482 break;
484 return Context.HalfTy;
486 return Context.FloatTy;
488 return Context.DoubleTy;
490 return Context.BFloat16Ty;
492 return Context.MFloat8Ty;
493 }
494 llvm_unreachable("Invalid NeonTypeFlag!");
495}
496
497enum ArmSMEState : unsigned {
499
500 ArmInZA = 0b01,
501 ArmOutZA = 0b10,
503 ArmZAMask = 0b11,
504
505 ArmInZT0 = 0b01 << 2,
506 ArmOutZT0 = 0b10 << 2,
507 ArmInOutZT0 = 0b11 << 2,
508 ArmZT0Mask = 0b11 << 2
509};
510
511bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy,
512 unsigned ArgIdx, unsigned EltBitWidth,
513 unsigned ContainerBitWidth) {
514 // Function that checks whether the operand (ArgIdx) is an immediate
515 // that is one of a given set of values.
516 auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set,
517 int ErrDiag) -> bool {
518 // We can't check the value of a dependent argument.
519 Expr *Arg = TheCall->getArg(ArgIdx);
520 if (Arg->isTypeDependent() || Arg->isValueDependent())
521 return false;
522
523 // Check constant-ness first.
524 llvm::APSInt Imm;
525 if (SemaRef.BuiltinConstantArg(TheCall, ArgIdx, Imm))
526 return true;
527
528 if (!llvm::is_contained(Set, Imm.getSExtValue()))
529 return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
530 return false;
531 };
532
533 switch ((ImmCheckType)CheckTy) {
534 case ImmCheckType::ImmCheck0_31:
535 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 31))
536 return true;
537 break;
538 case ImmCheckType::ImmCheck0_13:
539 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 13))
540 return true;
541 break;
542 case ImmCheckType::ImmCheck0_63:
543 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63))
544 return true;
545 break;
546 case ImmCheckType::ImmCheck1_16:
547 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16))
548 return true;
549 break;
550 case ImmCheckType::ImmCheck0_7:
551 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7))
552 return true;
553 break;
554 case ImmCheckType::ImmCheck1_1:
555 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 1))
556 return true;
557 break;
558 case ImmCheckType::ImmCheck1_3:
559 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 3))
560 return true;
561 break;
562 case ImmCheckType::ImmCheck1_7:
563 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 7))
564 return true;
565 break;
566 case ImmCheckType::ImmCheckExtract:
567 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
568 (2048 / EltBitWidth) - 1))
569 return true;
570 break;
571 case ImmCheckType::ImmCheckCvt:
572 case ImmCheckType::ImmCheckShiftRight:
573 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth))
574 return true;
575 break;
576 case ImmCheckType::ImmCheckShiftRightNarrow:
577 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth / 2))
578 return true;
579 break;
580 case ImmCheckType::ImmCheckShiftLeft:
581 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1))
582 return true;
583 break;
584 case ImmCheckType::ImmCheckShiftLeftLong:
585 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, (EltBitWidth / 2)))
586 return true;
587 break;
588 case ImmCheckType::ImmCheckLaneIndex:
589 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
590 (ContainerBitWidth / EltBitWidth) - 1))
591 return true;
592 break;
593 case ImmCheckType::ImmCheckLaneIndexCompRotate:
594 if (SemaRef.BuiltinConstantArgRange(
595 TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1))
596 return true;
597 break;
598 case ImmCheckType::ImmCheckLaneIndexDot:
599 if (SemaRef.BuiltinConstantArgRange(
600 TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1))
601 return true;
602 break;
603 case ImmCheckType::ImmCheckComplexRot90_270:
604 if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd))
605 return true;
606 break;
607 case ImmCheckType::ImmCheckComplexRotAll90:
608 if (CheckImmediateInSet({0, 90, 180, 270},
609 diag::err_rotation_argument_to_cmla))
610 return true;
611 break;
612 case ImmCheckType::ImmCheck0_1:
613 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 1))
614 return true;
615 break;
616 case ImmCheckType::ImmCheck0_2:
617 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 2))
618 return true;
619 break;
620 case ImmCheckType::ImmCheck0_3:
621 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3))
622 return true;
623 break;
624 case ImmCheckType::ImmCheck0_0:
625 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 0))
626 return true;
627 break;
628 case ImmCheckType::ImmCheck0_15:
629 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 15))
630 return true;
631 break;
632 case ImmCheckType::ImmCheck0_255:
633 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 255))
634 return true;
635 break;
636 case ImmCheckType::ImmCheck1_32:
637 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32))
638 return true;
639 break;
640 case ImmCheckType::ImmCheck1_64:
641 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64))
642 return true;
643 break;
644 case ImmCheckType::ImmCheck2_4_Mul2:
645 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 2, 4) ||
646 SemaRef.BuiltinConstantArgMultiple(TheCall, ArgIdx, 2))
647 return true;
648 break;
649 }
650 return false;
651}
652
654 CallExpr *TheCall,
655 SmallVectorImpl<std::tuple<int, int, int, int>> &ImmChecks,
656 int OverloadType) {
657 bool HasError = false;
658
659 for (const auto &I : ImmChecks) {
660 auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I;
661
662 if (OverloadType >= 0)
663 ElementBitWidth = NeonTypeFlags(OverloadType).getEltSizeInBits();
664
665 HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth,
666 VecBitWidth);
667 }
668
669 return HasError;
670}
671
673 CallExpr *TheCall, SmallVectorImpl<std::tuple<int, int, int>> &ImmChecks) {
674 bool HasError = false;
675
676 for (const auto &I : ImmChecks) {
677 auto [ArgIdx, CheckTy, ElementBitWidth] = I;
678 HasError |=
679 CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 128);
680 }
681
682 return HasError;
683}
684
686 if (FD->hasAttr<ArmLocallyStreamingAttr>())
688 if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
689 if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
690 if (FPT->getAArch64SMEAttributes() &
693 if (FPT->getAArch64SMEAttributes() &
696 }
697 }
699}
700
701static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
702 const FunctionDecl *FD,
704 unsigned BuiltinID) {
706
707 // Check if the intrinsic is available in the right mode, i.e.
708 // * When compiling for SME only, the caller must be in streaming mode.
709 // * When compiling for SVE only, the caller must be in non-streaming mode.
710 // * When compiling for both SVE and SME, the caller can be in either mode.
712 llvm::StringMap<bool> CallerFeatures;
713 S.Context.getFunctionFeatureMap(CallerFeatures, FD);
714
715 // Avoid emitting diagnostics for a function that can never compile.
716 if (FnType == SemaARM::ArmStreaming && !CallerFeatures["sme"])
717 return false;
718
719 const auto FindTopLevelPipe = [](const char *S) {
720 unsigned Depth = 0;
721 unsigned I = 0, E = strlen(S);
722 for (; I < E; ++I) {
723 if (S[I] == '|' && Depth == 0)
724 break;
725 if (S[I] == '(')
726 ++Depth;
727 else if (S[I] == ')')
728 --Depth;
729 }
730 return I;
731 };
732
733 const char *RequiredFeatures =
735 unsigned PipeIdx = FindTopLevelPipe(RequiredFeatures);
736 assert(PipeIdx != 0 && PipeIdx != strlen(RequiredFeatures) &&
737 "Expected feature string of the form 'SVE-EXPR|SME-EXPR'");
738 StringRef NonStreamingBuiltinGuard = StringRef(RequiredFeatures, PipeIdx);
739 StringRef StreamingBuiltinGuard = StringRef(RequiredFeatures + PipeIdx + 1);
740
741 bool SatisfiesSVE = Builtin::evaluateRequiredTargetFeatures(
742 NonStreamingBuiltinGuard, CallerFeatures);
743 bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures(
744 StreamingBuiltinGuard, CallerFeatures);
745
746 if (SatisfiesSVE && SatisfiesSME)
747 // Function type is irrelevant for streaming-agnostic builtins.
748 return false;
749 else if (SatisfiesSVE)
751 else if (SatisfiesSME)
753 else
754 // This should be diagnosed by CodeGen
755 return false;
756 }
757
758 if (FnType != SemaARM::ArmNonStreaming &&
760 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
761 << TheCall->getSourceRange() << "non-streaming";
762 else if (FnType != SemaARM::ArmStreaming &&
764 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
765 << TheCall->getSourceRange() << "streaming";
766 else
767 return false;
768
769 return true;
770}
771
772static ArmSMEState getSMEState(unsigned BuiltinID) {
773 switch (BuiltinID) {
774 default:
775 return ArmNoState;
776#define GET_SME_BUILTIN_GET_STATE
777#include "clang/Basic/arm_sme_builtins_za_state.inc"
778#undef GET_SME_BUILTIN_GET_STATE
779 }
780}
781
783 CallExpr *TheCall) {
784 if (const FunctionDecl *FD =
785 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
786 std::optional<ArmStreamingType> BuiltinType;
787
788 switch (BuiltinID) {
789#define GET_SME_STREAMING_ATTRS
790#include "clang/Basic/arm_sme_streaming_attrs.inc"
791#undef GET_SME_STREAMING_ATTRS
792 }
793
794 if (BuiltinType &&
795 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
796 return true;
797
798 if ((getSMEState(BuiltinID) & ArmZAMask) && !hasArmZAState(FD)) {
799 Diag(TheCall->getBeginLoc(),
800 diag::err_attribute_arm_za_builtin_no_za_state)
801 << TheCall->getSourceRange();
802 return true;
803 }
804
805 if ((getSMEState(BuiltinID) & ArmZT0Mask) && !hasArmZT0State(FD)) {
806 Diag(TheCall->getBeginLoc(),
807 diag::err_attribute_arm_zt0_builtin_no_zt0_state)
808 << TheCall->getSourceRange();
809 return true;
810 }
811 }
812
813 // Range check SME intrinsics that take immediate values.
815
816 switch (BuiltinID) {
817 default:
818 return false;
819#define GET_SME_IMMEDIATE_CHECK
820#include "clang/Basic/arm_sme_sema_rangechecks.inc"
821#undef GET_SME_IMMEDIATE_CHECK
822 }
823
824 return PerformSVEImmChecks(TheCall, ImmChecks);
825}
826
828 CallExpr *TheCall) {
829 if (const FunctionDecl *FD =
830 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
831 std::optional<ArmStreamingType> BuiltinType;
832
833 switch (BuiltinID) {
834#define GET_SVE_STREAMING_ATTRS
835#include "clang/Basic/arm_sve_streaming_attrs.inc"
836#undef GET_SVE_STREAMING_ATTRS
837 }
838 if (BuiltinType &&
839 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
840 return true;
841 }
842 // Range check SVE intrinsics that take immediate values.
844
845 switch (BuiltinID) {
846 default:
847 return false;
848#define GET_SVE_IMMEDIATE_CHECK
849#include "clang/Basic/arm_sve_sema_rangechecks.inc"
850#undef GET_SVE_IMMEDIATE_CHECK
851 }
852
853 return PerformSVEImmChecks(TheCall, ImmChecks);
854}
855
857 unsigned BuiltinID,
858 CallExpr *TheCall) {
859 if (const FunctionDecl *FD =
860 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
861 std::optional<ArmStreamingType> BuiltinType;
862
863 switch (BuiltinID) {
864 default:
865 break;
866#define GET_NEON_STREAMING_COMPAT_FLAG
867#include "clang/Basic/arm_neon.inc"
868#undef GET_NEON_STREAMING_COMPAT_FLAG
869 }
870 if (BuiltinType &&
871 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
872 return true;
873 }
874
875 llvm::APSInt Result;
876 uint64_t mask = 0;
877 int TV = -1;
878 int PtrArgNum = -1;
879 bool HasConstPtr = false;
880 switch (BuiltinID) {
881#define GET_NEON_OVERLOAD_CHECK
882#include "clang/Basic/arm_fp16.inc"
883#include "clang/Basic/arm_neon.inc"
884#undef GET_NEON_OVERLOAD_CHECK
885 }
886
887 // For NEON intrinsics which are overloaded on vector element type, validate
888 // the immediate which specifies which variant to emit.
889 if (mask) {
890 unsigned ImmArg = TheCall->getNumArgs() - 1;
891 if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result))
892 return true;
893
894 // FIXME: This is effectively dead code. Change the logic above so that the
895 // following check is actually run.
896 TV = Result.getLimitedValue(64);
897 if ((TV > 63) || (mask & (1ULL << TV)) == 0)
898 return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
899 << TheCall->getArg(ImmArg)->getSourceRange();
900 }
901
902 if (PtrArgNum >= 0) {
903 // Check that pointer arguments have the specified type.
904 Expr *Arg = TheCall->getArg(PtrArgNum);
905 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
906 Arg = ICE->getSubExpr();
907 ExprResult RHS = SemaRef.DefaultFunctionArrayLvalueConversion(Arg);
908 QualType RHSTy = RHS.get()->getType();
909
910 llvm::Triple::ArchType Arch = TI.getTriple().getArch();
911 bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
912 Arch == llvm::Triple::aarch64_32 ||
913 Arch == llvm::Triple::aarch64_be;
914 bool IsInt64Long = TI.getInt64Type() == TargetInfo::SignedLong;
916 IsPolyUnsigned, IsInt64Long);
917 if (HasConstPtr)
918 EltTy = EltTy.withConst();
919 QualType LHSTy = getASTContext().getPointerType(EltTy);
920 AssignConvertType ConvTy;
921 ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);
922 if (RHS.isInvalid())
923 return true;
924 if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy,
925 RHSTy, RHS.get(),
927 return true;
928 }
929
930 // For NEON intrinsics which take an immediate value as part of the
931 // instruction, range check them here.
933 switch (BuiltinID) {
934 default:
935 return false;
936#define GET_NEON_IMMEDIATE_CHECK
937#include "clang/Basic/arm_fp16.inc"
938#include "clang/Basic/arm_neon.inc"
939#undef GET_NEON_IMMEDIATE_CHECK
940 }
941
942 return PerformNeonImmChecks(TheCall, ImmChecks, TV);
943}
944
946 CallExpr *TheCall) {
947 switch (BuiltinID) {
948 default:
949 return false;
950#include "clang/Basic/arm_mve_builtin_sema.inc"
951 }
952}
953
955 unsigned BuiltinID,
956 CallExpr *TheCall) {
957 bool Err = false;
958 switch (BuiltinID) {
959 default:
960 return false;
961#include "clang/Basic/arm_cde_builtin_sema.inc"
962 }
963
964 if (Err)
965 return true;
966
967 return CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), /*WantCDE*/ true);
968}
969
971 const Expr *CoprocArg,
972 bool WantCDE) {
973 ASTContext &Context = getASTContext();
974 if (SemaRef.isConstantEvaluatedContext())
975 return false;
976
977 // We can't check the value of a dependent argument.
978 if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
979 return false;
980
981 llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context);
982 int64_t CoprocNo = CoprocNoAP.getExtValue();
983 assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
984
985 uint32_t CDECoprocMask = TI.getARMCDECoprocMask();
986 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
987
988 if (IsCDECoproc != WantCDE)
989 return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
990 << (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange();
991
992 return false;
993}
994
996 unsigned BuiltinID,
997 CallExpr *TheCall) {
998 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
999 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
1000 BuiltinID == ARM::BI__builtin_arm_ldaex ||
1001 BuiltinID == ARM::BI__builtin_arm_strex ||
1002 BuiltinID == ARM::BI__builtin_arm_strexd ||
1003 BuiltinID == ARM::BI__builtin_arm_stlex ||
1004 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1005 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1006 BuiltinID == AArch64::BI__builtin_arm_strex ||
1007 BuiltinID == AArch64::BI__builtin_arm_stlex) &&
1008 "unexpected ARM builtin");
1009 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
1010 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
1011 BuiltinID == ARM::BI__builtin_arm_ldaex ||
1012 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1013 BuiltinID == AArch64::BI__builtin_arm_ldaex;
1014 bool IsDoubleWord = BuiltinID == ARM::BI__builtin_arm_ldrexd ||
1015 BuiltinID == ARM::BI__builtin_arm_strexd;
1016
1017 ASTContext &Context = getASTContext();
1018 DeclRefExpr *DRE =
1020
1021 // Ensure that we have the proper number of arguments.
1022 if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))
1023 return true;
1024
1025 // Inspect the pointer argument of the atomic builtin. This should always be
1026 // a pointer type, whose element is an integral scalar or pointer type.
1027 // Because it is a pointer type, we don't have to worry about any implicit
1028 // casts here.
1029 Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
1030 ExprResult PointerArgRes =
1031 SemaRef.DefaultFunctionArrayLvalueConversion(PointerArg);
1032 if (PointerArgRes.isInvalid())
1033 return true;
1034 PointerArg = PointerArgRes.get();
1035
1036 const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
1037 if (!pointerType) {
1038 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
1039 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
1040 return true;
1041 }
1042
1043 // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next
1044 // task is to insert the appropriate casts into the AST. First work out just
1045 // what the appropriate type is.
1046 QualType ValType = pointerType->getPointeeType();
1047 QualType AddrType = ValType.getUnqualifiedType().withVolatile();
1048 if (IsLdrex)
1049 AddrType.addConst();
1050
1051 // Issue a warning if the cast is dodgy.
1052 CastKind CastNeeded = CK_NoOp;
1053 if (!AddrType.isAtLeastAsQualifiedAs(ValType, getASTContext())) {
1054 CastNeeded = CK_BitCast;
1055 Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
1056 << PointerArg->getType() << Context.getPointerType(AddrType)
1057 << AssignmentAction::Passing << PointerArg->getSourceRange();
1058 }
1059
1060 // Finally, do the cast and replace the argument with the corrected version.
1061 AddrType = Context.getPointerType(AddrType);
1062 PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);
1063 if (PointerArgRes.isInvalid())
1064 return true;
1065 PointerArg = PointerArgRes.get();
1066
1067 TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
1068
1069 // In general, we allow ints, floats and pointers to be loaded and stored.
1070 if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
1071 !ValType->isBlockPointerType() && !ValType->isFloatingType()) {
1072 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
1073 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
1074 return true;
1075 }
1076
1077 // Check whether the size of the type can be handled atomically on this
1078 // target.
1079 if (!TI.getTriple().isAArch64()) {
1080 unsigned Mask = TI.getARMLDREXMask();
1081 unsigned Bits = Context.getTypeSize(ValType);
1082 if (IsDoubleWord) {
1083 // Explicit request for ldrexd/strexd means only double word sizes
1084 // supported if the target supports them.
1086 }
1087 bool Supported =
1088 (llvm::isPowerOf2_64(Bits)) && Bits >= 8 && (Mask & (Bits / 8));
1089
1090 if (!Supported) {
1091 // Emit a diagnostic saying that this size isn't available. If _no_ size
1092 // of exclusive access is supported on this target, we emit a diagnostic
1093 // with special wording for that case, but otherwise, we emit
1094 // err_atomic_exclusive_builtin_pointer_size and loop over `Mask` to
1095 // control what subset of sizes it lists as legal.
1096 if (Mask) {
1097 auto D = Diag(DRE->getBeginLoc(),
1098 diag::err_atomic_exclusive_builtin_pointer_size)
1099 << PointerArg->getType();
1100 bool Started = false;
1101 for (unsigned Size = 1; Size <= 8; Size <<= 1) {
1102 // For each of the sizes 1,2,4,8, pass two integers into the
1103 // diagnostic. The first selects a separator from the previous
1104 // number: 0 for no separator at all, 1 for a comma, 2 for " or "
1105 // which appears before the final number in a list of more than one.
1106 // The second integer just indicates whether we print this size in
1107 // the message at all.
1108 if (!(Mask & Size)) {
1109 // This size isn't one of the supported ones, so emit no separator
1110 // text and don't print the size itself.
1111 D << 0 << 0;
1112 } else {
1113 // This size is supported, so print it, and an appropriate
1114 // separator.
1115 Mask &= ~Size;
1116 if (!Started)
1117 D << 0; // No separator if this is the first size we've printed
1118 else if (Mask)
1119 D << 1; // "," if there's still another size to come
1120 else
1121 D << 2; // " or " if the size we're about to print is the last
1122 D << 1; // print the size itself
1123 Started = true;
1124 }
1125 }
1126 } else {
1127 bool EmitDoubleWordDiagnostic =
1128 IsDoubleWord && !Mask && TI.getARMLDREXMask();
1129 Diag(DRE->getBeginLoc(),
1130 diag::err_atomic_exclusive_builtin_pointer_size_none)
1131 << (EmitDoubleWordDiagnostic ? 1 : 0)
1132 << PointerArg->getSourceRange();
1133 }
1134 }
1135 }
1136
1137 switch (ValType.getObjCLifetime()) {
1140 // okay
1141 break;
1142
1146 Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
1147 << ValType << PointerArg->getSourceRange();
1148 return true;
1149 }
1150
1151 if (IsLdrex) {
1152 TheCall->setType(ValType);
1153 return false;
1154 }
1155
1156 // Initialize the argument to be stored.
1157 ExprResult ValArg = TheCall->getArg(0);
1159 Context, ValType, /*consume*/ false);
1160 ValArg = SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg);
1161 if (ValArg.isInvalid())
1162 return true;
1163 TheCall->setArg(0, ValArg.get());
1164
1165 // __builtin_arm_strex always returns an int. It's marked as such in the .def,
1166 // but the custom checker bypasses all default analysis.
1167 TheCall->setType(Context.IntTy);
1168 return false;
1169}
1170
1171static bool checkFPMScaleIfConstant(Sema &S, CallExpr *Call, unsigned ArgNum,
1172 int64_t Low, int64_t High) {
1173 Expr *Arg = Call->getArg(ArgNum);
1174
1175 if (Arg->isTypeDependent() || Arg->isValueDependent())
1176 return false;
1177
1178 std::optional<llvm::APSInt> Value = Arg->getIntegerConstantExpr(S.Context);
1179
1180 // Runtime value: accept it.
1181 if (!Value)
1182 return false;
1183
1184 if (*Value < Low || *Value > High)
1185 return S.Diag(Call->getBeginLoc(), diag::warn_argument_invalid_range)
1186 << toString(*Value, 10) << Low << High << Arg->getSourceRange();
1187
1188 return false;
1189}
1190
1192 unsigned BuiltinID,
1193 CallExpr *TheCall) {
1194 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
1195 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
1196 BuiltinID == ARM::BI__builtin_arm_ldaex ||
1197 BuiltinID == ARM::BI__builtin_arm_strex ||
1198 BuiltinID == ARM::BI__builtin_arm_strexd ||
1199 BuiltinID == ARM::BI__builtin_arm_stlex) {
1200 return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
1201 }
1202
1203 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
1204 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1205 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
1206 }
1207
1208 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
1209 BuiltinID == ARM::BI__builtin_arm_wsr64)
1210 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);
1211
1212 if (BuiltinID == ARM::BI__builtin_arm_rsr ||
1213 BuiltinID == ARM::BI__builtin_arm_rsrp ||
1214 BuiltinID == ARM::BI__builtin_arm_wsr ||
1215 BuiltinID == ARM::BI__builtin_arm_wsrp)
1216 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1217
1218 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1219 return true;
1220 if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall))
1221 return true;
1222 if (CheckCDEBuiltinFunctionCall(TI, BuiltinID, TheCall))
1223 return true;
1224 // For intrinsics which take an immediate value as part of the instruction,
1225 // range check them here.
1226 // FIXME: VFP Intrinsics should error if VFP not present.
1227 switch (BuiltinID) {
1228 default:
1229 return false;
1230 case ARM::BI__builtin_arm_ssat:
1231 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);
1232 case ARM::BI__builtin_arm_usat:
1233 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1234 case ARM::BI__builtin_arm_ssat16:
1235 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
1236 case ARM::BI__builtin_arm_usat16:
1237 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
1238 case ARM::BI__builtin_arm_vcvtr_f:
1239 case ARM::BI__builtin_arm_vcvtr_d:
1240 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
1241 case ARM::BI__builtin_arm_dmb:
1242 case ARM::BI__dmb:
1243 case ARM::BI__builtin_arm_dsb:
1244 case ARM::BI__dsb:
1245 case ARM::BI__builtin_arm_isb:
1246 case ARM::BI__isb:
1247 case ARM::BI__builtin_arm_dbg:
1248 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
1249 case ARM::BI__builtin_arm_cdp:
1250 case ARM::BI__builtin_arm_cdp2:
1251 case ARM::BI__builtin_arm_mcr:
1252 case ARM::BI__builtin_arm_mcr2:
1253 case ARM::BI__builtin_arm_mrc:
1254 case ARM::BI__builtin_arm_mrc2:
1255 case ARM::BI__builtin_arm_mcrr:
1256 case ARM::BI__builtin_arm_mcrr2:
1257 case ARM::BI__builtin_arm_mrrc:
1258 case ARM::BI__builtin_arm_mrrc2:
1259 case ARM::BI__builtin_arm_ldc:
1260 case ARM::BI__builtin_arm_ldcl:
1261 case ARM::BI__builtin_arm_ldc2:
1262 case ARM::BI__builtin_arm_ldc2l:
1263 case ARM::BI__builtin_arm_stc:
1264 case ARM::BI__builtin_arm_stcl:
1265 case ARM::BI__builtin_arm_stc2:
1266 case ARM::BI__builtin_arm_stc2l:
1267 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
1268 CheckARMCoprocessorImmediate(TI, TheCall->getArg(0),
1269 /*WantCDE*/ false);
1270 }
1271}
1272
1274 unsigned BuiltinID,
1275 CallExpr *TheCall) {
1276 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1277 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1278 BuiltinID == AArch64::BI__builtin_arm_strex ||
1279 BuiltinID == AArch64::BI__builtin_arm_stlex) {
1280 return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
1281 }
1282
1283 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
1284 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1285 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
1286 SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
1287 SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);
1288 }
1289
1290 if (BuiltinID == AArch64::BI__builtin_arm_range_prefetch_x) {
1291 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1292 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1) ||
1293 SemaRef.BuiltinConstantArgRange(TheCall, 3, -2097152, 2097151) ||
1294 SemaRef.BuiltinConstantArgRange(TheCall, 4, 1, 65536) ||
1295 SemaRef.BuiltinConstantArgRange(TheCall, 5, -2097152, 2097151);
1296 }
1297
1298 if (BuiltinID == AArch64::BI__builtin_arm_range_prefetch) {
1299 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1300 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
1301 }
1302
1303 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
1304 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
1305 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
1306 BuiltinID == AArch64::BI__builtin_arm_wsr128)
1307 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1308
1309 // Memory Tagging Extensions (MTE) Intrinsics
1310 if (BuiltinID == AArch64::BI__builtin_arm_irg ||
1311 BuiltinID == AArch64::BI__builtin_arm_addg ||
1312 BuiltinID == AArch64::BI__builtin_arm_gmi ||
1313 BuiltinID == AArch64::BI__builtin_arm_ldg ||
1314 BuiltinID == AArch64::BI__builtin_arm_stg ||
1315 BuiltinID == AArch64::BI__builtin_arm_subp) {
1316 return BuiltinARMMemoryTaggingCall(BuiltinID, TheCall);
1317 }
1318
1319 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
1320 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
1321 BuiltinID == AArch64::BI__builtin_arm_wsr ||
1322 BuiltinID == AArch64::BI__builtin_arm_wsrp)
1323 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1324
1325 if (BuiltinID == AArch64::BI__builtin_arm_atomic_store_with_hint ||
1326 BuiltinID == AArch64::BI__builtin_arm_atomic_fetch_add_with_hint ||
1327 BuiltinID == AArch64::BI__builtin_arm_atomic_fetch_sub_with_hint ||
1328 BuiltinID == AArch64::BI__builtin_arm_atomic_fetch_and_with_hint ||
1329 BuiltinID == AArch64::BI__builtin_arm_atomic_fetch_xor_with_hint ||
1330 BuiltinID == AArch64::BI__builtin_arm_atomic_fetch_or_with_hint)
1331 return BuiltinARMAtomicHintCall(BuiltinID, TheCall);
1332
1333 // Only check the valid encoding range. Any constant in this range would be
1334 // converted to a register of the form S2_2_C3_C4_5. Let the hardware throw
1335 // an exception for incorrect registers. This matches MSVC behavior.
1336 // Bit 14 is o0, i.e. op0 - 2, so op0 == 2 registers have it clear and encode
1337 // below 0x4000.
1338 if (BuiltinID == AArch64::BI_ReadStatusReg ||
1339 BuiltinID == AArch64::BI_WriteStatusReg)
1340 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
1341
1342 if (BuiltinID == AArch64::BI__sys)
1343 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x3fff);
1344
1345 if (BuiltinID == AArch64::BI__getReg || BuiltinID == AArch64::BI__setReg ||
1346 BuiltinID == AArch64::BI__getRegFp || BuiltinID == AArch64::BI__setRegFp)
1347 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
1348
1349 if (BuiltinID == AArch64::BI__prefetch2)
1350 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1351
1352 if (BuiltinID == AArch64::BI__break)
1353 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1354
1355 if (BuiltinID == AArch64::BI__hlt)
1356 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1357
1358 if (BuiltinID == AArch64::BI__hvc || BuiltinID == AArch64::BI__svc) {
1359 // The immediate is the instruction number; the remaining arguments (at most
1360 // four) are passed in X0-X3, so the call takes at most five arguments.
1361 if (SemaRef.checkArgCountAtMost(TheCall, 5) ||
1362 SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff))
1363 return true;
1364 const FunctionDecl *FD = TheCall->getDirectCallee();
1365 for (unsigned I = 1, N = TheCall->getNumArgs(); I < N; ++I) {
1366 const Expr *Arg = TheCall->getArg(I);
1367 QualType Ty = Arg->getType();
1368 if (!Ty->isIntegerType() && !Ty->isAnyPointerType() &&
1369 !Ty->isBlockPointerType() && !Ty->isFloatingType())
1370 return Diag(Arg->getBeginLoc(),
1371 diag::err_aarch64_svc_hvc_invalid_arg_type)
1372 << I + 1 << FD << Ty << Arg->getSourceRange();
1373 }
1374 return false;
1375 }
1376
1377 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1378 return true;
1379
1380 if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall))
1381 return true;
1382
1383 if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall))
1384 return true;
1385
1386 if (BuiltinID == AArch64::BI__arm_set_fpm_lscale)
1387 return checkFPMScaleIfConstant(SemaRef, TheCall, 1, 0, 127);
1388
1389 if (BuiltinID == AArch64::BI__arm_set_fpm_nscale)
1390 return checkFPMScaleIfConstant(SemaRef, TheCall, 1, -128, 127);
1391
1392 if (BuiltinID == AArch64::BI__arm_set_fpm_lscale2)
1393 return checkFPMScaleIfConstant(SemaRef, TheCall, 1, 0, 63);
1394
1395 // For intrinsics which take an immediate value as part of the instruction,
1396 // range check them here.
1397 unsigned i = 0, l = 0, u = 0;
1398 switch (BuiltinID) {
1399 default: return false;
1400 case AArch64::BI__builtin_arm_dmb:
1401 case AArch64::BI__dmb:
1402 case AArch64::BI__builtin_arm_dsb:
1403 case AArch64::BI__dsb:
1404 case AArch64::BI__builtin_arm_isb:
1405 case AArch64::BI__isb:
1406 l = 0;
1407 u = 15;
1408 break;
1409 }
1410
1411 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
1412}
1413
1414namespace {
1415struct IntrinToName {
1416 uint32_t Id;
1417 int32_t FullName;
1418 int32_t ShortName;
1419};
1420} // unnamed namespace
1421
1422static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
1424 const char *IntrinNames) {
1425 AliasName.consume_front("__arm_");
1426 const IntrinToName *It =
1427 llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
1428 return L.Id < Id;
1429 });
1430 if (It == Map.end() || It->Id != BuiltinID)
1431 return false;
1432 StringRef FullName(&IntrinNames[It->FullName]);
1433 if (AliasName == FullName)
1434 return true;
1435 if (It->ShortName == -1)
1436 return false;
1437 StringRef ShortName(&IntrinNames[It->ShortName]);
1438 return AliasName == ShortName;
1439}
1440
1441bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1442#include "clang/Basic/arm_mve_builtin_aliases.inc"
1443 // The included file defines:
1444 // - ArrayRef<IntrinToName> Map
1445 // - const char IntrinNames[]
1446 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1447}
1448
1449bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1450#include "clang/Basic/arm_cde_builtin_aliases.inc"
1451 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1452}
1453
1454bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1455 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1456 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1457 return BuiltinID >= AArch64::FirstSVEBuiltin &&
1458 BuiltinID <= AArch64::LastSVEBuiltin;
1459}
1460
1461bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1462 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1463 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1464 return BuiltinID >= AArch64::FirstSMEBuiltin &&
1465 BuiltinID <= AArch64::LastSMEBuiltin;
1466}
1467
1469 ASTContext &Context = getASTContext();
1470 if (!AL.isArgIdent(0)) {
1471 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
1472 << AL << 1 << AANT_ArgumentIdentifier;
1473 return;
1474 }
1475
1477 unsigned BuiltinID = Ident->getBuiltinID();
1478 StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
1479
1480 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
1481 if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) &&
1482 !SmeAliasValid(BuiltinID, AliasName)) ||
1483 (!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) &&
1484 !CdeAliasValid(BuiltinID, AliasName))) {
1485 Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
1486 return;
1487 }
1488
1489 D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
1490}
1491
1493 Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT,
1494 FunctionType::ArmStateValue CurrentState, StringRef StateName) {
1495 auto CheckForIncompatibleAttr =
1496 [&](FunctionType::ArmStateValue IncompatibleState,
1497 StringRef IncompatibleStateName) {
1498 if (CurrentState == IncompatibleState) {
1499 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
1500 << (std::string("'__arm_new(\"") + StateName.str() + "\")'")
1501 << (std::string("'") + IncompatibleStateName.str() + "(\"" +
1502 StateName.str() + "\")'")
1503 << true;
1504 AL.setInvalid();
1505 }
1506 };
1507
1508 CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in");
1509 CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out");
1510 CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout");
1511 CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves");
1512 return AL.isInvalid();
1513}
1514
1516 if (!AL.getNumArgs()) {
1517 Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
1518 AL.setInvalid();
1519 return;
1520 }
1521
1522 std::vector<StringRef> NewState;
1523 if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) {
1524 for (StringRef S : ExistingAttr->newArgs())
1525 NewState.push_back(S);
1526 }
1527
1528 bool HasZA = false;
1529 bool HasZT0 = false;
1530 for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1531 StringRef StateName;
1532 SourceLocation LiteralLoc;
1533 if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
1534 return;
1535
1536 if (StateName == "za")
1537 HasZA = true;
1538 else if (StateName == "zt0")
1539 HasZT0 = true;
1540 else {
1541 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
1542 AL.setInvalid();
1543 return;
1544 }
1545
1546 if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates.
1547 NewState.push_back(StateName);
1548 }
1549
1550 if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) {
1552 FunctionType::getArmZAState(FPT->getAArch64SMEAttributes());
1553 if (HasZA && ZAState != FunctionType::ARM_None &&
1554 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za"))
1555 return;
1557 FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes());
1558 if (HasZT0 && ZT0State != FunctionType::ARM_None &&
1559 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0"))
1560 return;
1561 }
1562
1563 D->dropAttr<ArmNewAttr>();
1564 D->addAttr(::new (getASTContext()) ArmNewAttr(
1565 getASTContext(), AL, NewState.data(), NewState.size()));
1566}
1567
1570 Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
1571 return;
1572 }
1573
1574 const auto *FD = cast<FunctionDecl>(D);
1575 if (!FD->isExternallyVisible()) {
1576 Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
1577 return;
1578 }
1579
1580 D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL));
1581}
1582
1584 // Check the attribute arguments.
1585 if (AL.getNumArgs() > 1) {
1586 Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
1587 return;
1588 }
1589
1590 StringRef Str;
1591 SourceLocation ArgLoc;
1592
1593 if (AL.getNumArgs() == 0)
1594 Str = "";
1595 else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1596 return;
1597
1598 ARMInterruptAttr::InterruptType Kind;
1599 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
1600 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1601 << AL << Str << ArgLoc;
1602 return;
1603 }
1604
1605 if (!D->hasAttr<ARMSaveFPAttr>()) {
1606 const TargetInfo &TI = getASTContext().getTargetInfo();
1607 if (TI.hasFeature("vfp"))
1608 Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1609 }
1610
1611 D->addAttr(::new (getASTContext())
1612 ARMInterruptAttr(getASTContext(), AL, Kind));
1613}
1614
1616 // Go ahead and add ARMSaveFPAttr because handleInterruptAttr() checks for
1617 // it when deciding to issue a diagnostic about clobbering floating point
1618 // registers, which ARMSaveFPAttr prevents.
1619 D->addAttr(::new (SemaRef.Context) ARMSaveFPAttr(SemaRef.Context, AL));
1620 SemaRef.ARM().handleInterruptAttr(D, AL);
1621
1622 // If ARM().handleInterruptAttr() failed, remove ARMSaveFPAttr.
1623 if (!D->hasAttr<ARMInterruptAttr>()) {
1624 D->dropAttr<ARMSaveFPAttr>();
1625 return;
1626 }
1627
1628 // If VFP not enabled, remove ARMSaveFPAttr but leave ARMInterruptAttr.
1629 bool VFP = SemaRef.Context.getTargetInfo().hasFeature("vfp");
1630
1631 if (!VFP) {
1632 SemaRef.Diag(D->getLocation(), diag::warn_arm_interrupt_save_fp_without_vfp_unit);
1633 D->dropAttr<ARMSaveFPAttr>();
1634 }
1635}
1636
1637// Check if the function definition uses any AArch64 SME features without
1638// having the '+sme' feature enabled and warn user if sme locally streaming
1639// function returns or uses arguments with VL-based types.
1641 const auto *Attr = FD->getAttr<ArmNewAttr>();
1642 bool UsesSM = FD->hasAttr<ArmLocallyStreamingAttr>();
1643 bool UsesZA = Attr && Attr->isNewZA();
1644 bool UsesZT0 = Attr && Attr->isNewZT0();
1645
1646 if (UsesZA || UsesZT0) {
1647 if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
1648 FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1650 Diag(FD->getLocation(), diag::err_sme_unsupported_agnostic_new);
1651 }
1652 }
1653
1654 if (FD->hasAttr<ArmLocallyStreamingAttr>()) {
1656 Diag(FD->getLocation(),
1657 diag::warn_sme_locally_streaming_has_vl_args_returns)
1658 << /*IsArg=*/false;
1659 if (llvm::any_of(FD->parameters(), [](ParmVarDecl *P) {
1660 return P->getOriginalType()->isSizelessVectorType();
1661 }))
1662 Diag(FD->getLocation(),
1663 diag::warn_sme_locally_streaming_has_vl_args_returns)
1664 << /*IsArg=*/true;
1665 }
1666 if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
1667 FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1673 }
1674
1675 ASTContext &Context = getASTContext();
1676 if (UsesSM || UsesZA) {
1677 llvm::StringMap<bool> FeatureMap;
1678 Context.getFunctionFeatureMap(FeatureMap, FD);
1679 if (!FeatureMap.contains("sme")) {
1680 if (UsesSM)
1681 Diag(FD->getLocation(),
1682 diag::err_sme_definition_using_sm_in_non_sme_target);
1683 else
1684 Diag(FD->getLocation(),
1685 diag::err_sme_definition_using_za_in_non_sme_target);
1686 }
1687 }
1688 if (UsesZT0) {
1689 llvm::StringMap<bool> FeatureMap;
1690 Context.getFunctionFeatureMap(FeatureMap, FD);
1691 if (!FeatureMap.contains("sme2")) {
1692 Diag(FD->getLocation(),
1693 diag::err_sme_definition_using_zt0_in_non_sme2_target);
1694 }
1695 }
1696}
1697
1698/// getSVETypeSize - Return SVE vector or predicate register size.
1699static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty,
1700 bool IsStreaming) {
1701 assert(Ty->isSveVLSBuiltinType() && "Invalid SVE Type");
1702 uint64_t VScale = IsStreaming ? Context.getLangOpts().VScaleStreamingMin
1703 : Context.getLangOpts().VScaleMin;
1704 if (Ty->getKind() == BuiltinType::SveBool ||
1705 Ty->getKind() == BuiltinType::SveCount)
1706 return (VScale * 128) / Context.getCharWidth();
1707 return VScale * 128;
1708}
1709
1711 bool IsStreaming = false;
1712 if (getLangOpts().VScaleMin != getLangOpts().VScaleStreamingMin ||
1713 getLangOpts().VScaleMax != getLangOpts().VScaleStreamingMax) {
1714 if (const FunctionDecl *FD =
1715 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
1716 // For streaming-compatible functions, we don't know vector length.
1717 if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
1718 if (T->getAArch64SMEAttributes() &
1720 return false;
1721 }
1722
1723 if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
1724 IsStreaming = true;
1725 }
1726 }
1727
1728 auto IsValidCast = [&](QualType FirstType, QualType SecondType) {
1729 if (const auto *BT = FirstType->getAs<BuiltinType>()) {
1730 if (const auto *VT = SecondType->getAs<VectorType>()) {
1731 // Predicates have the same representation as uint8 so we also have to
1732 // check the kind to make these types incompatible.
1733 ASTContext &Context = getASTContext();
1734 if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate)
1735 return BT->getKind() == BuiltinType::SveBool;
1736 else if (VT->getVectorKind() == VectorKind::SveFixedLengthData)
1737 return VT->getElementType().getCanonicalType() ==
1738 FirstType->getSveEltType(Context) &&
1739 BT->getKind() != BuiltinType::SveBool;
1740 else if (VT->getVectorKind() == VectorKind::Generic)
1741 return Context.getTypeSize(SecondType) ==
1742 getSVETypeSize(Context, BT, IsStreaming) &&
1743 Context.hasSameType(
1744 VT->getElementType(),
1745 Context.getBuiltinVectorTypeInfo(BT).ElementType);
1746 }
1747 }
1748 return false;
1749 };
1750
1751 return IsValidCast(FirstType, SecondType) ||
1752 IsValidCast(SecondType, FirstType);
1753}
1754
1756 QualType SecondType) {
1757 bool IsStreaming = false;
1758 if (getLangOpts().VScaleMin != getLangOpts().VScaleStreamingMin ||
1759 getLangOpts().VScaleMax != getLangOpts().VScaleStreamingMax) {
1760 if (const FunctionDecl *FD =
1761 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
1762 // For streaming-compatible functions, we don't know vector length.
1763 if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
1764 if (T->getAArch64SMEAttributes() &
1766 return false;
1767
1768 if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
1769 IsStreaming = true;
1770 }
1771 }
1772
1773 auto IsLaxCompatible = [&](QualType FirstType, QualType SecondType) {
1774 const auto *BT = FirstType->getAs<BuiltinType>();
1775 if (!BT)
1776 return false;
1777
1778 const auto *VecTy = SecondType->getAs<VectorType>();
1779 if (VecTy && (VecTy->getVectorKind() == VectorKind::SveFixedLengthData ||
1780 VecTy->getVectorKind() == VectorKind::Generic)) {
1782 getLangOpts().getLaxVectorConversions();
1783 ASTContext &Context = getASTContext();
1784
1785 // Can not convert between sve predicates and sve vectors because of
1786 // different size.
1787 if (BT->getKind() == BuiltinType::SveBool &&
1788 VecTy->getVectorKind() == VectorKind::SveFixedLengthData)
1789 return false;
1790
1791 // If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion.
1792 // "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly
1793 // converts to VLAT and VLAT implicitly converts to GNUT."
1794 // ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and
1795 // predicates.
1796 if (VecTy->getVectorKind() == VectorKind::Generic &&
1797 Context.getTypeSize(SecondType) !=
1798 getSVETypeSize(Context, BT, IsStreaming))
1799 return false;
1800
1801 // If -flax-vector-conversions=all is specified, the types are
1802 // certainly compatible.
1804 return true;
1805
1806 // If -flax-vector-conversions=integer is specified, the types are
1807 // compatible if the elements are integer types.
1809 return VecTy->getElementType().getCanonicalType()->isIntegerType() &&
1810 FirstType->getSveEltType(Context)->isIntegerType();
1811 }
1812
1813 return false;
1814 };
1815
1816 return IsLaxCompatible(FirstType, SecondType) ||
1817 IsLaxCompatible(SecondType, FirstType);
1818}
1819
1820static void appendFeature(StringRef Feat, SmallString<64> &Buffer) {
1821 if (!Buffer.empty())
1822 Buffer.append("+");
1823 Buffer.append(Feat);
1824}
1825
1826static void convertPriorityString(unsigned Priority,
1827 SmallString<64> &NewParam) {
1828 StringRef PriorityString[8] = {"P0", "P1", "P2", "P3",
1829 "P4", "P5", "P6", "P7"};
1830
1831 assert(Priority > 0 && Priority < 256 && "priority out of range");
1832 // Convert priority=[1-255] -> P0 + ... + P7
1833 for (unsigned BitPos = 0; BitPos < 8; ++BitPos)
1834 if (Priority & (1U << BitPos))
1835 appendFeature(PriorityString[BitPos], NewParam);
1836}
1837
1838bool SemaARM::checkTargetVersionAttr(const StringRef Param,
1839 const SourceLocation Loc,
1840 SmallString<64> &NewParam) {
1841 using namespace DiagAttrParams;
1842
1843 auto [LHS, RHS] = Param.split(';');
1844 RHS = RHS.trim();
1845 bool IsDefault = false;
1847 LHS.split(Features, '+');
1848 for (StringRef Feat : Features) {
1849 Feat = Feat.trim();
1850 if (Feat == "default")
1851 IsDefault = true;
1852 else if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
1853 return Diag(Loc, diag::warn_unsupported_target_attribute)
1854 << Unsupported << None << Feat << TargetVersion;
1855 appendFeature(Feat, NewParam);
1856 }
1857
1858 if (!RHS.empty() && RHS.consume_front("priority=")) {
1859 if (IsDefault)
1860 Diag(Loc, diag::warn_invalid_default_version_priority);
1861 else {
1862 unsigned Digit;
1863 if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1864 Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1865 else
1866 convertPriorityString(Digit, NewParam);
1867 }
1868 }
1869 return false;
1870}
1871
1874 SmallVectorImpl<SmallString<64>> &NewParams) {
1875 using namespace DiagAttrParams;
1876
1877 if (!getASTContext().getTargetInfo().hasFeature("fmv"))
1878 return true;
1879
1880 assert(Params.size() == Locs.size() &&
1881 "Mismatch between number of string parameters and locations");
1882
1883 bool HasDefault = false;
1884 bool HasNonDefault = false;
1885 for (unsigned I = 0, E = Params.size(); I < E; ++I) {
1886 const StringRef Param = Params[I].trim();
1887 const SourceLocation &Loc = Locs[I];
1888
1889 auto [LHS, RHS] = Param.split(';');
1890 RHS = RHS.trim();
1891 bool HasPriority = !RHS.empty() && RHS.consume_front("priority=");
1892
1893 if (LHS.empty())
1894 return Diag(Loc, diag::warn_unsupported_target_attribute)
1895 << Unsupported << None << "" << TargetClones;
1896
1897 if (LHS == "default") {
1898 if (HasDefault)
1899 Diag(Loc, diag::warn_target_clone_duplicate_options);
1900 else {
1901 if (HasPriority)
1902 Diag(Loc, diag::warn_invalid_default_version_priority);
1903 NewParams.push_back(LHS);
1904 HasDefault = true;
1905 }
1906 continue;
1907 }
1908
1909 bool HasCodeGenImpact = false;
1911 llvm::SmallVector<StringRef, 8> ValidFeatures;
1912 LHS.split(Features, '+');
1913 for (StringRef Feat : Features) {
1914 Feat = Feat.trim();
1915 if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
1916 Diag(Loc, diag::warn_unsupported_target_attribute)
1917 << Unsupported << None << Feat << TargetClones;
1918 continue;
1919 }
1920 if (getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat))
1921 HasCodeGenImpact = true;
1922 ValidFeatures.push_back(Feat);
1923 }
1924
1925 // Ignore features that don't impact code generation.
1926 if (!HasCodeGenImpact) {
1927 Diag(Loc, diag::warn_target_clone_no_impact_options);
1928 continue;
1929 }
1930
1931 if (ValidFeatures.empty())
1932 continue;
1933
1934 // Canonicalize attribute parameter.
1935 llvm::sort(ValidFeatures);
1936 SmallString<64> NewParam(llvm::join(ValidFeatures, "+"));
1937 if (llvm::is_contained(NewParams, NewParam)) {
1938 Diag(Loc, diag::warn_target_clone_duplicate_options);
1939 continue;
1940 }
1941
1942 if (HasPriority) {
1943 unsigned Digit;
1944 if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1945 Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1946 else
1947 convertPriorityString(Digit, NewParam);
1948 }
1949
1950 // Valid non-default argument.
1951 NewParams.push_back(NewParam);
1952 HasNonDefault = true;
1953 }
1954
1955 return !HasNonDefault;
1956}
1957
1959 const FunctionDecl *FD,
1960 const llvm::StringMap<bool> &FeatureMap) {
1961 if (!Ty->isSVESizelessBuiltinType())
1962 return false;
1963
1964 if (FeatureMap.lookup("sve"))
1965 return false;
1966
1967 // No SVE environment available.
1968 if (!FeatureMap.lookup("sme"))
1969 return Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
1970
1971 // SVE environment only available to streaming functions.
1972 if (FD && !FD->getType().isNull() &&
1973 !IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
1974 return Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
1975
1976 return false;
1977}
1978} // namespace clang
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, const TargetInfo &Target)
Determine whether a translation unit built using the current language options has the given feature.
Definition Module.cpp:96
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
This file declares semantic analysis functions specific to ARM.
Enumerates target-specific builtins in their own namespaces within namespace clang.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
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:854
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:971
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
Attr - This represents one attribute.
Definition Attr.h:46
SourceLocation getLoc() const
This class is used for builtin types like 'int'.
Definition TypeBase.h:3245
Kind getKind() const
Definition TypeBase.h:3299
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
Definition Builtins.h:450
const char * getRequiredFeatures(unsigned ID) const
Definition Builtins.cpp:118
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2991
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3195
SourceLocation getBeginLoc() const
Definition Expr.h:3325
void setArg(unsigned Arg, Expr *ArgExpr)
setArg - Set the specified argument.
Definition Expr.h:3208
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3174
Expr * getCallee()
Definition Expr.h:3138
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3182
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1294
SourceLocation getBeginLoc() const
Definition Expr.h:1373
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:583
void addAttr(Attr *A)
const FunctionType * getFunctionType(bool BlocksToo=true) const
Looks through the Decl's underlying type to extract a FunctionType when possible.
SourceLocation getLocation() const
Definition DeclBase.h:449
DeclContext * getDeclContext()
Definition DeclBase.h:458
void dropAttr()
Definition DeclBase.h:566
bool hasAttr() const
Definition DeclBase.h:587
This represents one expression.
Definition Expr.h:113
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3134
void setType(QualType t)
Definition Expr.h:146
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:178
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:195
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3129
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Definition Expr.h:859
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition Expr.h:145
Represents a function declaration or definition.
Definition Decl.h:2059
QualType getReturnType() const
Definition Decl.h:2980
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2905
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5416
static ArmStateValue getArmZT0State(unsigned AttrBits)
Definition TypeBase.h:4921
static ArmStateValue getArmZAState(unsigned AttrBits)
Definition TypeBase.h:4917
One of these records is kept for each identifier that is lexed.
unsigned getBuiltinID() const
Return a value indicating whether this is a builtin function.
IdentifierInfo * getIdentifierInfo() const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition Expr.h:3901
Describes an entity that is being initialized.
static InitializedEntity InitializeParameter(ASTContext &Context, ParmVarDecl *Parm)
Create the initialization entity for a parameter.
@ Integer
Permit vector bitcasts between integer vectors with different numbers of elements but the same total ...
@ All
Permit vector bitcasts between all vectors with the same total bit-width.
Flags to identify the types for overloaded Neon builtins.
unsigned getEltSizeInBits() const
EltType getEltType() const
Represents a parameter to a function.
Definition Decl.h:1820
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
IdentifierLoc * getArgAsIdent(unsigned Arg) const
Definition ParsedAttr.h:389
void setInvalid(bool b=true) const
Definition ParsedAttr.h:345
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition ParsedAttr.h:371
bool isArgIdent(unsigned Arg) const
Definition ParsedAttr.h:385
bool isInvalid() const
Definition ParsedAttr.h:344
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3403
A (possibly-)qualified type.
Definition TypeBase.h:938
QualType withConst() const
Definition TypeBase.h:1175
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1172
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
QualType withVolatile() const
Definition TypeBase.h:1183
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition TypeBase.h:1454
QualType getCanonicalType() const
Definition TypeBase.h:8498
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8540
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8519
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8450
bool isAtLeastAsQualifiedAs(QualType Other, const ASTContext &Ctx) const
Determine whether this type is at least as qualified as the other given type, requiring exact equalit...
Definition TypeBase.h:8611
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition TypeBase.h:362
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition TypeBase.h:355
@ OCL_None
There is no lifetime qualification on this type.
Definition TypeBase.h:351
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition TypeBase.h:365
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition TypeBase.h:368
void CheckSMEFunctionDefAttributes(const FunctionDecl *FD)
Definition SemaARM.cpp:1640
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:1191
void handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL)
Definition SemaARM.cpp:1615
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:782
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE)
Definition SemaARM.cpp:970
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:827
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:856
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:954
bool PerformNeonImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int, int > > &ImmChecks, int OverloadType=-1)
Definition SemaARM.cpp:653
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:945
void handleInterruptAttr(Decl *D, const ParsedAttr &AL)
Definition SemaARM.cpp:1583
bool PerformSVEImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int > > &ImmChecks)
Definition SemaARM.cpp:672
void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL)
Definition SemaARM.cpp:1468
@ ArmStreaming
Intrinsic is only available in normal mode.
Definition SemaARM.h:37
@ 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:1515
bool CheckARMBuiltinExclusiveCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:995
bool areCompatibleSveTypes(QualType FirstType, QualType SecondType)
Return true if the given types are an SVE builtin and a VectorType that is a fixed-length representat...
Definition SemaARM.cpp:1710
bool BuiltinARMAtomicHintCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:326
bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc, SmallString< 64 > &NewParam)
Definition SemaARM.cpp:1838
bool checkSVETypeSupport(QualType Ty, SourceLocation Loc, const FunctionDecl *FD, const llvm::StringMap< bool > &FeatureMap)
Definition SemaARM.cpp:1958
bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition SemaARM.cpp:1454
bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType)
Return true if the given vector types are lax-compatible SVE vector types, false otherwise.
Definition SemaARM.cpp:1755
bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:1273
bool MveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition SemaARM.cpp:1441
bool BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall)
BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions.
Definition SemaARM.cpp:27
void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL)
Definition SemaARM.cpp:1568
bool CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, unsigned ArgIdx, unsigned EltBitWidth, unsigned VecBitWidth)
Definition SemaARM.cpp:511
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:196
bool SmeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition SemaARM.cpp:1461
bool checkTargetClonesAttr(SmallVectorImpl< StringRef > &Params, SmallVectorImpl< SourceLocation > &Locs, SmallVectorImpl< SmallString< 64 > > &NewParams)
Definition SemaARM.cpp:1872
bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition SemaARM.cpp:1449
SemaARM(Sema &S)
Definition SemaARM.cpp:24
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
const LangOptions & getLangOpts() const
Definition SemaBase.cpp:11
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:863
ASTContext & Context
Definition Sema.h:1332
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:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
Exposes information about the current target.
Definition TargetInfo.h:228
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
IntType getInt64Type() const
Definition TargetInfo.h:430
@ ARM_LDREX_D
word (32-bit)
virtual unsigned getARMLDREXMask() const
uint32_t getARMCDECoprocMask() const
For ARM targets returns a mask defining which coprocessors are configured as Custom Datapath.
virtual bool hasFeature(StringRef Feature) const
Determine whether the given target has the given feature.
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isBlockPointerType() const
Definition TypeBase.h:8703
bool isMFloat8Type() const
Definition TypeBase.h:9097
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9116
bool isSVESizelessBuiltinType() const
Returns true for SVE scalable vector types.
Definition Type.cpp:2795
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
Definition Type.cpp:2829
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2282
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
QualType getSveEltType(const ASTContext &Ctx) const
Returns the representative type for the element of an SVE builtin type.
Definition Type.cpp:2868
bool isBitIntType() const
Definition TypeBase.h:8958
bool isFloatingType() const
Definition Type.cpp:2517
bool isAnyPointerType() const
Definition TypeBase.h:8691
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
bool isSizelessVectorType() const
Returns true for all scalable vector types.
Definition Type.cpp:2791
QualType getType() const
Definition Decl.h:724
Represents a GCC generic vector type.
Definition TypeBase.h:4273
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.
Enums for the diagnostics of target, target_version and target_clones.
Definition Sema.h:849
const AstTypeMatcher< PointerType > pointerType
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
static void convertPriorityString(unsigned Priority, SmallString< 64 > &NewParam)
Definition SemaARM.cpp:1826
@ CPlusPlus
static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, ArrayRef< IntrinToName > Map, const char *IntrinNames)
Definition SemaARM.cpp:1422
static ArmSMEState getSMEState(unsigned BuiltinID)
Definition SemaARM.cpp:772
static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, SemaARM::ArmStreamingType BuiltinType, unsigned BuiltinID)
Definition SemaARM.cpp:701
ArmSMEState
Definition SemaARM.cpp:497
@ ArmInOutZA
Definition SemaARM.cpp:502
@ ArmZT0Mask
Definition SemaARM.cpp:508
@ ArmInOutZT0
Definition SemaARM.cpp:507
@ ArmInZA
Definition SemaARM.cpp:500
@ ArmInZT0
Definition SemaARM.cpp:505
@ ArmZAMask
Definition SemaARM.cpp:503
@ ArmOutZA
Definition SemaARM.cpp:501
@ ArmOutZT0
Definition SemaARM.cpp:506
@ ArmNoState
Definition SemaARM.cpp:498
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)
Definition SemaARM.cpp:685
static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty, bool IsStreaming)
getSVETypeSize - Return SVE vector or predicate register size.
Definition SemaARM.cpp:1699
@ AANT_ArgumentIdentifier
@ Result
The result type of a method or function.
Definition TypeBase.h:906
static bool checkFPMScaleIfConstant(Sema &S, CallExpr *Call, unsigned ArgNum, int64_t Low, int64_t High)
Definition SemaARM.cpp:1171
const FunctionProtoType * T
AssignConvertType
AssignConvertType - All of the 'assignment' semantic checks return this enum to indicate whether the ...
Definition Sema.h:683
bool hasArmZT0State(const FunctionDecl *FD)
Returns whether the given FunctionDecl has Arm ZT0 state.
Definition Decl.cpp:6206
CastKind
CastKind - The kind of operation required for a conversion.
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:457
static bool checkNewAttrMutualExclusion(Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT, FunctionType::ArmStateValue CurrentState, StringRef StateName)
Definition SemaARM.cpp:1492
static void appendFeature(StringRef Feat, SmallString< 64 > &Buffer)
Definition SemaARM.cpp:1820
@ SveFixedLengthData
is AArch64 SVE fixed-length data vector
Definition TypeBase.h:4252
@ Generic
not a target-specific vector type
Definition TypeBase.h:4234
@ SveFixedLengthPredicate
is AArch64 SVE fixed-length predicate vector
Definition TypeBase.h:4255
U cast(CodeGen::Address addr)
Definition Address.h:327
bool IsArmStreamingFunction(const FunctionDecl *FD, bool IncludeLocallyStreaming)
Returns whether the given FunctionDecl has an __arm[_locally]_streaming attribute.
Definition Decl.cpp:6185
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
bool hasArmZAState(const FunctionDecl *FD)
Returns whether the given FunctionDecl has Arm ZA state.
Definition Decl.cpp:6199
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t
Extra information about a function prototype.
Definition TypeBase.h:5501