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
327 CallExpr *TheCall) {
328 if (SemaRef.checkArgCount(TheCall, 4))
329 return true;
330
331 // Arg 0 should be the pointer type. The pointee type must be a
332 // scalar integral or floating-point type of 8, 16, 32 or 64 bits.
333 ASTContext &Context = getASTContext();
334 auto PtrArgRes =
335 SemaRef.DefaultFunctionArrayLvalueConversion(TheCall->getArg(0));
336 if (PtrArgRes.isInvalid())
337 return true;
338 auto *PtrArg = PtrArgRes.get();
339 auto *PtrTy = PtrArg->getType()->getAs<PointerType>();
340 if (!PtrTy)
341 return Diag(TheCall->getBeginLoc(),
342 diag::err_atomic_hint_builtin_must_be_pointer)
343 << PtrArg->getType() << 0 << PtrArg->getSourceRange();
344 TheCall->setArg(0, PtrArg);
345
346 QualType PtrQT = Context.getCanonicalType(PtrTy->getPointeeType());
347 if (PtrQT.isConstQualified())
348 return Diag(TheCall->getBeginLoc(),
349 diag::err_atomic_op_needs_non_const_pointer)
350 << PtrQT << PtrArg->getSourceRange();
351
352 PtrQT = PtrQT.getUnqualifiedType();
353 if (!PtrQT->isIntegralType(Context) && !PtrQT->isFloatingType() &&
354 !PtrQT->isMFloat8Type())
355 return Diag(TheCall->getBeginLoc(),
356 diag::err_atomic_op_needs_atomic_int_or_fp)
357 << 0 << PtrQT << PtrArg->getSourceRange();
358
359 if (PtrQT->isBitIntType())
360 return Diag(TheCall->getBeginLoc(),
361 diag::err_atomic_builtin_bit_int_prohibit)
362 << PtrQT << PtrArg->getSourceRange();
363
364 unsigned TySize = Context.getTypeSize(PtrQT);
365 if (TySize != 8 && TySize != 16 && TySize != 32 && TySize != 64)
366 return Diag(TheCall->getBeginLoc(), diag::err_atomic_op_hint_data_size)
367 << PtrArg->getSourceRange();
368
369 // Arg 1 is the data to be stored. The type must match the pointee
370 // type found above.
371 auto DataArgRes =
372 SemaRef.DefaultFunctionArrayLvalueConversion(TheCall->getArg(1));
373 if (DataArgRes.isInvalid())
374 return true;
375 auto *DataArg = DataArgRes.get();
376 QualType DataQT =
377 Context.getCanonicalType(DataArg->getType()).getUnqualifiedType();
378 TheCall->setArg(1, DataArg);
379
380 if (PtrQT != DataQT)
381 return Diag(TheCall->getBeginLoc(),
382 diag::err_typecheck_call_different_arg_types)
383 << PtrQT << DataQT;
384
385 // Arg 2 is the memory order, which must be relaxed, release or seq_cst
386 auto MemOrdArg =
387 SemaRef.DefaultFunctionArrayLvalueConversion(TheCall->getArg(2));
388 if (MemOrdArg.isInvalid())
389 return true;
390 auto *MemOrd = MemOrdArg.get();
391 if (SemaRef.convertArgumentToType(MemOrd, Context.IntTy))
392 return true;
393 TheCall->setArg(2, MemOrd);
394
395 if (!MemOrd->isValueDependent()) {
396 std::optional<llvm::APSInt> MemOrdAP =
397 MemOrd->getIntegerConstantExpr(Context);
398 if (!MemOrdAP)
399 return Diag(TheCall->getBeginLoc(),
400 diag::err_atomic_hint_has_invalid_memory_order)
401 << MemOrd->getType() << MemOrd->getSourceRange();
402
403 unsigned Ordering = MemOrdAP->getZExtValue();
404 if (!llvm::isValidAtomicOrderingCABI(Ordering))
405 return Diag(TheCall->getBeginLoc(),
406 diag::err_atomic_hint_has_invalid_memory_order)
407 << *MemOrdAP << MemOrd->getSourceRange();
408
409 auto AtomicOrdering = static_cast<llvm::AtomicOrderingCABI>(Ordering);
410 if (AtomicOrdering != llvm::AtomicOrderingCABI::relaxed &&
411 AtomicOrdering != llvm::AtomicOrderingCABI::release &&
412 AtomicOrdering != llvm::AtomicOrderingCABI::seq_cst)
413 return Diag(TheCall->getBeginLoc(),
414 diag::err_atomic_hint_has_invalid_memory_order)
415 << *MemOrdAP << MemOrd->getSourceRange();
416 }
417
418 // Arg 3 is the hint type. Only values represented by AArch64MemoryHint
419 // are valid.
420 auto HintArg =
421 SemaRef.DefaultFunctionArrayLvalueConversion(TheCall->getArg(3));
422 if (HintArg.isInvalid())
423 return true;
424 auto Hint = HintArg.get();
425 if (SemaRef.convertArgumentToType(Hint, Context.IntTy))
426 return true;
427 TheCall->setArg(3, Hint);
428
429 if (!Hint->isValueDependent()) {
430 std::optional<llvm::APSInt> HintAP = Hint->getIntegerConstantExpr(Context);
431 if (!HintAP)
432 return Diag(TheCall->getBeginLoc(),
433 diag::err_atomic_hint_has_invalid_hint_type)
434 << Hint->getType() << Hint->getSourceRange();
435
436 if (llvm::toAArch64MemoryHint(HintAP->getZExtValue()) ==
437 llvm::AArch64MemoryHint::NONE) {
438 Diag(TheCall->getBeginLoc(), diag::warn_atomic_hint_has_invalid_hint_type)
439 << *HintAP << Hint->getSourceRange();
440 return false;
441 }
442 }
443 return false;
444}
445
446/// getNeonEltType - Return the QualType corresponding to the elements of
447/// the vector type specified by the NeonTypeFlags. This is used to check
448/// the pointer arguments for Neon load/store intrinsics.
450 bool IsPolyUnsigned, bool IsInt64Long) {
451 switch (Flags.getEltType()) {
453 return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
455 return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
457 return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
459 if (IsInt64Long)
460 return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
461 else
462 return Flags.isUnsigned() ? Context.UnsignedLongLongTy
463 : Context.LongLongTy;
465 return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
467 return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
469 if (IsInt64Long)
470 return Context.UnsignedLongTy;
471 else
472 return Context.UnsignedLongLongTy;
474 break;
476 return Context.HalfTy;
478 return Context.FloatTy;
480 return Context.DoubleTy;
482 return Context.BFloat16Ty;
484 return Context.MFloat8Ty;
485 }
486 llvm_unreachable("Invalid NeonTypeFlag!");
487}
488
489enum ArmSMEState : unsigned {
491
492 ArmInZA = 0b01,
493 ArmOutZA = 0b10,
495 ArmZAMask = 0b11,
496
497 ArmInZT0 = 0b01 << 2,
498 ArmOutZT0 = 0b10 << 2,
499 ArmInOutZT0 = 0b11 << 2,
500 ArmZT0Mask = 0b11 << 2
501};
502
503bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy,
504 unsigned ArgIdx, unsigned EltBitWidth,
505 unsigned ContainerBitWidth) {
506 // Function that checks whether the operand (ArgIdx) is an immediate
507 // that is one of a given set of values.
508 auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set,
509 int ErrDiag) -> bool {
510 // We can't check the value of a dependent argument.
511 Expr *Arg = TheCall->getArg(ArgIdx);
512 if (Arg->isTypeDependent() || Arg->isValueDependent())
513 return false;
514
515 // Check constant-ness first.
516 llvm::APSInt Imm;
517 if (SemaRef.BuiltinConstantArg(TheCall, ArgIdx, Imm))
518 return true;
519
520 if (!llvm::is_contained(Set, Imm.getSExtValue()))
521 return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
522 return false;
523 };
524
525 switch ((ImmCheckType)CheckTy) {
526 case ImmCheckType::ImmCheck0_31:
527 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 31))
528 return true;
529 break;
530 case ImmCheckType::ImmCheck0_13:
531 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 13))
532 return true;
533 break;
534 case ImmCheckType::ImmCheck0_63:
535 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63))
536 return true;
537 break;
538 case ImmCheckType::ImmCheck1_16:
539 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16))
540 return true;
541 break;
542 case ImmCheckType::ImmCheck0_7:
543 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7))
544 return true;
545 break;
546 case ImmCheckType::ImmCheck1_1:
547 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 1))
548 return true;
549 break;
550 case ImmCheckType::ImmCheck1_3:
551 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 3))
552 return true;
553 break;
554 case ImmCheckType::ImmCheck1_7:
555 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 7))
556 return true;
557 break;
558 case ImmCheckType::ImmCheckExtract:
559 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
560 (2048 / EltBitWidth) - 1))
561 return true;
562 break;
563 case ImmCheckType::ImmCheckCvt:
564 case ImmCheckType::ImmCheckShiftRight:
565 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth))
566 return true;
567 break;
568 case ImmCheckType::ImmCheckShiftRightNarrow:
569 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth / 2))
570 return true;
571 break;
572 case ImmCheckType::ImmCheckShiftLeft:
573 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1))
574 return true;
575 break;
576 case ImmCheckType::ImmCheckShiftLeftLong:
577 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, (EltBitWidth / 2)))
578 return true;
579 break;
580 case ImmCheckType::ImmCheckLaneIndex:
581 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
582 (ContainerBitWidth / EltBitWidth) - 1))
583 return true;
584 break;
585 case ImmCheckType::ImmCheckLaneIndexCompRotate:
586 if (SemaRef.BuiltinConstantArgRange(
587 TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1))
588 return true;
589 break;
590 case ImmCheckType::ImmCheckLaneIndexDot:
591 if (SemaRef.BuiltinConstantArgRange(
592 TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1))
593 return true;
594 break;
595 case ImmCheckType::ImmCheckComplexRot90_270:
596 if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd))
597 return true;
598 break;
599 case ImmCheckType::ImmCheckComplexRotAll90:
600 if (CheckImmediateInSet({0, 90, 180, 270},
601 diag::err_rotation_argument_to_cmla))
602 return true;
603 break;
604 case ImmCheckType::ImmCheck0_1:
605 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 1))
606 return true;
607 break;
608 case ImmCheckType::ImmCheck0_2:
609 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 2))
610 return true;
611 break;
612 case ImmCheckType::ImmCheck0_3:
613 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3))
614 return true;
615 break;
616 case ImmCheckType::ImmCheck0_0:
617 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 0))
618 return true;
619 break;
620 case ImmCheckType::ImmCheck0_15:
621 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 15))
622 return true;
623 break;
624 case ImmCheckType::ImmCheck0_255:
625 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 255))
626 return true;
627 break;
628 case ImmCheckType::ImmCheck1_32:
629 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32))
630 return true;
631 break;
632 case ImmCheckType::ImmCheck1_64:
633 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64))
634 return true;
635 break;
636 case ImmCheckType::ImmCheck2_4_Mul2:
637 if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 2, 4) ||
638 SemaRef.BuiltinConstantArgMultiple(TheCall, ArgIdx, 2))
639 return true;
640 break;
641 }
642 return false;
643}
644
646 CallExpr *TheCall,
647 SmallVectorImpl<std::tuple<int, int, int, int>> &ImmChecks,
648 int OverloadType) {
649 bool HasError = false;
650
651 for (const auto &I : ImmChecks) {
652 auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I;
653
654 if (OverloadType >= 0)
655 ElementBitWidth = NeonTypeFlags(OverloadType).getEltSizeInBits();
656
657 HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth,
658 VecBitWidth);
659 }
660
661 return HasError;
662}
663
665 CallExpr *TheCall, SmallVectorImpl<std::tuple<int, int, int>> &ImmChecks) {
666 bool HasError = false;
667
668 for (const auto &I : ImmChecks) {
669 auto [ArgIdx, CheckTy, ElementBitWidth] = I;
670 HasError |=
671 CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 128);
672 }
673
674 return HasError;
675}
676
678 if (FD->hasAttr<ArmLocallyStreamingAttr>())
680 if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
681 if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
682 if (FPT->getAArch64SMEAttributes() &
685 if (FPT->getAArch64SMEAttributes() &
688 }
689 }
691}
692
693static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
694 const FunctionDecl *FD,
696 unsigned BuiltinID) {
698
699 // Check if the intrinsic is available in the right mode, i.e.
700 // * When compiling for SME only, the caller must be in streaming mode.
701 // * When compiling for SVE only, the caller must be in non-streaming mode.
702 // * When compiling for both SVE and SME, the caller can be in either mode.
704 llvm::StringMap<bool> CallerFeatures;
705 S.Context.getFunctionFeatureMap(CallerFeatures, FD);
706
707 // Avoid emitting diagnostics for a function that can never compile.
708 if (FnType == SemaARM::ArmStreaming && !CallerFeatures["sme"])
709 return false;
710
711 const auto FindTopLevelPipe = [](const char *S) {
712 unsigned Depth = 0;
713 unsigned I = 0, E = strlen(S);
714 for (; I < E; ++I) {
715 if (S[I] == '|' && Depth == 0)
716 break;
717 if (S[I] == '(')
718 ++Depth;
719 else if (S[I] == ')')
720 --Depth;
721 }
722 return I;
723 };
724
725 const char *RequiredFeatures =
727 unsigned PipeIdx = FindTopLevelPipe(RequiredFeatures);
728 assert(PipeIdx != 0 && PipeIdx != strlen(RequiredFeatures) &&
729 "Expected feature string of the form 'SVE-EXPR|SME-EXPR'");
730 StringRef NonStreamingBuiltinGuard = StringRef(RequiredFeatures, PipeIdx);
731 StringRef StreamingBuiltinGuard = StringRef(RequiredFeatures + PipeIdx + 1);
732
733 bool SatisfiesSVE = Builtin::evaluateRequiredTargetFeatures(
734 NonStreamingBuiltinGuard, CallerFeatures);
735 bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures(
736 StreamingBuiltinGuard, CallerFeatures);
737
738 if (SatisfiesSVE && SatisfiesSME)
739 // Function type is irrelevant for streaming-agnostic builtins.
740 return false;
741 else if (SatisfiesSVE)
743 else if (SatisfiesSME)
745 else
746 // This should be diagnosed by CodeGen
747 return false;
748 }
749
750 if (FnType != SemaARM::ArmNonStreaming &&
752 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
753 << TheCall->getSourceRange() << "non-streaming";
754 else if (FnType != SemaARM::ArmStreaming &&
756 S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
757 << TheCall->getSourceRange() << "streaming";
758 else
759 return false;
760
761 return true;
762}
763
764static ArmSMEState getSMEState(unsigned BuiltinID) {
765 switch (BuiltinID) {
766 default:
767 return ArmNoState;
768#define GET_SME_BUILTIN_GET_STATE
769#include "clang/Basic/arm_sme_builtins_za_state.inc"
770#undef GET_SME_BUILTIN_GET_STATE
771 }
772}
773
775 CallExpr *TheCall) {
776 if (const FunctionDecl *FD =
777 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
778 std::optional<ArmStreamingType> BuiltinType;
779
780 switch (BuiltinID) {
781#define GET_SME_STREAMING_ATTRS
782#include "clang/Basic/arm_sme_streaming_attrs.inc"
783#undef GET_SME_STREAMING_ATTRS
784 }
785
786 if (BuiltinType &&
787 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
788 return true;
789
790 if ((getSMEState(BuiltinID) & ArmZAMask) && !hasArmZAState(FD)) {
791 Diag(TheCall->getBeginLoc(),
792 diag::err_attribute_arm_za_builtin_no_za_state)
793 << TheCall->getSourceRange();
794 return true;
795 }
796
797 if ((getSMEState(BuiltinID) & ArmZT0Mask) && !hasArmZT0State(FD)) {
798 Diag(TheCall->getBeginLoc(),
799 diag::err_attribute_arm_zt0_builtin_no_zt0_state)
800 << TheCall->getSourceRange();
801 return true;
802 }
803 }
804
805 // Range check SME intrinsics that take immediate values.
807
808 switch (BuiltinID) {
809 default:
810 return false;
811#define GET_SME_IMMEDIATE_CHECK
812#include "clang/Basic/arm_sme_sema_rangechecks.inc"
813#undef GET_SME_IMMEDIATE_CHECK
814 }
815
816 return PerformSVEImmChecks(TheCall, ImmChecks);
817}
818
820 CallExpr *TheCall) {
821 if (const FunctionDecl *FD =
822 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
823 std::optional<ArmStreamingType> BuiltinType;
824
825 switch (BuiltinID) {
826#define GET_SVE_STREAMING_ATTRS
827#include "clang/Basic/arm_sve_streaming_attrs.inc"
828#undef GET_SVE_STREAMING_ATTRS
829 }
830 if (BuiltinType &&
831 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
832 return true;
833 }
834 // Range check SVE intrinsics that take immediate values.
836
837 switch (BuiltinID) {
838 default:
839 return false;
840#define GET_SVE_IMMEDIATE_CHECK
841#include "clang/Basic/arm_sve_sema_rangechecks.inc"
842#undef GET_SVE_IMMEDIATE_CHECK
843 }
844
845 return PerformSVEImmChecks(TheCall, ImmChecks);
846}
847
849 unsigned BuiltinID,
850 CallExpr *TheCall) {
851 if (const FunctionDecl *FD =
852 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
853 std::optional<ArmStreamingType> BuiltinType;
854
855 switch (BuiltinID) {
856 default:
857 break;
858#define GET_NEON_STREAMING_COMPAT_FLAG
859#include "clang/Basic/arm_neon.inc"
860#undef GET_NEON_STREAMING_COMPAT_FLAG
861 }
862 if (BuiltinType &&
863 checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
864 return true;
865 }
866
867 llvm::APSInt Result;
868 uint64_t mask = 0;
869 int TV = -1;
870 int PtrArgNum = -1;
871 bool HasConstPtr = false;
872 switch (BuiltinID) {
873#define GET_NEON_OVERLOAD_CHECK
874#include "clang/Basic/arm_fp16.inc"
875#include "clang/Basic/arm_neon.inc"
876#undef GET_NEON_OVERLOAD_CHECK
877 }
878
879 // For NEON intrinsics which are overloaded on vector element type, validate
880 // the immediate which specifies which variant to emit.
881 if (mask) {
882 unsigned ImmArg = TheCall->getNumArgs() - 1;
883 if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result))
884 return true;
885
886 // FIXME: This is effectively dead code. Change the logic above so that the
887 // following check is actually run.
888 TV = Result.getLimitedValue(64);
889 if ((TV > 63) || (mask & (1ULL << TV)) == 0)
890 return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
891 << TheCall->getArg(ImmArg)->getSourceRange();
892 }
893
894 if (PtrArgNum >= 0) {
895 // Check that pointer arguments have the specified type.
896 Expr *Arg = TheCall->getArg(PtrArgNum);
897 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
898 Arg = ICE->getSubExpr();
899 ExprResult RHS = SemaRef.DefaultFunctionArrayLvalueConversion(Arg);
900 QualType RHSTy = RHS.get()->getType();
901
902 llvm::Triple::ArchType Arch = TI.getTriple().getArch();
903 bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
904 Arch == llvm::Triple::aarch64_32 ||
905 Arch == llvm::Triple::aarch64_be;
906 bool IsInt64Long = TI.getInt64Type() == TargetInfo::SignedLong;
908 IsPolyUnsigned, IsInt64Long);
909 if (HasConstPtr)
910 EltTy = EltTy.withConst();
911 QualType LHSTy = getASTContext().getPointerType(EltTy);
912 AssignConvertType ConvTy;
913 ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);
914 if (RHS.isInvalid())
915 return true;
916 if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy,
917 RHSTy, RHS.get(),
919 return true;
920 }
921
922 // For NEON intrinsics which take an immediate value as part of the
923 // instruction, range check them here.
925 switch (BuiltinID) {
926 default:
927 return false;
928#define GET_NEON_IMMEDIATE_CHECK
929#include "clang/Basic/arm_fp16.inc"
930#include "clang/Basic/arm_neon.inc"
931#undef GET_NEON_IMMEDIATE_CHECK
932 }
933
934 return PerformNeonImmChecks(TheCall, ImmChecks, TV);
935}
936
938 CallExpr *TheCall) {
939 switch (BuiltinID) {
940 default:
941 return false;
942#include "clang/Basic/arm_mve_builtin_sema.inc"
943 }
944}
945
947 unsigned BuiltinID,
948 CallExpr *TheCall) {
949 bool Err = false;
950 switch (BuiltinID) {
951 default:
952 return false;
953#include "clang/Basic/arm_cde_builtin_sema.inc"
954 }
955
956 if (Err)
957 return true;
958
959 return CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), /*WantCDE*/ true);
960}
961
963 const Expr *CoprocArg,
964 bool WantCDE) {
965 ASTContext &Context = getASTContext();
966 if (SemaRef.isConstantEvaluatedContext())
967 return false;
968
969 // We can't check the value of a dependent argument.
970 if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
971 return false;
972
973 llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context);
974 int64_t CoprocNo = CoprocNoAP.getExtValue();
975 assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");
976
977 uint32_t CDECoprocMask = TI.getARMCDECoprocMask();
978 bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));
979
980 if (IsCDECoproc != WantCDE)
981 return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
982 << (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange();
983
984 return false;
985}
986
988 unsigned BuiltinID,
989 CallExpr *TheCall) {
990 assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
991 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
992 BuiltinID == ARM::BI__builtin_arm_ldaex ||
993 BuiltinID == ARM::BI__builtin_arm_strex ||
994 BuiltinID == ARM::BI__builtin_arm_strexd ||
995 BuiltinID == ARM::BI__builtin_arm_stlex ||
996 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
997 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
998 BuiltinID == AArch64::BI__builtin_arm_strex ||
999 BuiltinID == AArch64::BI__builtin_arm_stlex) &&
1000 "unexpected ARM builtin");
1001 bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
1002 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
1003 BuiltinID == ARM::BI__builtin_arm_ldaex ||
1004 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1005 BuiltinID == AArch64::BI__builtin_arm_ldaex;
1006 bool IsDoubleWord = BuiltinID == ARM::BI__builtin_arm_ldrexd ||
1007 BuiltinID == ARM::BI__builtin_arm_strexd;
1008
1009 ASTContext &Context = getASTContext();
1010 DeclRefExpr *DRE =
1012
1013 // Ensure that we have the proper number of arguments.
1014 if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))
1015 return true;
1016
1017 // Inspect the pointer argument of the atomic builtin. This should always be
1018 // a pointer type, whose element is an integral scalar or pointer type.
1019 // Because it is a pointer type, we don't have to worry about any implicit
1020 // casts here.
1021 Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
1022 ExprResult PointerArgRes =
1023 SemaRef.DefaultFunctionArrayLvalueConversion(PointerArg);
1024 if (PointerArgRes.isInvalid())
1025 return true;
1026 PointerArg = PointerArgRes.get();
1027
1028 const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
1029 if (!pointerType) {
1030 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
1031 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
1032 return true;
1033 }
1034
1035 // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next
1036 // task is to insert the appropriate casts into the AST. First work out just
1037 // what the appropriate type is.
1038 QualType ValType = pointerType->getPointeeType();
1039 QualType AddrType = ValType.getUnqualifiedType().withVolatile();
1040 if (IsLdrex)
1041 AddrType.addConst();
1042
1043 // Issue a warning if the cast is dodgy.
1044 CastKind CastNeeded = CK_NoOp;
1045 if (!AddrType.isAtLeastAsQualifiedAs(ValType, getASTContext())) {
1046 CastNeeded = CK_BitCast;
1047 Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
1048 << PointerArg->getType() << Context.getPointerType(AddrType)
1049 << AssignmentAction::Passing << PointerArg->getSourceRange();
1050 }
1051
1052 // Finally, do the cast and replace the argument with the corrected version.
1053 AddrType = Context.getPointerType(AddrType);
1054 PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);
1055 if (PointerArgRes.isInvalid())
1056 return true;
1057 PointerArg = PointerArgRes.get();
1058
1059 TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);
1060
1061 // In general, we allow ints, floats and pointers to be loaded and stored.
1062 if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
1063 !ValType->isBlockPointerType() && !ValType->isFloatingType()) {
1064 Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
1065 << PointerArg->getType() << 0 << PointerArg->getSourceRange();
1066 return true;
1067 }
1068
1069 // Check whether the size of the type can be handled atomically on this
1070 // target.
1071 if (!TI.getTriple().isAArch64()) {
1072 unsigned Mask = TI.getARMLDREXMask();
1073 unsigned Bits = Context.getTypeSize(ValType);
1074 if (IsDoubleWord) {
1075 // Explicit request for ldrexd/strexd means only double word sizes
1076 // supported if the target supports them.
1078 }
1079 bool Supported =
1080 (llvm::isPowerOf2_64(Bits)) && Bits >= 8 && (Mask & (Bits / 8));
1081
1082 if (!Supported) {
1083 // Emit a diagnostic saying that this size isn't available. If _no_ size
1084 // of exclusive access is supported on this target, we emit a diagnostic
1085 // with special wording for that case, but otherwise, we emit
1086 // err_atomic_exclusive_builtin_pointer_size and loop over `Mask` to
1087 // control what subset of sizes it lists as legal.
1088 if (Mask) {
1089 auto D = Diag(DRE->getBeginLoc(),
1090 diag::err_atomic_exclusive_builtin_pointer_size)
1091 << PointerArg->getType();
1092 bool Started = false;
1093 for (unsigned Size = 1; Size <= 8; Size <<= 1) {
1094 // For each of the sizes 1,2,4,8, pass two integers into the
1095 // diagnostic. The first selects a separator from the previous
1096 // number: 0 for no separator at all, 1 for a comma, 2 for " or "
1097 // which appears before the final number in a list of more than one.
1098 // The second integer just indicates whether we print this size in
1099 // the message at all.
1100 if (!(Mask & Size)) {
1101 // This size isn't one of the supported ones, so emit no separator
1102 // text and don't print the size itself.
1103 D << 0 << 0;
1104 } else {
1105 // This size is supported, so print it, and an appropriate
1106 // separator.
1107 Mask &= ~Size;
1108 if (!Started)
1109 D << 0; // No separator if this is the first size we've printed
1110 else if (Mask)
1111 D << 1; // "," if there's still another size to come
1112 else
1113 D << 2; // " or " if the size we're about to print is the last
1114 D << 1; // print the size itself
1115 Started = true;
1116 }
1117 }
1118 } else {
1119 bool EmitDoubleWordDiagnostic =
1120 IsDoubleWord && !Mask && TI.getARMLDREXMask();
1121 Diag(DRE->getBeginLoc(),
1122 diag::err_atomic_exclusive_builtin_pointer_size_none)
1123 << (EmitDoubleWordDiagnostic ? 1 : 0)
1124 << PointerArg->getSourceRange();
1125 }
1126 }
1127 }
1128
1129 switch (ValType.getObjCLifetime()) {
1132 // okay
1133 break;
1134
1138 Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
1139 << ValType << PointerArg->getSourceRange();
1140 return true;
1141 }
1142
1143 if (IsLdrex) {
1144 TheCall->setType(ValType);
1145 return false;
1146 }
1147
1148 // Initialize the argument to be stored.
1149 ExprResult ValArg = TheCall->getArg(0);
1151 Context, ValType, /*consume*/ false);
1152 ValArg = SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg);
1153 if (ValArg.isInvalid())
1154 return true;
1155 TheCall->setArg(0, ValArg.get());
1156
1157 // __builtin_arm_strex always returns an int. It's marked as such in the .def,
1158 // but the custom checker bypasses all default analysis.
1159 TheCall->setType(Context.IntTy);
1160 return false;
1161}
1162
1163static bool checkFPMScaleIfConstant(Sema &S, CallExpr *Call, unsigned ArgNum,
1164 int64_t Low, int64_t High) {
1165 Expr *Arg = Call->getArg(ArgNum);
1166
1167 if (Arg->isTypeDependent() || Arg->isValueDependent())
1168 return false;
1169
1170 std::optional<llvm::APSInt> Value = Arg->getIntegerConstantExpr(S.Context);
1171
1172 // Runtime value: accept it.
1173 if (!Value)
1174 return false;
1175
1176 if (*Value < Low || *Value > High)
1177 return S.Diag(Call->getBeginLoc(), diag::warn_argument_invalid_range)
1178 << toString(*Value, 10) << Low << High << Arg->getSourceRange();
1179
1180 return false;
1181}
1182
1184 unsigned BuiltinID,
1185 CallExpr *TheCall) {
1186 if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
1187 BuiltinID == ARM::BI__builtin_arm_ldrexd ||
1188 BuiltinID == ARM::BI__builtin_arm_ldaex ||
1189 BuiltinID == ARM::BI__builtin_arm_strex ||
1190 BuiltinID == ARM::BI__builtin_arm_strexd ||
1191 BuiltinID == ARM::BI__builtin_arm_stlex) {
1192 return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
1193 }
1194
1195 if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
1196 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1197 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
1198 }
1199
1200 if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
1201 BuiltinID == ARM::BI__builtin_arm_wsr64)
1202 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);
1203
1204 if (BuiltinID == ARM::BI__builtin_arm_rsr ||
1205 BuiltinID == ARM::BI__builtin_arm_rsrp ||
1206 BuiltinID == ARM::BI__builtin_arm_wsr ||
1207 BuiltinID == ARM::BI__builtin_arm_wsrp)
1208 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1209
1210 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1211 return true;
1212 if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall))
1213 return true;
1214 if (CheckCDEBuiltinFunctionCall(TI, BuiltinID, TheCall))
1215 return true;
1216 // For intrinsics which take an immediate value as part of the instruction,
1217 // range check them here.
1218 // FIXME: VFP Intrinsics should error if VFP not present.
1219 switch (BuiltinID) {
1220 default:
1221 return false;
1222 case ARM::BI__builtin_arm_ssat:
1223 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);
1224 case ARM::BI__builtin_arm_usat:
1225 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1226 case ARM::BI__builtin_arm_ssat16:
1227 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
1228 case ARM::BI__builtin_arm_usat16:
1229 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
1230 case ARM::BI__builtin_arm_vcvtr_f:
1231 case ARM::BI__builtin_arm_vcvtr_d:
1232 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
1233 case ARM::BI__builtin_arm_dmb:
1234 case ARM::BI__dmb:
1235 case ARM::BI__builtin_arm_dsb:
1236 case ARM::BI__dsb:
1237 case ARM::BI__builtin_arm_isb:
1238 case ARM::BI__isb:
1239 case ARM::BI__builtin_arm_dbg:
1240 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
1241 case ARM::BI__builtin_arm_cdp:
1242 case ARM::BI__builtin_arm_cdp2:
1243 case ARM::BI__builtin_arm_mcr:
1244 case ARM::BI__builtin_arm_mcr2:
1245 case ARM::BI__builtin_arm_mrc:
1246 case ARM::BI__builtin_arm_mrc2:
1247 case ARM::BI__builtin_arm_mcrr:
1248 case ARM::BI__builtin_arm_mcrr2:
1249 case ARM::BI__builtin_arm_mrrc:
1250 case ARM::BI__builtin_arm_mrrc2:
1251 case ARM::BI__builtin_arm_ldc:
1252 case ARM::BI__builtin_arm_ldcl:
1253 case ARM::BI__builtin_arm_ldc2:
1254 case ARM::BI__builtin_arm_ldc2l:
1255 case ARM::BI__builtin_arm_stc:
1256 case ARM::BI__builtin_arm_stcl:
1257 case ARM::BI__builtin_arm_stc2:
1258 case ARM::BI__builtin_arm_stc2l:
1259 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
1260 CheckARMCoprocessorImmediate(TI, TheCall->getArg(0),
1261 /*WantCDE*/ false);
1262 }
1263}
1264
1266 unsigned BuiltinID,
1267 CallExpr *TheCall) {
1268 if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
1269 BuiltinID == AArch64::BI__builtin_arm_ldaex ||
1270 BuiltinID == AArch64::BI__builtin_arm_strex ||
1271 BuiltinID == AArch64::BI__builtin_arm_stlex) {
1272 return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
1273 }
1274
1275 if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
1276 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1277 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
1278 SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
1279 SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);
1280 }
1281
1282 if (BuiltinID == AArch64::BI__builtin_arm_range_prefetch_x) {
1283 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1284 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1) ||
1285 SemaRef.BuiltinConstantArgRange(TheCall, 3, -2097152, 2097151) ||
1286 SemaRef.BuiltinConstantArgRange(TheCall, 4, 1, 65536) ||
1287 SemaRef.BuiltinConstantArgRange(TheCall, 5, -2097152, 2097151);
1288 }
1289
1290 if (BuiltinID == AArch64::BI__builtin_arm_range_prefetch) {
1291 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
1292 SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
1293 }
1294
1295 if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
1296 BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
1297 BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
1298 BuiltinID == AArch64::BI__builtin_arm_wsr128)
1299 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1300
1301 // Memory Tagging Extensions (MTE) Intrinsics
1302 if (BuiltinID == AArch64::BI__builtin_arm_irg ||
1303 BuiltinID == AArch64::BI__builtin_arm_addg ||
1304 BuiltinID == AArch64::BI__builtin_arm_gmi ||
1305 BuiltinID == AArch64::BI__builtin_arm_ldg ||
1306 BuiltinID == AArch64::BI__builtin_arm_stg ||
1307 BuiltinID == AArch64::BI__builtin_arm_subp) {
1308 return BuiltinARMMemoryTaggingCall(BuiltinID, TheCall);
1309 }
1310
1311 if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
1312 BuiltinID == AArch64::BI__builtin_arm_rsrp ||
1313 BuiltinID == AArch64::BI__builtin_arm_wsr ||
1314 BuiltinID == AArch64::BI__builtin_arm_wsrp)
1315 return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);
1316
1317 if (BuiltinID == AArch64::BI__builtin_arm_atomic_store_with_hint)
1318 return BuiltinARMAtomicStoreHintCall(BuiltinID, TheCall);
1319
1320 // Only check the valid encoding range. Any constant in this range would be
1321 // converted to a register of the form S2_2_C3_C4_5. Let the hardware throw
1322 // an exception for incorrect registers. This matches MSVC behavior.
1323 // Bit 14 is o0, i.e. op0 - 2, so op0 == 2 registers have it clear and encode
1324 // below 0x4000.
1325 if (BuiltinID == AArch64::BI_ReadStatusReg ||
1326 BuiltinID == AArch64::BI_WriteStatusReg)
1327 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
1328
1329 if (BuiltinID == AArch64::BI__sys)
1330 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x3fff);
1331
1332 if (BuiltinID == AArch64::BI__getReg || BuiltinID == AArch64::BI__setReg ||
1333 BuiltinID == AArch64::BI__getRegFp || BuiltinID == AArch64::BI__setRegFp)
1334 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);
1335
1336 if (BuiltinID == AArch64::BI__prefetch2)
1337 return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
1338
1339 if (BuiltinID == AArch64::BI__break)
1340 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1341
1342 if (BuiltinID == AArch64::BI__hlt)
1343 return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);
1344
1345 if (BuiltinID == AArch64::BI__hvc || BuiltinID == AArch64::BI__svc) {
1346 // The immediate is the instruction number; the remaining arguments (at most
1347 // four) are passed in X0-X3, so the call takes at most five arguments.
1348 if (SemaRef.checkArgCountAtMost(TheCall, 5) ||
1349 SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff))
1350 return true;
1351 const FunctionDecl *FD = TheCall->getDirectCallee();
1352 for (unsigned I = 1, N = TheCall->getNumArgs(); I < N; ++I) {
1353 const Expr *Arg = TheCall->getArg(I);
1354 QualType Ty = Arg->getType();
1355 if (!Ty->isIntegerType() && !Ty->isAnyPointerType() &&
1356 !Ty->isBlockPointerType() && !Ty->isFloatingType())
1357 return Diag(Arg->getBeginLoc(),
1358 diag::err_aarch64_svc_hvc_invalid_arg_type)
1359 << I + 1 << FD << Ty << Arg->getSourceRange();
1360 }
1361 return false;
1362 }
1363
1364 if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
1365 return true;
1366
1367 if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall))
1368 return true;
1369
1370 if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall))
1371 return true;
1372
1373 if (BuiltinID == AArch64::BI__arm_set_fpm_lscale)
1374 return checkFPMScaleIfConstant(SemaRef, TheCall, 1, 0, 127);
1375
1376 if (BuiltinID == AArch64::BI__arm_set_fpm_nscale)
1377 return checkFPMScaleIfConstant(SemaRef, TheCall, 1, -128, 127);
1378
1379 if (BuiltinID == AArch64::BI__arm_set_fpm_lscale2)
1380 return checkFPMScaleIfConstant(SemaRef, TheCall, 1, 0, 63);
1381
1382 // For intrinsics which take an immediate value as part of the instruction,
1383 // range check them here.
1384 unsigned i = 0, l = 0, u = 0;
1385 switch (BuiltinID) {
1386 default: return false;
1387 case AArch64::BI__builtin_arm_dmb:
1388 case AArch64::BI__dmb:
1389 case AArch64::BI__builtin_arm_dsb:
1390 case AArch64::BI__dsb:
1391 case AArch64::BI__builtin_arm_isb:
1392 case AArch64::BI__isb:
1393 l = 0;
1394 u = 15;
1395 break;
1396 }
1397
1398 return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
1399}
1400
1401namespace {
1402struct IntrinToName {
1403 uint32_t Id;
1404 int32_t FullName;
1405 int32_t ShortName;
1406};
1407} // unnamed namespace
1408
1409static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
1411 const char *IntrinNames) {
1412 AliasName.consume_front("__arm_");
1413 const IntrinToName *It =
1414 llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
1415 return L.Id < Id;
1416 });
1417 if (It == Map.end() || It->Id != BuiltinID)
1418 return false;
1419 StringRef FullName(&IntrinNames[It->FullName]);
1420 if (AliasName == FullName)
1421 return true;
1422 if (It->ShortName == -1)
1423 return false;
1424 StringRef ShortName(&IntrinNames[It->ShortName]);
1425 return AliasName == ShortName;
1426}
1427
1428bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1429#include "clang/Basic/arm_mve_builtin_aliases.inc"
1430 // The included file defines:
1431 // - ArrayRef<IntrinToName> Map
1432 // - const char IntrinNames[]
1433 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1434}
1435
1436bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1437#include "clang/Basic/arm_cde_builtin_aliases.inc"
1438 return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
1439}
1440
1441bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) {
1442 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1443 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1444 return BuiltinID >= AArch64::FirstSVEBuiltin &&
1445 BuiltinID <= AArch64::LastSVEBuiltin;
1446}
1447
1448bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) {
1449 if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
1450 BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
1451 return BuiltinID >= AArch64::FirstSMEBuiltin &&
1452 BuiltinID <= AArch64::LastSMEBuiltin;
1453}
1454
1456 ASTContext &Context = getASTContext();
1457 if (!AL.isArgIdent(0)) {
1458 Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
1459 << AL << 1 << AANT_ArgumentIdentifier;
1460 return;
1461 }
1462
1464 unsigned BuiltinID = Ident->getBuiltinID();
1465 StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
1466
1467 bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
1468 if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) &&
1469 !SmeAliasValid(BuiltinID, AliasName)) ||
1470 (!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) &&
1471 !CdeAliasValid(BuiltinID, AliasName))) {
1472 Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
1473 return;
1474 }
1475
1476 D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
1477}
1478
1480 Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT,
1481 FunctionType::ArmStateValue CurrentState, StringRef StateName) {
1482 auto CheckForIncompatibleAttr =
1483 [&](FunctionType::ArmStateValue IncompatibleState,
1484 StringRef IncompatibleStateName) {
1485 if (CurrentState == IncompatibleState) {
1486 S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
1487 << (std::string("'__arm_new(\"") + StateName.str() + "\")'")
1488 << (std::string("'") + IncompatibleStateName.str() + "(\"" +
1489 StateName.str() + "\")'")
1490 << true;
1491 AL.setInvalid();
1492 }
1493 };
1494
1495 CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in");
1496 CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out");
1497 CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout");
1498 CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves");
1499 return AL.isInvalid();
1500}
1501
1503 if (!AL.getNumArgs()) {
1504 Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
1505 AL.setInvalid();
1506 return;
1507 }
1508
1509 std::vector<StringRef> NewState;
1510 if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) {
1511 for (StringRef S : ExistingAttr->newArgs())
1512 NewState.push_back(S);
1513 }
1514
1515 bool HasZA = false;
1516 bool HasZT0 = false;
1517 for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1518 StringRef StateName;
1519 SourceLocation LiteralLoc;
1520 if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
1521 return;
1522
1523 if (StateName == "za")
1524 HasZA = true;
1525 else if (StateName == "zt0")
1526 HasZT0 = true;
1527 else {
1528 Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
1529 AL.setInvalid();
1530 return;
1531 }
1532
1533 if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates.
1534 NewState.push_back(StateName);
1535 }
1536
1537 if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) {
1539 FunctionType::getArmZAState(FPT->getAArch64SMEAttributes());
1540 if (HasZA && ZAState != FunctionType::ARM_None &&
1541 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za"))
1542 return;
1544 FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes());
1545 if (HasZT0 && ZT0State != FunctionType::ARM_None &&
1546 checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0"))
1547 return;
1548 }
1549
1550 D->dropAttr<ArmNewAttr>();
1551 D->addAttr(::new (getASTContext()) ArmNewAttr(
1552 getASTContext(), AL, NewState.data(), NewState.size()));
1553}
1554
1557 Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
1558 return;
1559 }
1560
1561 const auto *FD = cast<FunctionDecl>(D);
1562 if (!FD->isExternallyVisible()) {
1563 Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
1564 return;
1565 }
1566
1567 D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL));
1568}
1569
1571 // Check the attribute arguments.
1572 if (AL.getNumArgs() > 1) {
1573 Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
1574 return;
1575 }
1576
1577 StringRef Str;
1578 SourceLocation ArgLoc;
1579
1580 if (AL.getNumArgs() == 0)
1581 Str = "";
1582 else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
1583 return;
1584
1585 ARMInterruptAttr::InterruptType Kind;
1586 if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
1587 Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
1588 << AL << Str << ArgLoc;
1589 return;
1590 }
1591
1592 if (!D->hasAttr<ARMSaveFPAttr>()) {
1593 const TargetInfo &TI = getASTContext().getTargetInfo();
1594 if (TI.hasFeature("vfp"))
1595 Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1596 }
1597
1598 D->addAttr(::new (getASTContext())
1599 ARMInterruptAttr(getASTContext(), AL, Kind));
1600}
1601
1603 // Go ahead and add ARMSaveFPAttr because handleInterruptAttr() checks for
1604 // it when deciding to issue a diagnostic about clobbering floating point
1605 // registers, which ARMSaveFPAttr prevents.
1606 D->addAttr(::new (SemaRef.Context) ARMSaveFPAttr(SemaRef.Context, AL));
1607 SemaRef.ARM().handleInterruptAttr(D, AL);
1608
1609 // If ARM().handleInterruptAttr() failed, remove ARMSaveFPAttr.
1610 if (!D->hasAttr<ARMInterruptAttr>()) {
1611 D->dropAttr<ARMSaveFPAttr>();
1612 return;
1613 }
1614
1615 // If VFP not enabled, remove ARMSaveFPAttr but leave ARMInterruptAttr.
1616 bool VFP = SemaRef.Context.getTargetInfo().hasFeature("vfp");
1617
1618 if (!VFP) {
1619 SemaRef.Diag(D->getLocation(), diag::warn_arm_interrupt_save_fp_without_vfp_unit);
1620 D->dropAttr<ARMSaveFPAttr>();
1621 }
1622}
1623
1624// Check if the function definition uses any AArch64 SME features without
1625// having the '+sme' feature enabled and warn user if sme locally streaming
1626// function returns or uses arguments with VL-based types.
1628 const auto *Attr = FD->getAttr<ArmNewAttr>();
1629 bool UsesSM = FD->hasAttr<ArmLocallyStreamingAttr>();
1630 bool UsesZA = Attr && Attr->isNewZA();
1631 bool UsesZT0 = Attr && Attr->isNewZT0();
1632
1633 if (UsesZA || UsesZT0) {
1634 if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
1635 FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1637 Diag(FD->getLocation(), diag::err_sme_unsupported_agnostic_new);
1638 }
1639 }
1640
1641 if (FD->hasAttr<ArmLocallyStreamingAttr>()) {
1643 Diag(FD->getLocation(),
1644 diag::warn_sme_locally_streaming_has_vl_args_returns)
1645 << /*IsArg=*/false;
1646 if (llvm::any_of(FD->parameters(), [](ParmVarDecl *P) {
1647 return P->getOriginalType()->isSizelessVectorType();
1648 }))
1649 Diag(FD->getLocation(),
1650 diag::warn_sme_locally_streaming_has_vl_args_returns)
1651 << /*IsArg=*/true;
1652 }
1653 if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
1654 FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1660 }
1661
1662 ASTContext &Context = getASTContext();
1663 if (UsesSM || UsesZA) {
1664 llvm::StringMap<bool> FeatureMap;
1665 Context.getFunctionFeatureMap(FeatureMap, FD);
1666 if (!FeatureMap.contains("sme")) {
1667 if (UsesSM)
1668 Diag(FD->getLocation(),
1669 diag::err_sme_definition_using_sm_in_non_sme_target);
1670 else
1671 Diag(FD->getLocation(),
1672 diag::err_sme_definition_using_za_in_non_sme_target);
1673 }
1674 }
1675 if (UsesZT0) {
1676 llvm::StringMap<bool> FeatureMap;
1677 Context.getFunctionFeatureMap(FeatureMap, FD);
1678 if (!FeatureMap.contains("sme2")) {
1679 Diag(FD->getLocation(),
1680 diag::err_sme_definition_using_zt0_in_non_sme2_target);
1681 }
1682 }
1683}
1684
1685/// getSVETypeSize - Return SVE vector or predicate register size.
1686static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty,
1687 bool IsStreaming) {
1688 assert(Ty->isSveVLSBuiltinType() && "Invalid SVE Type");
1689 uint64_t VScale = IsStreaming ? Context.getLangOpts().VScaleStreamingMin
1690 : Context.getLangOpts().VScaleMin;
1691 if (Ty->getKind() == BuiltinType::SveBool ||
1692 Ty->getKind() == BuiltinType::SveCount)
1693 return (VScale * 128) / Context.getCharWidth();
1694 return VScale * 128;
1695}
1696
1698 bool IsStreaming = false;
1699 if (getLangOpts().VScaleMin != getLangOpts().VScaleStreamingMin ||
1700 getLangOpts().VScaleMax != getLangOpts().VScaleStreamingMax) {
1701 if (const FunctionDecl *FD =
1702 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
1703 // For streaming-compatible functions, we don't know vector length.
1704 if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
1705 if (T->getAArch64SMEAttributes() &
1707 return false;
1708 }
1709
1710 if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
1711 IsStreaming = true;
1712 }
1713 }
1714
1715 auto IsValidCast = [&](QualType FirstType, QualType SecondType) {
1716 if (const auto *BT = FirstType->getAs<BuiltinType>()) {
1717 if (const auto *VT = SecondType->getAs<VectorType>()) {
1718 // Predicates have the same representation as uint8 so we also have to
1719 // check the kind to make these types incompatible.
1720 ASTContext &Context = getASTContext();
1721 if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate)
1722 return BT->getKind() == BuiltinType::SveBool;
1723 else if (VT->getVectorKind() == VectorKind::SveFixedLengthData)
1724 return VT->getElementType().getCanonicalType() ==
1725 FirstType->getSveEltType(Context) &&
1726 BT->getKind() != BuiltinType::SveBool;
1727 else if (VT->getVectorKind() == VectorKind::Generic)
1728 return Context.getTypeSize(SecondType) ==
1729 getSVETypeSize(Context, BT, IsStreaming) &&
1730 Context.hasSameType(
1731 VT->getElementType(),
1732 Context.getBuiltinVectorTypeInfo(BT).ElementType);
1733 }
1734 }
1735 return false;
1736 };
1737
1738 return IsValidCast(FirstType, SecondType) ||
1739 IsValidCast(SecondType, FirstType);
1740}
1741
1743 QualType SecondType) {
1744 bool IsStreaming = false;
1745 if (getLangOpts().VScaleMin != getLangOpts().VScaleStreamingMin ||
1746 getLangOpts().VScaleMax != getLangOpts().VScaleStreamingMax) {
1747 if (const FunctionDecl *FD =
1748 SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
1749 // For streaming-compatible functions, we don't know vector length.
1750 if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
1751 if (T->getAArch64SMEAttributes() &
1753 return false;
1754
1755 if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
1756 IsStreaming = true;
1757 }
1758 }
1759
1760 auto IsLaxCompatible = [&](QualType FirstType, QualType SecondType) {
1761 const auto *BT = FirstType->getAs<BuiltinType>();
1762 if (!BT)
1763 return false;
1764
1765 const auto *VecTy = SecondType->getAs<VectorType>();
1766 if (VecTy && (VecTy->getVectorKind() == VectorKind::SveFixedLengthData ||
1767 VecTy->getVectorKind() == VectorKind::Generic)) {
1769 getLangOpts().getLaxVectorConversions();
1770 ASTContext &Context = getASTContext();
1771
1772 // Can not convert between sve predicates and sve vectors because of
1773 // different size.
1774 if (BT->getKind() == BuiltinType::SveBool &&
1775 VecTy->getVectorKind() == VectorKind::SveFixedLengthData)
1776 return false;
1777
1778 // If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion.
1779 // "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly
1780 // converts to VLAT and VLAT implicitly converts to GNUT."
1781 // ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and
1782 // predicates.
1783 if (VecTy->getVectorKind() == VectorKind::Generic &&
1784 Context.getTypeSize(SecondType) !=
1785 getSVETypeSize(Context, BT, IsStreaming))
1786 return false;
1787
1788 // If -flax-vector-conversions=all is specified, the types are
1789 // certainly compatible.
1791 return true;
1792
1793 // If -flax-vector-conversions=integer is specified, the types are
1794 // compatible if the elements are integer types.
1796 return VecTy->getElementType().getCanonicalType()->isIntegerType() &&
1797 FirstType->getSveEltType(Context)->isIntegerType();
1798 }
1799
1800 return false;
1801 };
1802
1803 return IsLaxCompatible(FirstType, SecondType) ||
1804 IsLaxCompatible(SecondType, FirstType);
1805}
1806
1807static void appendFeature(StringRef Feat, SmallString<64> &Buffer) {
1808 if (!Buffer.empty())
1809 Buffer.append("+");
1810 Buffer.append(Feat);
1811}
1812
1813static void convertPriorityString(unsigned Priority,
1814 SmallString<64> &NewParam) {
1815 StringRef PriorityString[8] = {"P0", "P1", "P2", "P3",
1816 "P4", "P5", "P6", "P7"};
1817
1818 assert(Priority > 0 && Priority < 256 && "priority out of range");
1819 // Convert priority=[1-255] -> P0 + ... + P7
1820 for (unsigned BitPos = 0; BitPos < 8; ++BitPos)
1821 if (Priority & (1U << BitPos))
1822 appendFeature(PriorityString[BitPos], NewParam);
1823}
1824
1825bool SemaARM::checkTargetVersionAttr(const StringRef Param,
1826 const SourceLocation Loc,
1827 SmallString<64> &NewParam) {
1828 using namespace DiagAttrParams;
1829
1830 auto [LHS, RHS] = Param.split(';');
1831 RHS = RHS.trim();
1832 bool IsDefault = false;
1834 LHS.split(Features, '+');
1835 for (StringRef Feat : Features) {
1836 Feat = Feat.trim();
1837 if (Feat == "default")
1838 IsDefault = true;
1839 else if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
1840 return Diag(Loc, diag::warn_unsupported_target_attribute)
1841 << Unsupported << None << Feat << TargetVersion;
1842 appendFeature(Feat, NewParam);
1843 }
1844
1845 if (!RHS.empty() && RHS.consume_front("priority=")) {
1846 if (IsDefault)
1847 Diag(Loc, diag::warn_invalid_default_version_priority);
1848 else {
1849 unsigned Digit;
1850 if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1851 Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1852 else
1853 convertPriorityString(Digit, NewParam);
1854 }
1855 }
1856 return false;
1857}
1858
1861 SmallVectorImpl<SmallString<64>> &NewParams) {
1862 using namespace DiagAttrParams;
1863
1864 if (!getASTContext().getTargetInfo().hasFeature("fmv"))
1865 return true;
1866
1867 assert(Params.size() == Locs.size() &&
1868 "Mismatch between number of string parameters and locations");
1869
1870 bool HasDefault = false;
1871 bool HasNonDefault = false;
1872 for (unsigned I = 0, E = Params.size(); I < E; ++I) {
1873 const StringRef Param = Params[I].trim();
1874 const SourceLocation &Loc = Locs[I];
1875
1876 auto [LHS, RHS] = Param.split(';');
1877 RHS = RHS.trim();
1878 bool HasPriority = !RHS.empty() && RHS.consume_front("priority=");
1879
1880 if (LHS.empty())
1881 return Diag(Loc, diag::warn_unsupported_target_attribute)
1882 << Unsupported << None << "" << TargetClones;
1883
1884 if (LHS == "default") {
1885 if (HasDefault)
1886 Diag(Loc, diag::warn_target_clone_duplicate_options);
1887 else {
1888 if (HasPriority)
1889 Diag(Loc, diag::warn_invalid_default_version_priority);
1890 NewParams.push_back(LHS);
1891 HasDefault = true;
1892 }
1893 continue;
1894 }
1895
1896 bool HasCodeGenImpact = false;
1898 llvm::SmallVector<StringRef, 8> ValidFeatures;
1899 LHS.split(Features, '+');
1900 for (StringRef Feat : Features) {
1901 Feat = Feat.trim();
1902 if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
1903 Diag(Loc, diag::warn_unsupported_target_attribute)
1904 << Unsupported << None << Feat << TargetClones;
1905 continue;
1906 }
1907 if (getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat))
1908 HasCodeGenImpact = true;
1909 ValidFeatures.push_back(Feat);
1910 }
1911
1912 // Ignore features that don't impact code generation.
1913 if (!HasCodeGenImpact) {
1914 Diag(Loc, diag::warn_target_clone_no_impact_options);
1915 continue;
1916 }
1917
1918 if (ValidFeatures.empty())
1919 continue;
1920
1921 // Canonicalize attribute parameter.
1922 llvm::sort(ValidFeatures);
1923 SmallString<64> NewParam(llvm::join(ValidFeatures, "+"));
1924 if (llvm::is_contained(NewParams, NewParam)) {
1925 Diag(Loc, diag::warn_target_clone_duplicate_options);
1926 continue;
1927 }
1928
1929 if (HasPriority) {
1930 unsigned Digit;
1931 if (RHS.getAsInteger(0, Digit) || Digit < 1 || Digit > 255)
1932 Diag(Loc, diag::warn_version_priority_out_of_range) << RHS;
1933 else
1934 convertPriorityString(Digit, NewParam);
1935 }
1936
1937 // Valid non-default argument.
1938 NewParams.push_back(NewParam);
1939 HasNonDefault = true;
1940 }
1941
1942 return !HasNonDefault;
1943}
1944
1946 const FunctionDecl *FD,
1947 const llvm::StringMap<bool> &FeatureMap) {
1948 if (!Ty->isSVESizelessBuiltinType())
1949 return false;
1950
1951 if (FeatureMap.lookup("sve"))
1952 return false;
1953
1954 // No SVE environment available.
1955 if (!FeatureMap.lookup("sme"))
1956 return Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
1957
1958 // SVE environment only available to streaming functions.
1959 if (FD && !FD->getType().isNull() &&
1960 !IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
1961 return Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
1962
1963 return false;
1964}
1965} // 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:239
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:852
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:969
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:581
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:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
void dropAttr()
Definition DeclBase.h:564
bool hasAttr() const
Definition DeclBase.h:585
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:3131
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:3126
@ 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:2976
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:1627
bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:1183
bool BuiltinARMAtomicStoreHintCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:326
void handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL)
Definition SemaARM.cpp:1602
bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:774
bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, bool WantCDE)
Definition SemaARM.cpp:962
bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:819
bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:848
bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:946
bool PerformNeonImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int, int > > &ImmChecks, int OverloadType=-1)
Definition SemaARM.cpp:645
bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:937
void handleInterruptAttr(Decl *D, const ParsedAttr &AL)
Definition SemaARM.cpp:1570
bool PerformSVEImmChecks(CallExpr *TheCall, SmallVectorImpl< std::tuple< int, int, int > > &ImmChecks)
Definition SemaARM.cpp:664
void handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL)
Definition SemaARM.cpp:1455
@ 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:1502
bool CheckARMBuiltinExclusiveCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:987
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:1697
bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc, SmallString< 64 > &NewParam)
Definition SemaARM.cpp:1825
bool checkSVETypeSupport(QualType Ty, SourceLocation Loc, const FunctionDecl *FD, const llvm::StringMap< bool > &FeatureMap)
Definition SemaARM.cpp:1945
bool SveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition SemaARM.cpp:1441
bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType)
Return true if the given vector types are lax-compatible SVE vector types, false otherwise.
Definition SemaARM.cpp:1742
bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
Definition SemaARM.cpp:1265
bool MveAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition SemaARM.cpp:1428
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:1555
bool CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, unsigned ArgIdx, unsigned EltBitWidth, unsigned VecBitWidth)
Definition SemaARM.cpp:503
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:1448
bool checkTargetClonesAttr(SmallVectorImpl< StringRef > &Params, SmallVectorImpl< SourceLocation > &Locs, SmallVectorImpl< SmallString< 64 > > &NewParams)
Definition SemaARM.cpp:1859
bool CdeAliasValid(unsigned BuiltinID, llvm::StringRef AliasName)
Definition SemaARM.cpp:1436
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:226
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
IntType getInt64Type() const
Definition TargetInfo.h:428
@ 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:1813
@ CPlusPlus
static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, ArrayRef< IntrinToName > Map, const char *IntrinNames)
Definition SemaARM.cpp:1409
static ArmSMEState getSMEState(unsigned BuiltinID)
Definition SemaARM.cpp:764
static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, const FunctionDecl *FD, SemaARM::ArmStreamingType BuiltinType, unsigned BuiltinID)
Definition SemaARM.cpp:693
ArmSMEState
Definition SemaARM.cpp:489
@ ArmInOutZA
Definition SemaARM.cpp:494
@ ArmZT0Mask
Definition SemaARM.cpp:500
@ ArmInOutZT0
Definition SemaARM.cpp:499
@ ArmInZA
Definition SemaARM.cpp:492
@ ArmInZT0
Definition SemaARM.cpp:497
@ ArmZAMask
Definition SemaARM.cpp:495
@ ArmOutZA
Definition SemaARM.cpp:493
@ ArmOutZT0
Definition SemaARM.cpp:498
@ ArmNoState
Definition SemaARM.cpp:490
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD)
Definition SemaARM.cpp:677
static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty, bool IsStreaming)
getSVETypeSize - Return SVE vector or predicate register size.
Definition SemaARM.cpp:1686
@ 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:1163
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:6203
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:449
static bool checkNewAttrMutualExclusion(Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT, FunctionType::ArmStateValue CurrentState, StringRef StateName)
Definition SemaARM.cpp:1479
static void appendFeature(StringRef Feat, SmallString< 64 > &Buffer)
Definition SemaARM.cpp:1807
@ 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:6182
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
bool hasArmZAState(const FunctionDecl *FD)
Returns whether the given FunctionDecl has Arm ZA state.
Definition Decl.cpp:6196
int32_t uint32_t
Extra information about a function prototype.
Definition TypeBase.h:5501