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