//===------ SemaARM.cpp ---------- ARM target-specific routines -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis functions specific to ARM.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaARM.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"

namespace clang {

SemaARM::SemaARM(Sema &S) : SemaBase(S) {}

/// BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions
bool SemaARM::BuiltinARMMemoryTaggingCall(unsigned BuiltinID,
                                          CallExpr *TheCall) {
  ASTContext &Context = getASTContext();

  if (BuiltinID == AArch64::BI__builtin_arm_irg) {
    if (SemaRef.checkArgCount(TheCall, 2))
      return true;
    Expr *Arg0 = TheCall->getArg(0);
    Expr *Arg1 = TheCall->getArg(1);

    ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);
    if (FirstArg.isInvalid())
      return true;
    QualType FirstArgType = FirstArg.get()->getType();
    if (!FirstArgType->isAnyPointerType())
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
             << "first" << FirstArgType << Arg0->getSourceRange();
    TheCall->setArg(0, FirstArg.get());

    ExprResult SecArg = SemaRef.DefaultLvalueConversion(Arg1);
    if (SecArg.isInvalid())
      return true;
    QualType SecArgType = SecArg.get()->getType();
    if (!SecArgType->isIntegerType())
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
             << "second" << SecArgType << Arg1->getSourceRange();

    // Derive the return type from the pointer argument.
    TheCall->setType(FirstArgType);
    return false;
  }

  if (BuiltinID == AArch64::BI__builtin_arm_addg) {
    if (SemaRef.checkArgCount(TheCall, 2))
      return true;

    Expr *Arg0 = TheCall->getArg(0);
    ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);
    if (FirstArg.isInvalid())
      return true;
    QualType FirstArgType = FirstArg.get()->getType();
    if (!FirstArgType->isAnyPointerType())
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
             << "first" << FirstArgType << Arg0->getSourceRange();
    TheCall->setArg(0, FirstArg.get());

    // Derive the return type from the pointer argument.
    TheCall->setType(FirstArgType);

    // Second arg must be an constant in range [0,15]
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
  }

  if (BuiltinID == AArch64::BI__builtin_arm_gmi) {
    if (SemaRef.checkArgCount(TheCall, 2))
      return true;
    Expr *Arg0 = TheCall->getArg(0);
    Expr *Arg1 = TheCall->getArg(1);

    ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);
    if (FirstArg.isInvalid())
      return true;
    QualType FirstArgType = FirstArg.get()->getType();
    if (!FirstArgType->isAnyPointerType())
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
             << "first" << FirstArgType << Arg0->getSourceRange();

    QualType SecArgType = Arg1->getType();
    if (!SecArgType->isIntegerType())
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer)
             << "second" << SecArgType << Arg1->getSourceRange();
    TheCall->setType(Context.IntTy);
    return false;
  }

  if (BuiltinID == AArch64::BI__builtin_arm_ldg ||
      BuiltinID == AArch64::BI__builtin_arm_stg) {
    if (SemaRef.checkArgCount(TheCall, 1))
      return true;
    Expr *Arg0 = TheCall->getArg(0);
    ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0);
    if (FirstArg.isInvalid())
      return true;

    QualType FirstArgType = FirstArg.get()->getType();
    if (!FirstArgType->isAnyPointerType())
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer)
             << "first" << FirstArgType << Arg0->getSourceRange();
    TheCall->setArg(0, FirstArg.get());

    // Derive the return type from the pointer argument.
    if (BuiltinID == AArch64::BI__builtin_arm_ldg)
      TheCall->setType(FirstArgType);
    return false;
  }

  if (BuiltinID == AArch64::BI__builtin_arm_subp) {
    Expr *ArgA = TheCall->getArg(0);
    Expr *ArgB = TheCall->getArg(1);

    ExprResult ArgExprA = SemaRef.DefaultFunctionArrayLvalueConversion(ArgA);
    ExprResult ArgExprB = SemaRef.DefaultFunctionArrayLvalueConversion(ArgB);

    if (ArgExprA.isInvalid() || ArgExprB.isInvalid())
      return true;

    QualType ArgTypeA = ArgExprA.get()->getType();
    QualType ArgTypeB = ArgExprB.get()->getType();

    auto isNull = [&](Expr *E) -> bool {
      return E->isNullPointerConstant(Context,
                                      Expr::NPC_ValueDependentIsNotNull);
    };

    // argument should be either a pointer or null
    if (!ArgTypeA->isAnyPointerType() && !isNull(ArgA))
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
             << "first" << ArgTypeA << ArgA->getSourceRange();

    if (!ArgTypeB->isAnyPointerType() && !isNull(ArgB))
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer)
             << "second" << ArgTypeB << ArgB->getSourceRange();

    // Ensure Pointee types are compatible
    if (ArgTypeA->isAnyPointerType() && !isNull(ArgA) &&
        ArgTypeB->isAnyPointerType() && !isNull(ArgB)) {
      QualType pointeeA = ArgTypeA->getPointeeType();
      QualType pointeeB = ArgTypeB->getPointeeType();
      if (!Context.typesAreCompatible(
              Context.getCanonicalType(pointeeA).getUnqualifiedType(),
              Context.getCanonicalType(pointeeB).getUnqualifiedType())) {
        return Diag(TheCall->getBeginLoc(),
                    diag::err_typecheck_sub_ptr_compatible)
               << ArgTypeA << ArgTypeB << ArgA->getSourceRange()
               << ArgB->getSourceRange();
      }
    }

    // at least one argument should be pointer type
    if (!ArgTypeA->isAnyPointerType() && !ArgTypeB->isAnyPointerType())
      return Diag(TheCall->getBeginLoc(), diag::err_memtag_any2arg_pointer)
             << ArgTypeA << ArgTypeB << ArgA->getSourceRange();

    if (isNull(ArgA)) // adopt type of the other pointer
      ArgExprA =
          SemaRef.ImpCastExprToType(ArgExprA.get(), ArgTypeB, CK_NullToPointer);

    if (isNull(ArgB))
      ArgExprB =
          SemaRef.ImpCastExprToType(ArgExprB.get(), ArgTypeA, CK_NullToPointer);

    TheCall->setArg(0, ArgExprA.get());
    TheCall->setArg(1, ArgExprB.get());
    TheCall->setType(Context.LongLongTy);
    return false;
  }
  assert(false && "Unhandled ARM MTE intrinsic");
  return true;
}

/// BuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr
/// TheCall is an ARM/AArch64 special register string literal.
bool SemaARM::BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
                                   int ArgNum, unsigned ExpectedFieldNum,
                                   bool AllowName) {
  bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 ||
                      BuiltinID == ARM::BI__builtin_arm_wsr64 ||
                      BuiltinID == ARM::BI__builtin_arm_rsr ||
                      BuiltinID == ARM::BI__builtin_arm_rsrp ||
                      BuiltinID == ARM::BI__builtin_arm_wsr ||
                      BuiltinID == ARM::BI__builtin_arm_wsrp;
  bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
                          BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
                          BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
                          BuiltinID == AArch64::BI__builtin_arm_wsr128 ||
                          BuiltinID == AArch64::BI__builtin_arm_rsr ||
                          BuiltinID == AArch64::BI__builtin_arm_rsrp ||
                          BuiltinID == AArch64::BI__builtin_arm_wsr ||
                          BuiltinID == AArch64::BI__builtin_arm_wsrp;
  assert((IsARMBuiltin || IsAArch64Builtin) && "Unexpected ARM builtin.");

  // We can't check the value of a dependent argument.
  Expr *Arg = TheCall->getArg(ArgNum);
  if (Arg->isTypeDependent() || Arg->isValueDependent())
    return false;

  // Check if the argument is a string literal.
  if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
    return Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
           << Arg->getSourceRange();

  // Check the type of special register given.
  StringRef Reg = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
  SmallVector<StringRef, 6> Fields;
  Reg.split(Fields, ":");

  if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1))
    return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
           << Arg->getSourceRange();

  // If the string is the name of a register then we cannot check that it is
  // valid here but if the string is of one the forms described in ACLE then we
  // can check that the supplied fields are integers and within the valid
  // ranges.
  if (Fields.size() > 1) {
    bool FiveFields = Fields.size() == 5;

    bool ValidString = true;
    if (IsARMBuiltin) {
      ValidString &= Fields[0].starts_with_insensitive("cp") ||
                     Fields[0].starts_with_insensitive("p");
      if (ValidString)
        Fields[0] = Fields[0].drop_front(
            Fields[0].starts_with_insensitive("cp") ? 2 : 1);

      ValidString &= Fields[2].starts_with_insensitive("c");
      if (ValidString)
        Fields[2] = Fields[2].drop_front(1);

      if (FiveFields) {
        ValidString &= Fields[3].starts_with_insensitive("c");
        if (ValidString)
          Fields[3] = Fields[3].drop_front(1);
      }
    }

    SmallVector<int, 5> FieldBitWidths;
    if (FiveFields)
      FieldBitWidths.append({IsAArch64Builtin ? 2 : 4, 3, 4, 4, 3});
    else
      FieldBitWidths.append({4, 3, 4});

    for (unsigned i = 0; i < Fields.size(); ++i) {
      int IntField;
      ValidString &= !Fields[i].getAsInteger(10, IntField);
      ValidString &= (IntField >= 0 && IntField < (1 << FieldBitWidths[i]));
    }

    if (!ValidString)
      return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg)
             << Arg->getSourceRange();
  } else if (IsAArch64Builtin && Fields.size() == 1) {
    // This code validates writes to PSTATE registers.

    // Not a write.
    if (TheCall->getNumArgs() != 2)
      return false;

    // The 128-bit system register accesses do not touch PSTATE.
    if (BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
        BuiltinID == AArch64::BI__builtin_arm_wsr128)
      return false;

    // These are the named PSTATE accesses using "MSR (immediate)" instructions,
    // along with the upper limit on the immediates allowed.
    auto MaxLimit = llvm::StringSwitch<std::optional<unsigned>>(Reg)
                        .CaseLower("spsel", 15)
                        .CaseLower("daifclr", 15)
                        .CaseLower("daifset", 15)
                        .CaseLower("pan", 15)
                        .CaseLower("uao", 15)
                        .CaseLower("dit", 15)
                        .CaseLower("ssbs", 15)
                        .CaseLower("tco", 15)
                        .CaseLower("allint", 1)
                        .CaseLower("pm", 1)
                        .Default(std::nullopt);

    // If this is not a named PSTATE, just continue without validating, as this
    // will be lowered to an "MSR (register)" instruction directly
    if (!MaxLimit)
      return false;

    // Here we only allow constants in the range for that pstate, as required by
    // the ACLE.
    //
    // While clang also accepts the names of system registers in its ACLE
    // intrinsics, we prevent this with the PSTATE names used in MSR (immediate)
    // as the value written via a register is different to the value used as an
    // immediate to have the same effect. e.g., for the instruction `msr tco,
    // x0`, it is bit 25 of register x0 that is written into PSTATE.TCO, but
    // with `msr tco, #imm`, it is bit 0 of xN that is written into PSTATE.TCO.
    //
    // If a programmer wants to codegen the MSR (register) form of `msr tco,
    // xN`, they can still do so by specifying the register using five
    // colon-separated numbers in a string.
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit);
  }

  return false;
}

/// getNeonEltType - Return the QualType corresponding to the elements of
/// the vector type specified by the NeonTypeFlags.  This is used to check
/// the pointer arguments for Neon load/store intrinsics.
static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
                               bool IsPolyUnsigned, bool IsInt64Long) {
  switch (Flags.getEltType()) {
  case NeonTypeFlags::Int8:
    return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy;
  case NeonTypeFlags::Int16:
    return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy;
  case NeonTypeFlags::Int32:
    return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
  case NeonTypeFlags::Int64:
    if (IsInt64Long)
      return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
    else
      return Flags.isUnsigned() ? Context.UnsignedLongLongTy
                                : Context.LongLongTy;
  case NeonTypeFlags::Poly8:
    return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy;
  case NeonTypeFlags::Poly16:
    return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
  case NeonTypeFlags::Poly64:
    if (IsInt64Long)
      return Context.UnsignedLongTy;
    else
      return Context.UnsignedLongLongTy;
  case NeonTypeFlags::Poly128:
    break;
  case NeonTypeFlags::Float16:
    return Context.HalfTy;
  case NeonTypeFlags::Float32:
    return Context.FloatTy;
  case NeonTypeFlags::Float64:
    return Context.DoubleTy;
  case NeonTypeFlags::BFloat16:
    return Context.BFloat16Ty;
  case NeonTypeFlags::MFloat8:
    return Context.MFloat8Ty;
  }
  llvm_unreachable("Invalid NeonTypeFlag!");
}

enum ArmSMEState : unsigned {
  ArmNoState = 0,

  ArmInZA = 0b01,
  ArmOutZA = 0b10,
  ArmInOutZA = 0b11,
  ArmZAMask = 0b11,

  ArmInZT0 = 0b01 << 2,
  ArmOutZT0 = 0b10 << 2,
  ArmInOutZT0 = 0b11 << 2,
  ArmZT0Mask = 0b11 << 2
};

bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy,
                                unsigned ArgIdx, unsigned EltBitWidth,
                                unsigned ContainerBitWidth) {
  // Function that checks whether the operand (ArgIdx) is an immediate
  // that is one of a given set of values.
  auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set,
                                 int ErrDiag) -> bool {
    // We can't check the value of a dependent argument.
    Expr *Arg = TheCall->getArg(ArgIdx);
    if (Arg->isTypeDependent() || Arg->isValueDependent())
      return false;

    // Check constant-ness first.
    llvm::APSInt Imm;
    if (SemaRef.BuiltinConstantArg(TheCall, ArgIdx, Imm))
      return true;

    if (!llvm::is_contained(Set, Imm.getSExtValue()))
      return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
    return false;
  };

  switch ((ImmCheckType)CheckTy) {
  case ImmCheckType::ImmCheck0_31:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 31))
      return true;
    break;
  case ImmCheckType::ImmCheck0_13:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 13))
      return true;
    break;
  case ImmCheckType::ImmCheck0_63:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63))
      return true;
    break;
  case ImmCheckType::ImmCheck1_16:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16))
      return true;
    break;
  case ImmCheckType::ImmCheck0_7:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7))
      return true;
    break;
  case ImmCheckType::ImmCheck1_1:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 1))
      return true;
    break;
  case ImmCheckType::ImmCheck1_3:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 3))
      return true;
    break;
  case ImmCheckType::ImmCheck1_7:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 7))
      return true;
    break;
  case ImmCheckType::ImmCheckExtract:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
                                        (2048 / EltBitWidth) - 1))
      return true;
    break;
  case ImmCheckType::ImmCheckCvt:
  case ImmCheckType::ImmCheckShiftRight:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth))
      return true;
    break;
  case ImmCheckType::ImmCheckShiftRightNarrow:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth / 2))
      return true;
    break;
  case ImmCheckType::ImmCheckShiftLeft:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1))
      return true;
    break;
  case ImmCheckType::ImmCheckLaneIndex:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
                                        (ContainerBitWidth / EltBitWidth) - 1))
      return true;
    break;
  case ImmCheckType::ImmCheckLaneIndexCompRotate:
    if (SemaRef.BuiltinConstantArgRange(
            TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1))
      return true;
    break;
  case ImmCheckType::ImmCheckLaneIndexDot:
    if (SemaRef.BuiltinConstantArgRange(
            TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1))
      return true;
    break;
  case ImmCheckType::ImmCheckComplexRot90_270:
    if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd))
      return true;
    break;
  case ImmCheckType::ImmCheckComplexRotAll90:
    if (CheckImmediateInSet({0, 90, 180, 270},
                            diag::err_rotation_argument_to_cmla))
      return true;
    break;
  case ImmCheckType::ImmCheck0_1:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 1))
      return true;
    break;
  case ImmCheckType::ImmCheck0_2:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 2))
      return true;
    break;
  case ImmCheckType::ImmCheck0_3:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3))
      return true;
    break;
  case ImmCheckType::ImmCheck0_0:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 0))
      return true;
    break;
  case ImmCheckType::ImmCheck0_15:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 15))
      return true;
    break;
  case ImmCheckType::ImmCheck0_255:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 255))
      return true;
    break;
  case ImmCheckType::ImmCheck1_32:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32))
      return true;
    break;
  case ImmCheckType::ImmCheck1_64:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64))
      return true;
    break;
  case ImmCheckType::ImmCheck2_4_Mul2:
    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 2, 4) ||
        SemaRef.BuiltinConstantArgMultiple(TheCall, ArgIdx, 2))
      return true;
    break;
  }
  return false;
}

bool SemaARM::PerformNeonImmChecks(
    CallExpr *TheCall,
    SmallVectorImpl<std::tuple<int, int, int, int>> &ImmChecks,
    int OverloadType) {
  bool HasError = false;

  for (const auto &I : ImmChecks) {
    auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I;

    if (OverloadType >= 0)
      ElementBitWidth = NeonTypeFlags(OverloadType).getEltSizeInBits();

    HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth,
                                  VecBitWidth);
  }

  return HasError;
}

bool SemaARM::PerformSVEImmChecks(
    CallExpr *TheCall, SmallVectorImpl<std::tuple<int, int, int>> &ImmChecks) {
  bool HasError = false;

  for (const auto &I : ImmChecks) {
    auto [ArgIdx, CheckTy, ElementBitWidth] = I;
    HasError |=
        CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 128);
  }

  return HasError;
}

SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) {
  if (FD->hasAttr<ArmLocallyStreamingAttr>())
    return SemaARM::ArmStreaming;
  if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
    if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
      if (FPT->getAArch64SMEAttributes() &
          FunctionType::SME_PStateSMEnabledMask)
        return SemaARM::ArmStreaming;
      if (FPT->getAArch64SMEAttributes() &
          FunctionType::SME_PStateSMCompatibleMask)
        return SemaARM::ArmStreamingCompatible;
    }
  }
  return SemaARM::ArmNonStreaming;
}

static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
                                     const FunctionDecl *FD,
                                     SemaARM::ArmStreamingType BuiltinType,
                                     unsigned BuiltinID) {
  SemaARM::ArmStreamingType FnType = getArmStreamingFnType(FD);

  // Check if the intrinsic is available in the right mode, i.e.
  // * When compiling for SME only, the caller must be in streaming mode.
  // * When compiling for SVE only, the caller must be in non-streaming mode.
  // * When compiling for both SVE and SME, the caller can be in either mode.
  if (BuiltinType == SemaARM::VerifyRuntimeMode) {
    llvm::StringMap<bool> CallerFeatures;
    S.Context.getFunctionFeatureMap(CallerFeatures, FD);

    // Avoid emitting diagnostics for a function that can never compile.
    if (FnType == SemaARM::ArmStreaming && !CallerFeatures["sme"])
      return false;

    const auto FindTopLevelPipe = [](const char *S) {
      unsigned Depth = 0;
      unsigned I = 0, E = strlen(S);
      for (; I < E; ++I) {
        if (S[I] == '|' && Depth == 0)
          break;
        if (S[I] == '(')
          ++Depth;
        else if (S[I] == ')')
          --Depth;
      }
      return I;
    };

    const char *RequiredFeatures =
        S.Context.BuiltinInfo.getRequiredFeatures(BuiltinID);
    unsigned PipeIdx = FindTopLevelPipe(RequiredFeatures);
    assert(PipeIdx != 0 && PipeIdx != strlen(RequiredFeatures) &&
           "Expected feature string of the form 'SVE-EXPR|SME-EXPR'");
    StringRef NonStreamingBuiltinGuard = StringRef(RequiredFeatures, PipeIdx);
    StringRef StreamingBuiltinGuard = StringRef(RequiredFeatures + PipeIdx + 1);

    bool SatisfiesSVE = Builtin::evaluateRequiredTargetFeatures(
        NonStreamingBuiltinGuard, CallerFeatures);
    bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures(
        StreamingBuiltinGuard, CallerFeatures);

    if ((SatisfiesSVE && SatisfiesSME) ||
        (SatisfiesSVE && FnType == SemaARM::ArmStreamingCompatible))
      return false;
    else if (SatisfiesSVE)
      BuiltinType = SemaARM::ArmNonStreaming;
    else if (SatisfiesSME)
      BuiltinType = SemaARM::ArmStreaming;
    else
      // This should be diagnosed by CodeGen
      return false;
  }

  if (FnType != SemaARM::ArmNonStreaming &&
      BuiltinType == SemaARM::ArmNonStreaming)
    S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
        << TheCall->getSourceRange() << "non-streaming";
  else if (FnType != SemaARM::ArmStreaming &&
           BuiltinType == SemaARM::ArmStreaming)
    S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin)
        << TheCall->getSourceRange() << "streaming";
  else
    return false;

  return true;
}

static ArmSMEState getSMEState(unsigned BuiltinID) {
  switch (BuiltinID) {
  default:
    return ArmNoState;
#define GET_SME_BUILTIN_GET_STATE
#include "clang/Basic/arm_sme_builtins_za_state.inc"
#undef GET_SME_BUILTIN_GET_STATE
  }
}

bool SemaARM::CheckSMEBuiltinFunctionCall(unsigned BuiltinID,
                                          CallExpr *TheCall) {
  if (const FunctionDecl *FD =
          SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
    std::optional<ArmStreamingType> BuiltinType;

    switch (BuiltinID) {
#define GET_SME_STREAMING_ATTRS
#include "clang/Basic/arm_sme_streaming_attrs.inc"
#undef GET_SME_STREAMING_ATTRS
    }

    if (BuiltinType &&
        checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
      return true;

    if ((getSMEState(BuiltinID) & ArmZAMask) && !hasArmZAState(FD))
      Diag(TheCall->getBeginLoc(),
           diag::warn_attribute_arm_za_builtin_no_za_state)
          << TheCall->getSourceRange();

    if ((getSMEState(BuiltinID) & ArmZT0Mask) && !hasArmZT0State(FD))
      Diag(TheCall->getBeginLoc(),
           diag::warn_attribute_arm_zt0_builtin_no_zt0_state)
          << TheCall->getSourceRange();
  }

  // Range check SME intrinsics that take immediate values.
  SmallVector<std::tuple<int, int, int>, 3> ImmChecks;

  switch (BuiltinID) {
  default:
    return false;
#define GET_SME_IMMEDIATE_CHECK
#include "clang/Basic/arm_sme_sema_rangechecks.inc"
#undef GET_SME_IMMEDIATE_CHECK
  }

  return PerformSVEImmChecks(TheCall, ImmChecks);
}

bool SemaARM::CheckSVEBuiltinFunctionCall(unsigned BuiltinID,
                                          CallExpr *TheCall) {
  if (const FunctionDecl *FD =
          SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
    std::optional<ArmStreamingType> BuiltinType;

    switch (BuiltinID) {
#define GET_SVE_STREAMING_ATTRS
#include "clang/Basic/arm_sve_streaming_attrs.inc"
#undef GET_SVE_STREAMING_ATTRS
    }
    if (BuiltinType &&
        checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
      return true;
  }
  // Range check SVE intrinsics that take immediate values.
  SmallVector<std::tuple<int, int, int>, 3> ImmChecks;

  switch (BuiltinID) {
  default:
    return false;
#define GET_SVE_IMMEDIATE_CHECK
#include "clang/Basic/arm_sve_sema_rangechecks.inc"
#undef GET_SVE_IMMEDIATE_CHECK
  }

  return PerformSVEImmChecks(TheCall, ImmChecks);
}

bool SemaARM::CheckNeonBuiltinFunctionCall(const TargetInfo &TI,
                                           unsigned BuiltinID,
                                           CallExpr *TheCall) {
  if (const FunctionDecl *FD =
          SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
    std::optional<ArmStreamingType> BuiltinType;

    switch (BuiltinID) {
    default:
      break;
#define GET_NEON_STREAMING_COMPAT_FLAG
#include "clang/Basic/arm_neon.inc"
#undef GET_NEON_STREAMING_COMPAT_FLAG
    }
    if (BuiltinType &&
        checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID))
      return true;
  }

  llvm::APSInt Result;
  uint64_t mask = 0;
  int TV = -1;
  int PtrArgNum = -1;
  bool HasConstPtr = false;
  switch (BuiltinID) {
#define GET_NEON_OVERLOAD_CHECK
#include "clang/Basic/arm_fp16.inc"
#include "clang/Basic/arm_neon.inc"
#undef GET_NEON_OVERLOAD_CHECK
  }

  // For NEON intrinsics which are overloaded on vector element type, validate
  // the immediate which specifies which variant to emit.
  unsigned ImmArg = TheCall->getNumArgs() - 1;
  if (mask) {
    if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result))
      return true;

    TV = Result.getLimitedValue(64);
    if ((TV > 63) || (mask & (1ULL << TV)) == 0)
      return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code)
             << TheCall->getArg(ImmArg)->getSourceRange();
  }

  if (PtrArgNum >= 0) {
    // Check that pointer arguments have the specified type.
    Expr *Arg = TheCall->getArg(PtrArgNum);
    if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg))
      Arg = ICE->getSubExpr();
    ExprResult RHS = SemaRef.DefaultFunctionArrayLvalueConversion(Arg);
    QualType RHSTy = RHS.get()->getType();

    llvm::Triple::ArchType Arch = TI.getTriple().getArch();
    bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 ||
                          Arch == llvm::Triple::aarch64_32 ||
                          Arch == llvm::Triple::aarch64_be;
    bool IsInt64Long = TI.getInt64Type() == TargetInfo::SignedLong;
    QualType EltTy = getNeonEltType(NeonTypeFlags(TV), getASTContext(),
                                    IsPolyUnsigned, IsInt64Long);
    if (HasConstPtr)
      EltTy = EltTy.withConst();
    QualType LHSTy = getASTContext().getPointerType(EltTy);
    AssignConvertType ConvTy;
    ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS);
    if (RHS.isInvalid())
      return true;
    if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy,
                                         RHSTy, RHS.get(),
                                         AssignmentAction::Assigning))
      return true;
  }

  // For NEON intrinsics which take an immediate value as part of the
  // instruction, range check them here.
  SmallVector<std::tuple<int, int, int, int>, 2> ImmChecks;
  switch (BuiltinID) {
  default:
    return false;
#define GET_NEON_IMMEDIATE_CHECK
#include "clang/Basic/arm_fp16.inc"
#include "clang/Basic/arm_neon.inc"
#undef GET_NEON_IMMEDIATE_CHECK
  }

  return PerformNeonImmChecks(TheCall, ImmChecks, TV);
}

bool SemaARM::CheckMVEBuiltinFunctionCall(unsigned BuiltinID,
                                          CallExpr *TheCall) {
  switch (BuiltinID) {
  default:
    return false;
#include "clang/Basic/arm_mve_builtin_sema.inc"
  }
}

bool SemaARM::CheckCDEBuiltinFunctionCall(const TargetInfo &TI,
                                          unsigned BuiltinID,
                                          CallExpr *TheCall) {
  bool Err = false;
  switch (BuiltinID) {
  default:
    return false;
#include "clang/Basic/arm_cde_builtin_sema.inc"
  }

  if (Err)
    return true;

  return CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), /*WantCDE*/ true);
}

bool SemaARM::CheckARMCoprocessorImmediate(const TargetInfo &TI,
                                           const Expr *CoprocArg,
                                           bool WantCDE) {
  ASTContext &Context = getASTContext();
  if (SemaRef.isConstantEvaluatedContext())
    return false;

  // We can't check the value of a dependent argument.
  if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent())
    return false;

  llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context);
  int64_t CoprocNo = CoprocNoAP.getExtValue();
  assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative");

  uint32_t CDECoprocMask = TI.getARMCDECoprocMask();
  bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo));

  if (IsCDECoproc != WantCDE)
    return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc)
           << (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange();

  return false;
}

bool SemaARM::CheckARMBuiltinExclusiveCall(const TargetInfo &TI,
                                           unsigned BuiltinID,
                                           CallExpr *TheCall) {
  assert((BuiltinID == ARM::BI__builtin_arm_ldrex ||
          BuiltinID == ARM::BI__builtin_arm_ldaex ||
          BuiltinID == ARM::BI__builtin_arm_strex ||
          BuiltinID == ARM::BI__builtin_arm_stlex ||
          BuiltinID == AArch64::BI__builtin_arm_ldrex ||
          BuiltinID == AArch64::BI__builtin_arm_ldaex ||
          BuiltinID == AArch64::BI__builtin_arm_strex ||
          BuiltinID == AArch64::BI__builtin_arm_stlex) &&
         "unexpected ARM builtin");
  bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex ||
                 BuiltinID == ARM::BI__builtin_arm_ldaex ||
                 BuiltinID == AArch64::BI__builtin_arm_ldrex ||
                 BuiltinID == AArch64::BI__builtin_arm_ldaex;

  ASTContext &Context = getASTContext();
  DeclRefExpr *DRE =
      cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());

  // Ensure that we have the proper number of arguments.
  if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2))
    return true;

  // Inspect the pointer argument of the atomic builtin.  This should always be
  // a pointer type, whose element is an integral scalar or pointer type.
  // Because it is a pointer type, we don't have to worry about any implicit
  // casts here.
  Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1);
  ExprResult PointerArgRes =
      SemaRef.DefaultFunctionArrayLvalueConversion(PointerArg);
  if (PointerArgRes.isInvalid())
    return true;
  PointerArg = PointerArgRes.get();

  const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
  if (!pointerType) {
    Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
        << PointerArg->getType() << 0 << PointerArg->getSourceRange();
    return true;
  }

  // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next
  // task is to insert the appropriate casts into the AST. First work out just
  // what the appropriate type is.
  QualType ValType = pointerType->getPointeeType();
  QualType AddrType = ValType.getUnqualifiedType().withVolatile();
  if (IsLdrex)
    AddrType.addConst();

  // Issue a warning if the cast is dodgy.
  CastKind CastNeeded = CK_NoOp;
  if (!AddrType.isAtLeastAsQualifiedAs(ValType, getASTContext())) {
    CastNeeded = CK_BitCast;
    Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
        << PointerArg->getType() << Context.getPointerType(AddrType)
        << AssignmentAction::Passing << PointerArg->getSourceRange();
  }

  // Finally, do the cast and replace the argument with the corrected version.
  AddrType = Context.getPointerType(AddrType);
  PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded);
  if (PointerArgRes.isInvalid())
    return true;
  PointerArg = PointerArgRes.get();

  TheCall->setArg(IsLdrex ? 0 : 1, PointerArg);

  // In general, we allow ints, floats and pointers to be loaded and stored.
  if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
      !ValType->isBlockPointerType() && !ValType->isFloatingType()) {
    Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
        << PointerArg->getType() << 0 << PointerArg->getSourceRange();
    return true;
  }

  // Check whether the size of the type can be handled atomically on this
  // target.
  if (!TI.getTriple().isAArch64()) {
    unsigned Mask = TI.getARMLDREXMask();
    unsigned Bits = Context.getTypeSize(ValType);
    bool Supported =
        (llvm::isPowerOf2_64(Bits)) && Bits >= 8 && (Mask & (Bits / 8));

    if (!Supported) {
      // Emit a diagnostic saying that this size isn't available. If _no_ size
      // of exclusive access is supported on this target, we emit a diagnostic
      // with special wording for that case, but otherwise, we emit
      // err_atomic_exclusive_builtin_pointer_size and loop over `Mask` to
      // control what subset of sizes it lists as legal.
      if (Mask) {
        auto D = Diag(DRE->getBeginLoc(),
                      diag::err_atomic_exclusive_builtin_pointer_size)
                 << PointerArg->getType();
        bool Started = false;
        for (unsigned Size = 1; Size <= 8; Size <<= 1) {
          // For each of the sizes 1,2,4,8, pass two integers into the
          // diagnostic. The first selects a separator from the previous
          // number: 0 for no separator at all, 1 for a comma, 2 for " or "
          // which appears before the final number in a list of more than one.
          // The second integer just indicates whether we print this size in
          // the message at all.
          if (!(Mask & Size)) {
            // This size isn't one of the supported ones, so emit no separator
            // text and don't print the size itself.
            D << 0 << 0;
          } else {
            // This size is supported, so print it, and an appropriate
            // separator.
            Mask &= ~Size;
            if (!Started)
              D << 0; // No separator if this is the first size we've printed
            else if (Mask)
              D << 1; // "," if there's still another size to come
            else
              D << 2; // " or " if the size we're about to print is the last
            D << 1;   // print the size itself
            Started = true;
          }
        }
      } else {
        Diag(DRE->getBeginLoc(),
             diag::err_atomic_exclusive_builtin_pointer_size_none)
            << PointerArg->getSourceRange();
      }
    }
  }

  switch (ValType.getObjCLifetime()) {
  case Qualifiers::OCL_None:
  case Qualifiers::OCL_ExplicitNone:
    // okay
    break;

  case Qualifiers::OCL_Weak:
  case Qualifiers::OCL_Strong:
  case Qualifiers::OCL_Autoreleasing:
    Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
        << ValType << PointerArg->getSourceRange();
    return true;
  }

  if (IsLdrex) {
    TheCall->setType(ValType);
    return false;
  }

  // Initialize the argument to be stored.
  ExprResult ValArg = TheCall->getArg(0);
  InitializedEntity Entity = InitializedEntity::InitializeParameter(
      Context, ValType, /*consume*/ false);
  ValArg = SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg);
  if (ValArg.isInvalid())
    return true;
  TheCall->setArg(0, ValArg.get());

  // __builtin_arm_strex always returns an int. It's marked as such in the .def,
  // but the custom checker bypasses all default analysis.
  TheCall->setType(Context.IntTy);
  return false;
}

bool SemaARM::CheckARMBuiltinFunctionCall(const TargetInfo &TI,
                                          unsigned BuiltinID,
                                          CallExpr *TheCall) {
  if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
      BuiltinID == ARM::BI__builtin_arm_ldaex ||
      BuiltinID == ARM::BI__builtin_arm_strex ||
      BuiltinID == ARM::BI__builtin_arm_stlex) {
    return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
  }

  if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
           SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1);
  }

  if (BuiltinID == ARM::BI__builtin_arm_rsr64 ||
      BuiltinID == ARM::BI__builtin_arm_wsr64)
    return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false);

  if (BuiltinID == ARM::BI__builtin_arm_rsr ||
      BuiltinID == ARM::BI__builtin_arm_rsrp ||
      BuiltinID == ARM::BI__builtin_arm_wsr ||
      BuiltinID == ARM::BI__builtin_arm_wsrp)
    return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);

  if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
    return true;
  if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall))
    return true;
  if (CheckCDEBuiltinFunctionCall(TI, BuiltinID, TheCall))
    return true;

  // For intrinsics which take an immediate value as part of the instruction,
  // range check them here.
  // FIXME: VFP Intrinsics should error if VFP not present.
  switch (BuiltinID) {
  default:
    return false;
  case ARM::BI__builtin_arm_ssat:
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32);
  case ARM::BI__builtin_arm_usat:
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31);
  case ARM::BI__builtin_arm_ssat16:
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16);
  case ARM::BI__builtin_arm_usat16:
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15);
  case ARM::BI__builtin_arm_vcvtr_f:
  case ARM::BI__builtin_arm_vcvtr_d:
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1);
  case ARM::BI__builtin_arm_dmb:
  case ARM::BI__dmb:
  case ARM::BI__builtin_arm_dsb:
  case ARM::BI__dsb:
  case ARM::BI__builtin_arm_isb:
  case ARM::BI__isb:
  case ARM::BI__builtin_arm_dbg:
    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15);
  case ARM::BI__builtin_arm_cdp:
  case ARM::BI__builtin_arm_cdp2:
  case ARM::BI__builtin_arm_mcr:
  case ARM::BI__builtin_arm_mcr2:
  case ARM::BI__builtin_arm_mrc:
  case ARM::BI__builtin_arm_mrc2:
  case ARM::BI__builtin_arm_mcrr:
  case ARM::BI__builtin_arm_mcrr2:
  case ARM::BI__builtin_arm_mrrc:
  case ARM::BI__builtin_arm_mrrc2:
  case ARM::BI__builtin_arm_ldc:
  case ARM::BI__builtin_arm_ldcl:
  case ARM::BI__builtin_arm_ldc2:
  case ARM::BI__builtin_arm_ldc2l:
  case ARM::BI__builtin_arm_stc:
  case ARM::BI__builtin_arm_stcl:
  case ARM::BI__builtin_arm_stc2:
  case ARM::BI__builtin_arm_stc2l:
    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
           CheckARMCoprocessorImmediate(TI, TheCall->getArg(0),
                                        /*WantCDE*/ false);
  }
}

bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI,
                                              unsigned BuiltinID,
                                              CallExpr *TheCall) {
  if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
      BuiltinID == AArch64::BI__builtin_arm_ldaex ||
      BuiltinID == AArch64::BI__builtin_arm_strex ||
      BuiltinID == AArch64::BI__builtin_arm_stlex) {
    return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall);
  }

  if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
    return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
           SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
           SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
           SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1);
  }

  if (BuiltinID == AArch64::BI__builtin_arm_rsr64 ||
      BuiltinID == AArch64::BI__builtin_arm_wsr64 ||
      BuiltinID == AArch64::BI__builtin_arm_rsr128 ||
      BuiltinID == AArch64::BI__builtin_arm_wsr128)
    return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);

  // Memory Tagging Extensions (MTE) Intrinsics
  if (BuiltinID == AArch64::BI__builtin_arm_irg ||
      BuiltinID == AArch64::BI__builtin_arm_addg ||
      BuiltinID == AArch64::BI__builtin_arm_gmi ||
      BuiltinID == AArch64::BI__builtin_arm_ldg ||
      BuiltinID == AArch64::BI__builtin_arm_stg ||
      BuiltinID == AArch64::BI__builtin_arm_subp) {
    return BuiltinARMMemoryTaggingCall(BuiltinID, TheCall);
  }

  if (BuiltinID == AArch64::BI__builtin_arm_rsr ||
      BuiltinID == AArch64::BI__builtin_arm_rsrp ||
      BuiltinID == AArch64::BI__builtin_arm_wsr ||
      BuiltinID == AArch64::BI__builtin_arm_wsrp)
    return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true);

  // Only check the valid encoding range. Any constant in this range would be
  // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw
  // an exception for incorrect registers. This matches MSVC behavior.
  if (BuiltinID == AArch64::BI_ReadStatusReg ||
      BuiltinID == AArch64::BI_WriteStatusReg || BuiltinID == AArch64::BI__sys)
    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);

  if (BuiltinID == AArch64::BI__getReg)
    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31);

  if (BuiltinID == AArch64::BI__break)
    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);

  if (BuiltinID == AArch64::BI__hlt)
    return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff);

  if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall))
    return true;

  if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall))
    return true;

  if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall))
    return true;

  // For intrinsics which take an immediate value as part of the instruction,
  // range check them here.
  unsigned i = 0, l = 0, u = 0;
  switch (BuiltinID) {
  default: return false;
  case AArch64::BI__builtin_arm_dmb:
  case AArch64::BI__dmb:
  case AArch64::BI__builtin_arm_dsb:
  case AArch64::BI__dsb:
  case AArch64::BI__builtin_arm_isb:
  case AArch64::BI__isb:
    l = 0;
    u = 15;
    break;
  case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break;
  }

  return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l);
}

namespace {
struct IntrinToName {
  uint32_t Id;
  int32_t FullName;
  int32_t ShortName;
};
} // unnamed namespace

static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
                              ArrayRef<IntrinToName> Map,
                              const char *IntrinNames) {
  AliasName.consume_front("__arm_");
  const IntrinToName *It =
      llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) {
        return L.Id < Id;
      });
  if (It == Map.end() || It->Id != BuiltinID)
    return false;
  StringRef FullName(&IntrinNames[It->FullName]);
  if (AliasName == FullName)
    return true;
  if (It->ShortName == -1)
    return false;
  StringRef ShortName(&IntrinNames[It->ShortName]);
  return AliasName == ShortName;
}

bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) {
#include "clang/Basic/arm_mve_builtin_aliases.inc"
  // The included file defines:
  // - ArrayRef<IntrinToName> Map
  // - const char IntrinNames[]
  return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
}

bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
#include "clang/Basic/arm_cde_builtin_aliases.inc"
  return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
}

bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) {
  if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
    BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
  return BuiltinID >= AArch64::FirstSVEBuiltin &&
         BuiltinID <= AArch64::LastSVEBuiltin;
}

bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) {
  if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID))
    BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID);
  return BuiltinID >= AArch64::FirstSMEBuiltin &&
         BuiltinID <= AArch64::LastSMEBuiltin;
}

void SemaARM::handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL) {
  ASTContext &Context = getASTContext();
  if (!AL.isArgIdent(0)) {
    Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
        << AL << 1 << AANT_ArgumentIdentifier;
    return;
  }

  IdentifierInfo *Ident = AL.getArgAsIdent(0)->getIdentifierInfo();
  unsigned BuiltinID = Ident->getBuiltinID();
  StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();

  bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64();
  if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) &&
       !SmeAliasValid(BuiltinID, AliasName)) ||
      (!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) &&
       !CdeAliasValid(BuiltinID, AliasName))) {
    Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
    return;
  }

  D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident));
}

static bool checkNewAttrMutualExclusion(
    Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT,
    FunctionType::ArmStateValue CurrentState, StringRef StateName) {
  auto CheckForIncompatibleAttr =
      [&](FunctionType::ArmStateValue IncompatibleState,
          StringRef IncompatibleStateName) {
        if (CurrentState == IncompatibleState) {
          S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
              << (std::string("'__arm_new(\"") + StateName.str() + "\")'")
              << (std::string("'") + IncompatibleStateName.str() + "(\"" +
                  StateName.str() + "\")'")
              << true;
          AL.setInvalid();
        }
      };

  CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in");
  CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out");
  CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout");
  CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves");
  return AL.isInvalid();
}

void SemaARM::handleNewAttr(Decl *D, const ParsedAttr &AL) {
  if (!AL.getNumArgs()) {
    Diag(AL.getLoc(), diag::err_missing_arm_state) << AL;
    AL.setInvalid();
    return;
  }

  std::vector<StringRef> NewState;
  if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) {
    for (StringRef S : ExistingAttr->newArgs())
      NewState.push_back(S);
  }

  bool HasZA = false;
  bool HasZT0 = false;
  for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
    StringRef StateName;
    SourceLocation LiteralLoc;
    if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc))
      return;

    if (StateName == "za")
      HasZA = true;
    else if (StateName == "zt0")
      HasZT0 = true;
    else {
      Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName;
      AL.setInvalid();
      return;
    }

    if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates.
      NewState.push_back(StateName);
  }

  if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) {
    FunctionType::ArmStateValue ZAState =
        FunctionType::getArmZAState(FPT->getAArch64SMEAttributes());
    if (HasZA && ZAState != FunctionType::ARM_None &&
        checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za"))
      return;
    FunctionType::ArmStateValue ZT0State =
        FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes());
    if (HasZT0 && ZT0State != FunctionType::ARM_None &&
        checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0"))
      return;
  }

  D->dropAttr<ArmNewAttr>();
  D->addAttr(::new (getASTContext()) ArmNewAttr(
      getASTContext(), AL, NewState.data(), NewState.size()));
}

void SemaARM::handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL) {
  if (getLangOpts().CPlusPlus && !D->getDeclContext()->isExternCContext()) {
    Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
    return;
  }

  const auto *FD = cast<FunctionDecl>(D);
  if (!FD->isExternallyVisible()) {
    Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
    return;
  }

  D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL));
}

void SemaARM::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
  // Check the attribute arguments.
  if (AL.getNumArgs() > 1) {
    Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
    return;
  }

  StringRef Str;
  SourceLocation ArgLoc;

  if (AL.getNumArgs() == 0)
    Str = "";
  else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
    return;

  ARMInterruptAttr::InterruptType Kind;
  if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
    Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
        << AL << Str << ArgLoc;
    return;
  }

  if (!D->hasAttr<ARMSaveFPAttr>()) {
    const TargetInfo &TI = getASTContext().getTargetInfo();
    if (TI.hasFeature("vfp"))
      Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
  }

  D->addAttr(::new (getASTContext())
                 ARMInterruptAttr(getASTContext(), AL, Kind));
}

void SemaARM::handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL) {
  // Go ahead and add ARMSaveFPAttr because handleInterruptAttr() checks for
  // it when deciding to issue a diagnostic about clobbering floating point
  // registers, which ARMSaveFPAttr prevents.
  D->addAttr(::new (SemaRef.Context) ARMSaveFPAttr(SemaRef.Context, AL));
  SemaRef.ARM().handleInterruptAttr(D, AL);

  // If ARM().handleInterruptAttr() failed, remove ARMSaveFPAttr.
  if (!D->hasAttr<ARMInterruptAttr>()) {
    D->dropAttr<ARMSaveFPAttr>();
    return;
  }

  // If VFP not enabled, remove ARMSaveFPAttr but leave ARMInterruptAttr.
  bool VFP = SemaRef.Context.getTargetInfo().hasFeature("vfp");

  if (!VFP) {
    SemaRef.Diag(D->getLocation(), diag::warn_arm_interrupt_save_fp_without_vfp_unit);
    D->dropAttr<ARMSaveFPAttr>();
  }
}

// Check if the function definition uses any AArch64 SME features without
// having the '+sme' feature enabled and warn user if sme locally streaming
// function returns or uses arguments with VL-based types.
void SemaARM::CheckSMEFunctionDefAttributes(const FunctionDecl *FD) {
  const auto *Attr = FD->getAttr<ArmNewAttr>();
  bool UsesSM = FD->hasAttr<ArmLocallyStreamingAttr>();
  bool UsesZA = Attr && Attr->isNewZA();
  bool UsesZT0 = Attr && Attr->isNewZT0();

  if (UsesZA || UsesZT0) {
    if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
      FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
      if (EPI.AArch64SMEAttributes & FunctionType::SME_AgnosticZAStateMask)
        Diag(FD->getLocation(), diag::err_sme_unsupported_agnostic_new);
    }
  }

  if (FD->hasAttr<ArmLocallyStreamingAttr>()) {
    if (FD->getReturnType()->isSizelessVectorType())
      Diag(FD->getLocation(),
           diag::warn_sme_locally_streaming_has_vl_args_returns)
          << /*IsArg=*/false;
    if (llvm::any_of(FD->parameters(), [](ParmVarDecl *P) {
          return P->getOriginalType()->isSizelessVectorType();
        }))
      Diag(FD->getLocation(),
           diag::warn_sme_locally_streaming_has_vl_args_returns)
          << /*IsArg=*/true;
  }
  if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) {
    FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
    UsesSM |= EPI.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask;
    UsesZA |= FunctionType::getArmZAState(EPI.AArch64SMEAttributes) !=
              FunctionType::ARM_None;
    UsesZT0 |= FunctionType::getArmZT0State(EPI.AArch64SMEAttributes) !=
               FunctionType::ARM_None;
  }

  ASTContext &Context = getASTContext();
  if (UsesSM || UsesZA) {
    llvm::StringMap<bool> FeatureMap;
    Context.getFunctionFeatureMap(FeatureMap, FD);
    if (!FeatureMap.contains("sme")) {
      if (UsesSM)
        Diag(FD->getLocation(),
             diag::err_sme_definition_using_sm_in_non_sme_target);
      else
        Diag(FD->getLocation(),
             diag::err_sme_definition_using_za_in_non_sme_target);
    }
  }
  if (UsesZT0) {
    llvm::StringMap<bool> FeatureMap;
    Context.getFunctionFeatureMap(FeatureMap, FD);
    if (!FeatureMap.contains("sme2")) {
      Diag(FD->getLocation(),
           diag::err_sme_definition_using_zt0_in_non_sme2_target);
    }
  }
}

/// getSVETypeSize - Return SVE vector or predicate register size.
static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty,
                               bool IsStreaming) {
  assert(Ty->isSveVLSBuiltinType() && "Invalid SVE Type");
  uint64_t VScale = IsStreaming ? Context.getLangOpts().VScaleStreamingMin
                                : Context.getLangOpts().VScaleMin;
  if (Ty->getKind() == BuiltinType::SveBool ||
      Ty->getKind() == BuiltinType::SveCount)
    return (VScale * 128) / Context.getCharWidth();
  return VScale * 128;
}

bool SemaARM::areCompatibleSveTypes(QualType FirstType, QualType SecondType) {
  bool IsStreaming = false;
  if (getLangOpts().VScaleMin != getLangOpts().VScaleStreamingMin ||
      getLangOpts().VScaleMax != getLangOpts().VScaleStreamingMax) {
    if (const FunctionDecl *FD =
            SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
      // For streaming-compatible functions, we don't know vector length.
      if (const auto *T = FD->getType()->getAs<FunctionProtoType>()) {
        if (T->getAArch64SMEAttributes() &
            FunctionType::SME_PStateSMCompatibleMask)
          return false;
      }

      if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
        IsStreaming = true;
    }
  }

  auto IsValidCast = [&](QualType FirstType, QualType SecondType) {
    if (const auto *BT = FirstType->getAs<BuiltinType>()) {
      if (const auto *VT = SecondType->getAs<VectorType>()) {
        // Predicates have the same representation as uint8 so we also have to
        // check the kind to make these types incompatible.
        ASTContext &Context = getASTContext();
        if (VT->getVectorKind() == VectorKind::SveFixedLengthPredicate)
          return BT->getKind() == BuiltinType::SveBool;
        else if (VT->getVectorKind() == VectorKind::SveFixedLengthData)
          return VT->getElementType().getCanonicalType() ==
                 FirstType->getSveEltType(Context);
        else if (VT->getVectorKind() == VectorKind::Generic)
          return Context.getTypeSize(SecondType) ==
                     getSVETypeSize(Context, BT, IsStreaming) &&
                 Context.hasSameType(
                     VT->getElementType(),
                     Context.getBuiltinVectorTypeInfo(BT).ElementType);
      }
    }
    return false;
  };

  return IsValidCast(FirstType, SecondType) ||
         IsValidCast(SecondType, FirstType);
}

bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
                                       QualType SecondType) {
  bool IsStreaming = false;
  if (getLangOpts().VScaleMin != getLangOpts().VScaleStreamingMin ||
      getLangOpts().VScaleMax != getLangOpts().VScaleStreamingMax) {
    if (const FunctionDecl *FD =
            SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
      // For streaming-compatible functions, we don't know vector length.
      if (const auto *T = FD->getType()->getAs<FunctionProtoType>())
        if (T->getAArch64SMEAttributes() &
            FunctionType::SME_PStateSMCompatibleMask)
          return false;

      if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true))
        IsStreaming = true;
    }
  }

  auto IsLaxCompatible = [&](QualType FirstType, QualType SecondType) {
    const auto *BT = FirstType->getAs<BuiltinType>();
    if (!BT)
      return false;

    const auto *VecTy = SecondType->getAs<VectorType>();
    if (VecTy && (VecTy->getVectorKind() == VectorKind::SveFixedLengthData ||
                  VecTy->getVectorKind() == VectorKind::Generic)) {
      const LangOptions::LaxVectorConversionKind LVCKind =
          getLangOpts().getLaxVectorConversions();
      ASTContext &Context = getASTContext();

      // Can not convert between sve predicates and sve vectors because of
      // different size.
      if (BT->getKind() == BuiltinType::SveBool &&
          VecTy->getVectorKind() == VectorKind::SveFixedLengthData)
        return false;

      // If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion.
      // "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly
      // converts to VLAT and VLAT implicitly converts to GNUT."
      // ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and
      // predicates.
      if (VecTy->getVectorKind() == VectorKind::Generic &&
          Context.getTypeSize(SecondType) !=
              getSVETypeSize(Context, BT, IsStreaming))
        return false;

      // If -flax-vector-conversions=all is specified, the types are
      // certainly compatible.
      if (LVCKind == LangOptions::LaxVectorConversionKind::All)
        return true;

      // If -flax-vector-conversions=integer is specified, the types are
      // compatible if the elements are integer types.
      if (LVCKind == LangOptions::LaxVectorConversionKind::Integer)
        return VecTy->getElementType().getCanonicalType()->isIntegerType() &&
               FirstType->getSveEltType(Context)->isIntegerType();
    }

    return false;
  };

  return IsLaxCompatible(FirstType, SecondType) ||
         IsLaxCompatible(SecondType, FirstType);
}

bool SemaARM::checkTargetVersionAttr(const StringRef Param,
                                     const SourceLocation Loc) {
  using namespace DiagAttrParams;

  llvm::SmallVector<StringRef, 8> Features;
  Param.split(Features, '+');
  for (StringRef Feat : Features) {
    Feat = Feat.trim();
    if (Feat == "default")
      continue;
    if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
      return Diag(Loc, diag::warn_unsupported_target_attribute)
             << Unsupported << None << Feat << TargetVersion;
  }
  return false;
}

bool SemaARM::checkTargetClonesAttr(
    SmallVectorImpl<StringRef> &Params, SmallVectorImpl<SourceLocation> &Locs,
    SmallVectorImpl<SmallString<64>> &NewParams) {
  using namespace DiagAttrParams;

  if (!getASTContext().getTargetInfo().hasFeature("fmv"))
    return true;

  assert(Params.size() == Locs.size() &&
         "Mismatch between number of string parameters and locations");

  bool HasDefault = false;
  bool HasNonDefault = false;
  for (unsigned I = 0, E = Params.size(); I < E; ++I) {
    const StringRef Param = Params[I].trim();
    const SourceLocation &Loc = Locs[I];

    if (Param.empty())
      return Diag(Loc, diag::warn_unsupported_target_attribute)
             << Unsupported << None << "" << TargetClones;

    if (Param == "default") {
      if (HasDefault)
        Diag(Loc, diag::warn_target_clone_duplicate_options);
      else {
        NewParams.push_back(Param);
        HasDefault = true;
      }
      continue;
    }

    bool HasCodeGenImpact = false;
    llvm::SmallVector<StringRef, 8> Features;
    llvm::SmallVector<StringRef, 8> ValidFeatures;
    Param.split(Features, '+');
    for (StringRef Feat : Features) {
      Feat = Feat.trim();
      if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
        Diag(Loc, diag::warn_unsupported_target_attribute)
            << Unsupported << None << Feat << TargetClones;
        continue;
      }
      if (getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat))
        HasCodeGenImpact = true;
      ValidFeatures.push_back(Feat);
    }

    // Ignore features that don't impact code generation.
    if (!HasCodeGenImpact) {
      Diag(Loc, diag::warn_target_clone_no_impact_options);
      continue;
    }

    if (ValidFeatures.empty())
      continue;

    // Canonicalize attribute parameter.
    llvm::sort(ValidFeatures);
    SmallString<64> NewParam(llvm::join(ValidFeatures, "+"));
    if (llvm::is_contained(NewParams, NewParam)) {
      Diag(Loc, diag::warn_target_clone_duplicate_options);
      continue;
    }

    // Valid non-default argument.
    NewParams.push_back(NewParam);
    HasNonDefault = true;
  }
  if (!HasNonDefault)
    return true;

  return false;
}

} // namespace clang
