aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp3018
1 files changed, 27 insertions, 2991 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7ce1486..300af022 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -61,9 +61,19 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaAMDGPU.h"
+#include "clang/Sema/SemaARM.h"
+#include "clang/Sema/SemaBPF.h"
+#include "clang/Sema/SemaHexagon.h"
#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/SemaLoongArch.h"
+#include "clang/Sema/SemaMIPS.h"
+#include "clang/Sema/SemaNVPTX.h"
#include "clang/Sema/SemaObjC.h"
+#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
+#include "clang/Sema/SemaSystemZ.h"
+#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
@@ -2259,23 +2269,23 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- return CheckARMBuiltinFunctionCall(TI, BuiltinID, TheCall);
+ return ARM().CheckARMBuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
- return CheckAArch64BuiltinFunctionCall(TI, BuiltinID, TheCall);
+ return ARM().CheckAArch64BuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::bpfeb:
case llvm::Triple::bpfel:
- return CheckBPFBuiltinFunctionCall(BuiltinID, TheCall);
+ return BPF().CheckBPFBuiltinFunctionCall(BuiltinID, TheCall);
case llvm::Triple::hexagon:
- return CheckHexagonBuiltinFunctionCall(BuiltinID, TheCall);
+ return Hexagon().CheckHexagonBuiltinFunctionCall(BuiltinID, TheCall);
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
- return CheckMipsBuiltinFunctionCall(TI, BuiltinID, TheCall);
+ return MIPS().CheckMipsBuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::systemz:
- return CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall);
+ return SystemZ().CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall);
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return X86().CheckBuiltinFunctionCall(TI, BuiltinID, TheCall);
@@ -2283,21 +2293,22 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case llvm::Triple::ppcle:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
- return CheckPPCBuiltinFunctionCall(TI, BuiltinID, TheCall);
+ return PPC().CheckPPCBuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::amdgcn:
- return CheckAMDGCNBuiltinFunctionCall(BuiltinID, TheCall);
+ return AMDGPU().CheckAMDGCNBuiltinFunctionCall(BuiltinID, TheCall);
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
return RISCV().CheckBuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::loongarch32:
case llvm::Triple::loongarch64:
- return CheckLoongArchBuiltinFunctionCall(TI, BuiltinID, TheCall);
+ return LoongArch().CheckLoongArchBuiltinFunctionCall(TI, BuiltinID,
+ TheCall);
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
- return CheckWebAssemblyBuiltinFunctionCall(TI, BuiltinID, TheCall);
+ return Wasm().CheckWebAssemblyBuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
- return CheckNVPTXBuiltinFunctionCall(TI, BuiltinID, TheCall);
+ return NVPTX().CheckNVPTXBuiltinFunctionCall(TI, BuiltinID, TheCall);
}
}
@@ -3287,1982 +3298,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
return TheCallResult;
}
-// Get the valid immediate range for the specified NEON type code.
-static unsigned RFT(unsigned t, bool shift = false, bool ForceQuad = false) {
- NeonTypeFlags Type(t);
- int IsQuad = ForceQuad ? true : Type.isQuad();
- switch (Type.getEltType()) {
- case NeonTypeFlags::Int8:
- case NeonTypeFlags::Poly8:
- return shift ? 7 : (8 << IsQuad) - 1;
- case NeonTypeFlags::Int16:
- case NeonTypeFlags::Poly16:
- return shift ? 15 : (4 << IsQuad) - 1;
- case NeonTypeFlags::Int32:
- return shift ? 31 : (2 << IsQuad) - 1;
- case NeonTypeFlags::Int64:
- case NeonTypeFlags::Poly64:
- return shift ? 63 : (1 << IsQuad) - 1;
- case NeonTypeFlags::Poly128:
- return shift ? 127 : (1 << IsQuad) - 1;
- case NeonTypeFlags::Float16:
- assert(!shift && "cannot shift float types!");
- return (4 << IsQuad) - 1;
- case NeonTypeFlags::Float32:
- assert(!shift && "cannot shift float types!");
- return (2 << IsQuad) - 1;
- case NeonTypeFlags::Float64:
- assert(!shift && "cannot shift float types!");
- return (1 << IsQuad) - 1;
- case NeonTypeFlags::BFloat16:
- assert(!shift && "cannot shift float types!");
- return (4 << IsQuad) - 1;
- }
- llvm_unreachable("Invalid NeonTypeFlag!");
-}
-
-/// 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;
- }
- llvm_unreachable("Invalid NeonTypeFlag!");
-}
-
-enum ArmStreamingType {
- ArmNonStreaming,
- ArmStreaming,
- ArmStreamingCompatible,
- ArmStreamingOrSVE2p1
-};
-
-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 Sema::ParseSVEImmChecks(
- CallExpr *TheCall, SmallVector<std::tuple<int, int, int>, 3> &ImmChecks) {
- // Perform all the immediate checks for this builtin call.
- bool HasError = false;
- for (auto &I : ImmChecks) {
- int ArgNum, CheckTy, ElementSizeInBits;
- std::tie(ArgNum, CheckTy, ElementSizeInBits) = I;
-
- typedef bool (*OptionSetCheckFnTy)(int64_t Value);
-
- // Function that checks whether the operand (ArgNum) is an immediate
- // that is one of the predefined values.
- auto CheckImmediateInSet = [&](OptionSetCheckFnTy CheckImm,
- int ErrDiag) -> bool {
- // We can't check the value of a dependent argument.
- Expr *Arg = TheCall->getArg(ArgNum);
- if (Arg->isTypeDependent() || Arg->isValueDependent())
- return false;
-
- // Check constant-ness first.
- llvm::APSInt Imm;
- if (BuiltinConstantArg(TheCall, ArgNum, Imm))
- return true;
-
- if (!CheckImm(Imm.getSExtValue()))
- return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
- return false;
- };
-
- switch ((SVETypeFlags::ImmCheckType)CheckTy) {
- case SVETypeFlags::ImmCheck0_31:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 31))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck0_13:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 13))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck1_16:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 1, 16))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck0_7:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 7))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck1_1:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 1, 1))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck1_3:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 1, 3))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck1_7:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 1, 7))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckExtract:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0,
- (2048 / ElementSizeInBits) - 1))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckShiftRight:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 1, ElementSizeInBits))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckShiftRightNarrow:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 1, ElementSizeInBits / 2))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckShiftLeft:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, ElementSizeInBits - 1))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckLaneIndex:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0,
- (128 / (1 * ElementSizeInBits)) - 1))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckLaneIndexCompRotate:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0,
- (128 / (2 * ElementSizeInBits)) - 1))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckLaneIndexDot:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0,
- (128 / (4 * ElementSizeInBits)) - 1))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckComplexRot90_270:
- if (CheckImmediateInSet([](int64_t V) { return V == 90 || V == 270; },
- diag::err_rotation_argument_to_cadd))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheckComplexRotAll90:
- if (CheckImmediateInSet(
- [](int64_t V) {
- return V == 0 || V == 90 || V == 180 || V == 270;
- },
- diag::err_rotation_argument_to_cmla))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck0_1:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 1))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck0_2:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 2))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck0_3:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 3))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck0_0:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 0))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck0_15:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 15))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck0_255:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 0, 255))
- HasError = true;
- break;
- case SVETypeFlags::ImmCheck2_4_Mul2:
- if (BuiltinConstantArgRange(TheCall, ArgNum, 2, 4) ||
- BuiltinConstantArgMultiple(TheCall, ArgNum, 2))
- HasError = true;
- break;
- }
- }
-
- return HasError;
-}
-
-static ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) {
- if (FD->hasAttr<ArmLocallyStreamingAttr>())
- return ArmStreaming;
- if (const Type *Ty = FD->getType().getTypePtrOrNull()) {
- if (const auto *FPT = Ty->getAs<FunctionProtoType>()) {
- if (FPT->getAArch64SMEAttributes() &
- FunctionType::SME_PStateSMEnabledMask)
- return ArmStreaming;
- if (FPT->getAArch64SMEAttributes() &
- FunctionType::SME_PStateSMCompatibleMask)
- return ArmStreamingCompatible;
- }
- }
- return ArmNonStreaming;
-}
-
-static void checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
- const FunctionDecl *FD,
- ArmStreamingType BuiltinType) {
- ArmStreamingType FnType = getArmStreamingFnType(FD);
- if (BuiltinType == ArmStreamingOrSVE2p1) {
- // Check intrinsics that are available in [sve2p1 or sme/sme2].
- llvm::StringMap<bool> CallerFeatureMap;
- S.Context.getFunctionFeatureMap(CallerFeatureMap, FD);
- if (Builtin::evaluateRequiredTargetFeatures("sve2p1", CallerFeatureMap))
- BuiltinType = ArmStreamingCompatible;
- else
- BuiltinType = ArmStreaming;
- }
-
- if (FnType == ArmStreaming && BuiltinType == ArmNonStreaming)
- S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
- << TheCall->getSourceRange() << "streaming";
- else if (FnType == ArmNonStreaming && BuiltinType == ArmStreaming)
- S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
- << TheCall->getSourceRange() << "non-streaming";
- else if (FnType == ArmStreamingCompatible &&
- BuiltinType != ArmStreamingCompatible)
- S.Diag(TheCall->getBeginLoc(), diag::warn_attribute_arm_sm_incompat_builtin)
- << TheCall->getSourceRange() << "streaming compatible";
-}
-
-static bool hasArmZAState(const FunctionDecl *FD) {
- const auto *T = FD->getType()->getAs<FunctionProtoType>();
- return (T && FunctionType::getArmZAState(T->getAArch64SMEAttributes()) !=
- FunctionType::ARM_None) ||
- (FD->hasAttr<ArmNewAttr>() && FD->getAttr<ArmNewAttr>()->isNewZA());
-}
-
-static bool hasArmZT0State(const FunctionDecl *FD) {
- const auto *T = FD->getType()->getAs<FunctionProtoType>();
- return (T && FunctionType::getArmZT0State(T->getAArch64SMEAttributes()) !=
- FunctionType::ARM_None) ||
- (FD->hasAttr<ArmNewAttr>() && FD->getAttr<ArmNewAttr>()->isNewZT0());
-}
-
-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 Sema::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
- if (const FunctionDecl *FD = getCurFunctionDecl()) {
- 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(*this, TheCall, FD, *BuiltinType);
-
- 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 ParseSVEImmChecks(TheCall, ImmChecks);
-}
-
-bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
- if (const FunctionDecl *FD = getCurFunctionDecl()) {
- 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(*this, TheCall, FD, *BuiltinType);
- }
- // 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 ParseSVEImmChecks(TheCall, ImmChecks);
-}
-
-bool Sema::CheckNeonBuiltinFunctionCall(const TargetInfo &TI,
- unsigned BuiltinID, CallExpr *TheCall) {
- if (const FunctionDecl *FD = getCurFunctionDecl()) {
-
- switch (BuiltinID) {
- default:
- break;
-#define GET_NEON_BUILTINS
-#define TARGET_BUILTIN(id, ...) case NEON::BI##id:
-#define BUILTIN(id, ...) case NEON::BI##id:
-#include "clang/Basic/arm_neon.inc"
- checkArmStreamingBuiltin(*this, TheCall, FD, ArmNonStreaming);
- break;
-#undef TARGET_BUILTIN
-#undef BUILTIN
-#undef GET_NEON_BUILTINS
- }
- }
-
- llvm::APSInt Result;
- uint64_t mask = 0;
- unsigned TV = 0;
- int PtrArgNum = -1;
- bool HasConstPtr = false;
- switch (BuiltinID) {
-#define GET_NEON_OVERLOAD_CHECK
-#include "clang/Basic/arm_neon.inc"
-#include "clang/Basic/arm_fp16.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 (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 = 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), Context, IsPolyUnsigned, IsInt64Long);
- if (HasConstPtr)
- EltTy = EltTy.withConst();
- QualType LHSTy = Context.getPointerType(EltTy);
- AssignConvertType ConvTy;
- ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
- if (RHS.isInvalid())
- return true;
- if (DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy, RHSTy,
- RHS.get(), AA_Assigning))
- return true;
- }
-
- // For NEON 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;
- #define GET_NEON_IMMEDIATE_CHECK
- #include "clang/Basic/arm_neon.inc"
- #include "clang/Basic/arm_fp16.inc"
- #undef GET_NEON_IMMEDIATE_CHECK
- }
-
- return BuiltinConstantArgRange(TheCall, i, l, u + l);
-}
-
-bool Sema::CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
- switch (BuiltinID) {
- default:
- return false;
- #include "clang/Basic/arm_mve_builtin_sema.inc"
- }
-}
-
-bool Sema::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 Sema::CheckARMCoprocessorImmediate(const TargetInfo &TI,
- const Expr *CoprocArg, bool WantCDE) {
- if (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 Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
- unsigned MaxWidth) {
- 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;
-
- DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
-
- // Ensure that we have the proper number of arguments.
- if (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 = 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)) {
- CastNeeded = CK_BitCast;
- Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers)
- << PointerArg->getType() << Context.getPointerType(AddrType)
- << AA_Passing << PointerArg->getSourceRange();
- }
-
- // Finally, do the cast and replace the argument with the corrected version.
- AddrType = Context.getPointerType(AddrType);
- PointerArgRes = 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;
- }
-
- // But ARM doesn't have instructions to deal with 128-bit versions.
- if (Context.getTypeSize(ValType) > MaxWidth) {
- assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate");
- Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size)
- << PointerArg->getType() << PointerArg->getSourceRange();
- return true;
- }
-
- 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 = 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 Sema::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(BuiltinID, TheCall, 64);
- }
-
- if (BuiltinID == ARM::BI__builtin_arm_prefetch) {
- return BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
- 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 BuiltinConstantArgRange(TheCall, 1, 1, 32);
- case ARM::BI__builtin_arm_usat:
- return BuiltinConstantArgRange(TheCall, 1, 0, 31);
- case ARM::BI__builtin_arm_ssat16:
- return BuiltinConstantArgRange(TheCall, 1, 1, 16);
- case ARM::BI__builtin_arm_usat16:
- return BuiltinConstantArgRange(TheCall, 1, 0, 15);
- case ARM::BI__builtin_arm_vcvtr_f:
- case ARM::BI__builtin_arm_vcvtr_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 1);
- case ARM::BI__builtin_arm_dmb:
- case ARM::BI__builtin_arm_dsb:
- case ARM::BI__builtin_arm_isb:
- case ARM::BI__builtin_arm_dbg:
- return 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 BuiltinConstantArgRange(TheCall, 0, 0, 15) ||
- CheckARMCoprocessorImmediate(TI, TheCall->getArg(0),
- /*WantCDE*/ false);
- }
-}
-
-bool Sema::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(BuiltinID, TheCall, 128);
- }
-
- if (BuiltinID == AArch64::BI__builtin_arm_prefetch) {
- return BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
- BuiltinConstantArgRange(TheCall, 2, 0, 3) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 1) ||
- 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)
- return BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff);
-
- if (BuiltinID == AArch64::BI__getReg)
- return BuiltinConstantArgRange(TheCall, 0, 0, 31);
-
- if (BuiltinID == AArch64::BI__break)
- return 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__builtin_arm_dsb:
- case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break;
- case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break;
- }
-
- return BuiltinConstantArgRange(TheCall, i, l, u + l);
-}
-
-static bool isValidBPFPreserveFieldInfoArg(Expr *Arg) {
- if (Arg->getType()->getAsPlaceholderType())
- return false;
-
- // The first argument needs to be a record field access.
- // If it is an array element access, we delay decision
- // to BPF backend to check whether the access is a
- // field access or not.
- return (Arg->IgnoreParens()->getObjectKind() == OK_BitField ||
- isa<MemberExpr>(Arg->IgnoreParens()) ||
- isa<ArraySubscriptExpr>(Arg->IgnoreParens()));
-}
-
-static bool isValidBPFPreserveTypeInfoArg(Expr *Arg) {
- QualType ArgType = Arg->getType();
- if (ArgType->getAsPlaceholderType())
- return false;
-
- // for TYPE_EXISTENCE/TYPE_MATCH/TYPE_SIZEOF reloc type
- // format:
- // 1. __builtin_preserve_type_info(*(<type> *)0, flag);
- // 2. <type> var;
- // __builtin_preserve_type_info(var, flag);
- if (!isa<DeclRefExpr>(Arg->IgnoreParens()) &&
- !isa<UnaryOperator>(Arg->IgnoreParens()))
- return false;
-
- // Typedef type.
- if (ArgType->getAs<TypedefType>())
- return true;
-
- // Record type or Enum type.
- const Type *Ty = ArgType->getUnqualifiedDesugaredType();
- if (const auto *RT = Ty->getAs<RecordType>()) {
- if (!RT->getDecl()->getDeclName().isEmpty())
- return true;
- } else if (const auto *ET = Ty->getAs<EnumType>()) {
- if (!ET->getDecl()->getDeclName().isEmpty())
- return true;
- }
-
- return false;
-}
-
-static bool isValidBPFPreserveEnumValueArg(Expr *Arg) {
- QualType ArgType = Arg->getType();
- if (ArgType->getAsPlaceholderType())
- return false;
-
- // for ENUM_VALUE_EXISTENCE/ENUM_VALUE reloc type
- // format:
- // __builtin_preserve_enum_value(*(<enum_type> *)<enum_value>,
- // flag);
- const auto *UO = dyn_cast<UnaryOperator>(Arg->IgnoreParens());
- if (!UO)
- return false;
-
- const auto *CE = dyn_cast<CStyleCastExpr>(UO->getSubExpr());
- if (!CE)
- return false;
- if (CE->getCastKind() != CK_IntegralToPointer &&
- CE->getCastKind() != CK_NullToPointer)
- return false;
-
- // The integer must be from an EnumConstantDecl.
- const auto *DR = dyn_cast<DeclRefExpr>(CE->getSubExpr());
- if (!DR)
- return false;
-
- const EnumConstantDecl *Enumerator =
- dyn_cast<EnumConstantDecl>(DR->getDecl());
- if (!Enumerator)
- return false;
-
- // The type must be EnumType.
- const Type *Ty = ArgType->getUnqualifiedDesugaredType();
- const auto *ET = Ty->getAs<EnumType>();
- if (!ET)
- return false;
-
- // The enum value must be supported.
- return llvm::is_contained(ET->getDecl()->enumerators(), Enumerator);
-}
-
-bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall) {
- assert((BuiltinID == BPF::BI__builtin_preserve_field_info ||
- BuiltinID == BPF::BI__builtin_btf_type_id ||
- BuiltinID == BPF::BI__builtin_preserve_type_info ||
- BuiltinID == BPF::BI__builtin_preserve_enum_value) &&
- "unexpected BPF builtin");
-
- if (checkArgCount(TheCall, 2))
- return true;
-
- // The second argument needs to be a constant int
- Expr *Arg = TheCall->getArg(1);
- std::optional<llvm::APSInt> Value = Arg->getIntegerConstantExpr(Context);
- diag::kind kind;
- if (!Value) {
- if (BuiltinID == BPF::BI__builtin_preserve_field_info)
- kind = diag::err_preserve_field_info_not_const;
- else if (BuiltinID == BPF::BI__builtin_btf_type_id)
- kind = diag::err_btf_type_id_not_const;
- else if (BuiltinID == BPF::BI__builtin_preserve_type_info)
- kind = diag::err_preserve_type_info_not_const;
- else
- kind = diag::err_preserve_enum_value_not_const;
- Diag(Arg->getBeginLoc(), kind) << 2 << Arg->getSourceRange();
- return true;
- }
-
- // The first argument
- Arg = TheCall->getArg(0);
- bool InvalidArg = false;
- bool ReturnUnsignedInt = true;
- if (BuiltinID == BPF::BI__builtin_preserve_field_info) {
- if (!isValidBPFPreserveFieldInfoArg(Arg)) {
- InvalidArg = true;
- kind = diag::err_preserve_field_info_not_field;
- }
- } else if (BuiltinID == BPF::BI__builtin_preserve_type_info) {
- if (!isValidBPFPreserveTypeInfoArg(Arg)) {
- InvalidArg = true;
- kind = diag::err_preserve_type_info_invalid;
- }
- } else if (BuiltinID == BPF::BI__builtin_preserve_enum_value) {
- if (!isValidBPFPreserveEnumValueArg(Arg)) {
- InvalidArg = true;
- kind = diag::err_preserve_enum_value_invalid;
- }
- ReturnUnsignedInt = false;
- } else if (BuiltinID == BPF::BI__builtin_btf_type_id) {
- ReturnUnsignedInt = false;
- }
-
- if (InvalidArg) {
- Diag(Arg->getBeginLoc(), kind) << 1 << Arg->getSourceRange();
- return true;
- }
-
- if (ReturnUnsignedInt)
- TheCall->setType(Context.UnsignedIntTy);
- else
- TheCall->setType(Context.UnsignedLongTy);
- return false;
-}
-
-bool Sema::CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) {
- struct ArgInfo {
- uint8_t OpNum;
- bool IsSigned;
- uint8_t BitWidth;
- uint8_t Align;
- };
- struct BuiltinInfo {
- unsigned BuiltinID;
- ArgInfo Infos[2];
- };
-
- static BuiltinInfo Infos[] = {
- { Hexagon::BI__builtin_circ_ldd, {{ 3, true, 4, 3 }} },
- { Hexagon::BI__builtin_circ_ldw, {{ 3, true, 4, 2 }} },
- { Hexagon::BI__builtin_circ_ldh, {{ 3, true, 4, 1 }} },
- { Hexagon::BI__builtin_circ_lduh, {{ 3, true, 4, 1 }} },
- { Hexagon::BI__builtin_circ_ldb, {{ 3, true, 4, 0 }} },
- { Hexagon::BI__builtin_circ_ldub, {{ 3, true, 4, 0 }} },
- { Hexagon::BI__builtin_circ_std, {{ 3, true, 4, 3 }} },
- { Hexagon::BI__builtin_circ_stw, {{ 3, true, 4, 2 }} },
- { Hexagon::BI__builtin_circ_sth, {{ 3, true, 4, 1 }} },
- { Hexagon::BI__builtin_circ_sthhi, {{ 3, true, 4, 1 }} },
- { Hexagon::BI__builtin_circ_stb, {{ 3, true, 4, 0 }} },
-
- { Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci, {{ 1, true, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci, {{ 1, true, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_L2_loadruh_pci, {{ 1, true, 4, 1 }} },
- { Hexagon::BI__builtin_HEXAGON_L2_loadrh_pci, {{ 1, true, 4, 1 }} },
- { Hexagon::BI__builtin_HEXAGON_L2_loadri_pci, {{ 1, true, 4, 2 }} },
- { Hexagon::BI__builtin_HEXAGON_L2_loadrd_pci, {{ 1, true, 4, 3 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_storerb_pci, {{ 1, true, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_storerh_pci, {{ 1, true, 4, 1 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_storerf_pci, {{ 1, true, 4, 1 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_storeri_pci, {{ 1, true, 4, 2 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_storerd_pci, {{ 1, true, 4, 3 }} },
-
- { Hexagon::BI__builtin_HEXAGON_A2_combineii, {{ 1, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A2_tfrih, {{ 1, false, 16, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A2_tfril, {{ 1, false, 16, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A2_tfrpi, {{ 0, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_bitspliti, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_cmpbeqi, {{ 1, false, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_cmpbgti, {{ 1, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_cround_ri, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_round_ri, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_round_ri_sat, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmpbeqi, {{ 1, false, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmpbgti, {{ 1, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmpbgtui, {{ 1, false, 7, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmpheqi, {{ 1, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmphgti, {{ 1, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmphgtui, {{ 1, false, 7, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmpweqi, {{ 1, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmpwgti, {{ 1, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_A4_vcmpwgtui, {{ 1, false, 7, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_C2_bitsclri, {{ 1, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_C2_muxii, {{ 2, true, 8, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_C4_nbitsclri, {{ 1, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_F2_dfclass, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_F2_dfimm_n, {{ 0, false, 10, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_F2_dfimm_p, {{ 0, false, 10, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_F2_sfclass, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_F2_sfimm_n, {{ 0, false, 10, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_F2_sfimm_p, {{ 0, false, 10, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_M4_mpyri_addi, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_M4_mpyri_addr_u2, {{ 1, false, 6, 2 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_addasl_rrri, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_acc, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_and, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p, {{ 1, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_nac, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_or, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_p_xacc, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_acc, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_and, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_nac, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_or, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_sat, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_r_xacc, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_vh, {{ 1, false, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asl_i_vw, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_acc, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_and, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p, {{ 1, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_nac, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_or, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax,
- {{ 1, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_p_rnd, {{ 1, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_acc, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_and, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_nac, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_or, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax,
- {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_r_rnd, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_svw_trun, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_vh, {{ 1, false, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_asr_i_vw, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_clrbit_i, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_extractu, {{ 1, false, 5, 0 },
- { 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_extractup, {{ 1, false, 6, 0 },
- { 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_insert, {{ 2, false, 5, 0 },
- { 3, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_insertp, {{ 2, false, 6, 0 },
- { 3, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_acc, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_and, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p, {{ 1, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_nac, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_or, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_p_xacc, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_acc, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_and, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_nac, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_or, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_r_xacc, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_vh, {{ 1, false, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_lsr_i_vw, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_setbit_i, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_tableidxb_goodsyntax,
- {{ 2, false, 4, 0 },
- { 3, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_tableidxd_goodsyntax,
- {{ 2, false, 4, 0 },
- { 3, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_tableidxh_goodsyntax,
- {{ 2, false, 4, 0 },
- { 3, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_tableidxw_goodsyntax,
- {{ 2, false, 4, 0 },
- { 3, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_togglebit_i, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_tstbit_i, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_valignib, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S2_vspliceib, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_addi_asl_ri, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_addi_lsr_ri, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_andi_asl_ri, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_andi_lsr_ri, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_clbaddi, {{ 1, true , 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_clbpaddi, {{ 1, true, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_extract, {{ 1, false, 5, 0 },
- { 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_extractp, {{ 1, false, 6, 0 },
- { 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_lsli, {{ 0, true, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_ntstbit_i, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_ori_asl_ri, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_ori_lsr_ri, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_subi_asl_ri, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_subi_lsr_ri, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_vrcrotate_acc, {{ 3, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S4_vrcrotate, {{ 2, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax,
- {{ 1, false, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S5_asrhub_sat, {{ 1, false, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S5_vasrhrnd_goodsyntax,
- {{ 1, false, 4, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, {{ 1, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, {{ 2, false, 6, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, {{ 1, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, {{ 2, false, 5, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_valignbi, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi, {{ 2, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_128B, {{ 2, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc, {{ 3, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpybusi_acc_128B,
- {{ 3, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi, {{ 2, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_128B, {{ 2, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc, {{ 3, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrmpyubi_acc_128B,
- {{ 3, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi, {{ 2, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_128B, {{ 2, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc, {{ 3, false, 1, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vrsadubi_acc_128B,
- {{ 3, false, 1, 0 }} },
-
- { Hexagon::BI__builtin_HEXAGON_V6_v6mpyhubs10, {{ 2, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_v6mpyhubs10_128B,
- {{ 2, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_v6mpyhubs10_vxx,
- {{ 3, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_v6mpyhubs10_vxx_128B,
- {{ 3, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_v6mpyvubs10, {{ 2, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_v6mpyvubs10_128B,
- {{ 2, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_v6mpyvubs10_vxx,
- {{ 3, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_v6mpyvubs10_vxx_128B,
- {{ 3, false, 2, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi_128B, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci, {{ 3, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci_128B,
- {{ 3, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi_128B, {{ 2, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci, {{ 3, false, 3, 0 }} },
- { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci_128B,
- {{ 3, false, 3, 0 }} },
- };
-
- // Use a dynamically initialized static to sort the table exactly once on
- // first run.
- static const bool SortOnce =
- (llvm::sort(Infos,
- [](const BuiltinInfo &LHS, const BuiltinInfo &RHS) {
- return LHS.BuiltinID < RHS.BuiltinID;
- }),
- true);
- (void)SortOnce;
-
- const BuiltinInfo *F = llvm::partition_point(
- Infos, [=](const BuiltinInfo &BI) { return BI.BuiltinID < BuiltinID; });
- if (F == std::end(Infos) || F->BuiltinID != BuiltinID)
- return false;
-
- bool Error = false;
-
- for (const ArgInfo &A : F->Infos) {
- // Ignore empty ArgInfo elements.
- if (A.BitWidth == 0)
- continue;
-
- int32_t Min = A.IsSigned ? -(1 << (A.BitWidth - 1)) : 0;
- int32_t Max = (1 << (A.IsSigned ? A.BitWidth - 1 : A.BitWidth)) - 1;
- if (!A.Align) {
- Error |= BuiltinConstantArgRange(TheCall, A.OpNum, Min, Max);
- } else {
- unsigned M = 1 << A.Align;
- Min *= M;
- Max *= M;
- Error |= BuiltinConstantArgRange(TheCall, A.OpNum, Min, Max);
- Error |= BuiltinConstantArgMultiple(TheCall, A.OpNum, M);
- }
- }
- return Error;
-}
-
-bool Sema::CheckHexagonBuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall) {
- return CheckHexagonBuiltinArgument(BuiltinID, TheCall);
-}
-
-bool Sema::CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
- unsigned BuiltinID,
- CallExpr *TheCall) {
- switch (BuiltinID) {
- default:
- break;
- // Basic intrinsics.
- case LoongArch::BI__builtin_loongarch_cacop_d:
- case LoongArch::BI__builtin_loongarch_cacop_w: {
- BuiltinConstantArgRange(TheCall, 0, 0, llvm::maxUIntN(5));
- BuiltinConstantArgRange(TheCall, 2, llvm::minIntN(12), llvm::maxIntN(12));
- break;
- }
- case LoongArch::BI__builtin_loongarch_break:
- case LoongArch::BI__builtin_loongarch_dbar:
- case LoongArch::BI__builtin_loongarch_ibar:
- case LoongArch::BI__builtin_loongarch_syscall:
- // Check if immediate is in [0, 32767].
- return BuiltinConstantArgRange(TheCall, 0, 0, 32767);
- case LoongArch::BI__builtin_loongarch_csrrd_w:
- case LoongArch::BI__builtin_loongarch_csrrd_d:
- return BuiltinConstantArgRange(TheCall, 0, 0, 16383);
- case LoongArch::BI__builtin_loongarch_csrwr_w:
- case LoongArch::BI__builtin_loongarch_csrwr_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 16383);
- case LoongArch::BI__builtin_loongarch_csrxchg_w:
- case LoongArch::BI__builtin_loongarch_csrxchg_d:
- return BuiltinConstantArgRange(TheCall, 2, 0, 16383);
- case LoongArch::BI__builtin_loongarch_lddir_d:
- case LoongArch::BI__builtin_loongarch_ldpte_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 31);
- case LoongArch::BI__builtin_loongarch_movfcsr2gr:
- case LoongArch::BI__builtin_loongarch_movgr2fcsr:
- return BuiltinConstantArgRange(TheCall, 0, 0, llvm::maxUIntN(2));
-
- // LSX intrinsics.
- case LoongArch::BI__builtin_lsx_vbitclri_b:
- case LoongArch::BI__builtin_lsx_vbitrevi_b:
- case LoongArch::BI__builtin_lsx_vbitseti_b:
- case LoongArch::BI__builtin_lsx_vsat_b:
- case LoongArch::BI__builtin_lsx_vsat_bu:
- case LoongArch::BI__builtin_lsx_vslli_b:
- case LoongArch::BI__builtin_lsx_vsrai_b:
- case LoongArch::BI__builtin_lsx_vsrari_b:
- case LoongArch::BI__builtin_lsx_vsrli_b:
- case LoongArch::BI__builtin_lsx_vsllwil_h_b:
- case LoongArch::BI__builtin_lsx_vsllwil_hu_bu:
- case LoongArch::BI__builtin_lsx_vrotri_b:
- case LoongArch::BI__builtin_lsx_vsrlri_b:
- return BuiltinConstantArgRange(TheCall, 1, 0, 7);
- case LoongArch::BI__builtin_lsx_vbitclri_h:
- case LoongArch::BI__builtin_lsx_vbitrevi_h:
- case LoongArch::BI__builtin_lsx_vbitseti_h:
- case LoongArch::BI__builtin_lsx_vsat_h:
- case LoongArch::BI__builtin_lsx_vsat_hu:
- case LoongArch::BI__builtin_lsx_vslli_h:
- case LoongArch::BI__builtin_lsx_vsrai_h:
- case LoongArch::BI__builtin_lsx_vsrari_h:
- case LoongArch::BI__builtin_lsx_vsrli_h:
- case LoongArch::BI__builtin_lsx_vsllwil_w_h:
- case LoongArch::BI__builtin_lsx_vsllwil_wu_hu:
- case LoongArch::BI__builtin_lsx_vrotri_h:
- case LoongArch::BI__builtin_lsx_vsrlri_h:
- return BuiltinConstantArgRange(TheCall, 1, 0, 15);
- case LoongArch::BI__builtin_lsx_vssrarni_b_h:
- case LoongArch::BI__builtin_lsx_vssrarni_bu_h:
- case LoongArch::BI__builtin_lsx_vssrani_b_h:
- case LoongArch::BI__builtin_lsx_vssrani_bu_h:
- case LoongArch::BI__builtin_lsx_vsrarni_b_h:
- case LoongArch::BI__builtin_lsx_vsrlni_b_h:
- case LoongArch::BI__builtin_lsx_vsrlrni_b_h:
- case LoongArch::BI__builtin_lsx_vssrlni_b_h:
- case LoongArch::BI__builtin_lsx_vssrlni_bu_h:
- case LoongArch::BI__builtin_lsx_vssrlrni_b_h:
- case LoongArch::BI__builtin_lsx_vssrlrni_bu_h:
- case LoongArch::BI__builtin_lsx_vsrani_b_h:
- return BuiltinConstantArgRange(TheCall, 2, 0, 15);
- case LoongArch::BI__builtin_lsx_vslei_bu:
- case LoongArch::BI__builtin_lsx_vslei_hu:
- case LoongArch::BI__builtin_lsx_vslei_wu:
- case LoongArch::BI__builtin_lsx_vslei_du:
- case LoongArch::BI__builtin_lsx_vslti_bu:
- case LoongArch::BI__builtin_lsx_vslti_hu:
- case LoongArch::BI__builtin_lsx_vslti_wu:
- case LoongArch::BI__builtin_lsx_vslti_du:
- case LoongArch::BI__builtin_lsx_vmaxi_bu:
- case LoongArch::BI__builtin_lsx_vmaxi_hu:
- case LoongArch::BI__builtin_lsx_vmaxi_wu:
- case LoongArch::BI__builtin_lsx_vmaxi_du:
- case LoongArch::BI__builtin_lsx_vmini_bu:
- case LoongArch::BI__builtin_lsx_vmini_hu:
- case LoongArch::BI__builtin_lsx_vmini_wu:
- case LoongArch::BI__builtin_lsx_vmini_du:
- case LoongArch::BI__builtin_lsx_vaddi_bu:
- case LoongArch::BI__builtin_lsx_vaddi_hu:
- case LoongArch::BI__builtin_lsx_vaddi_wu:
- case LoongArch::BI__builtin_lsx_vaddi_du:
- case LoongArch::BI__builtin_lsx_vbitclri_w:
- case LoongArch::BI__builtin_lsx_vbitrevi_w:
- case LoongArch::BI__builtin_lsx_vbitseti_w:
- case LoongArch::BI__builtin_lsx_vsat_w:
- case LoongArch::BI__builtin_lsx_vsat_wu:
- case LoongArch::BI__builtin_lsx_vslli_w:
- case LoongArch::BI__builtin_lsx_vsrai_w:
- case LoongArch::BI__builtin_lsx_vsrari_w:
- case LoongArch::BI__builtin_lsx_vsrli_w:
- case LoongArch::BI__builtin_lsx_vsllwil_d_w:
- case LoongArch::BI__builtin_lsx_vsllwil_du_wu:
- case LoongArch::BI__builtin_lsx_vsrlri_w:
- case LoongArch::BI__builtin_lsx_vrotri_w:
- case LoongArch::BI__builtin_lsx_vsubi_bu:
- case LoongArch::BI__builtin_lsx_vsubi_hu:
- case LoongArch::BI__builtin_lsx_vbsrl_v:
- case LoongArch::BI__builtin_lsx_vbsll_v:
- case LoongArch::BI__builtin_lsx_vsubi_wu:
- case LoongArch::BI__builtin_lsx_vsubi_du:
- return BuiltinConstantArgRange(TheCall, 1, 0, 31);
- case LoongArch::BI__builtin_lsx_vssrarni_h_w:
- case LoongArch::BI__builtin_lsx_vssrarni_hu_w:
- case LoongArch::BI__builtin_lsx_vssrani_h_w:
- case LoongArch::BI__builtin_lsx_vssrani_hu_w:
- case LoongArch::BI__builtin_lsx_vsrarni_h_w:
- case LoongArch::BI__builtin_lsx_vsrani_h_w:
- case LoongArch::BI__builtin_lsx_vfrstpi_b:
- case LoongArch::BI__builtin_lsx_vfrstpi_h:
- case LoongArch::BI__builtin_lsx_vsrlni_h_w:
- case LoongArch::BI__builtin_lsx_vsrlrni_h_w:
- case LoongArch::BI__builtin_lsx_vssrlni_h_w:
- case LoongArch::BI__builtin_lsx_vssrlni_hu_w:
- case LoongArch::BI__builtin_lsx_vssrlrni_h_w:
- case LoongArch::BI__builtin_lsx_vssrlrni_hu_w:
- return BuiltinConstantArgRange(TheCall, 2, 0, 31);
- case LoongArch::BI__builtin_lsx_vbitclri_d:
- case LoongArch::BI__builtin_lsx_vbitrevi_d:
- case LoongArch::BI__builtin_lsx_vbitseti_d:
- case LoongArch::BI__builtin_lsx_vsat_d:
- case LoongArch::BI__builtin_lsx_vsat_du:
- case LoongArch::BI__builtin_lsx_vslli_d:
- case LoongArch::BI__builtin_lsx_vsrai_d:
- case LoongArch::BI__builtin_lsx_vsrli_d:
- case LoongArch::BI__builtin_lsx_vsrari_d:
- case LoongArch::BI__builtin_lsx_vrotri_d:
- case LoongArch::BI__builtin_lsx_vsrlri_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 63);
- case LoongArch::BI__builtin_lsx_vssrarni_w_d:
- case LoongArch::BI__builtin_lsx_vssrarni_wu_d:
- case LoongArch::BI__builtin_lsx_vssrani_w_d:
- case LoongArch::BI__builtin_lsx_vssrani_wu_d:
- case LoongArch::BI__builtin_lsx_vsrarni_w_d:
- case LoongArch::BI__builtin_lsx_vsrlni_w_d:
- case LoongArch::BI__builtin_lsx_vsrlrni_w_d:
- case LoongArch::BI__builtin_lsx_vssrlni_w_d:
- case LoongArch::BI__builtin_lsx_vssrlni_wu_d:
- case LoongArch::BI__builtin_lsx_vssrlrni_w_d:
- case LoongArch::BI__builtin_lsx_vssrlrni_wu_d:
- case LoongArch::BI__builtin_lsx_vsrani_w_d:
- return BuiltinConstantArgRange(TheCall, 2, 0, 63);
- case LoongArch::BI__builtin_lsx_vssrarni_d_q:
- case LoongArch::BI__builtin_lsx_vssrarni_du_q:
- case LoongArch::BI__builtin_lsx_vssrani_d_q:
- case LoongArch::BI__builtin_lsx_vssrani_du_q:
- case LoongArch::BI__builtin_lsx_vsrarni_d_q:
- case LoongArch::BI__builtin_lsx_vssrlni_d_q:
- case LoongArch::BI__builtin_lsx_vssrlni_du_q:
- case LoongArch::BI__builtin_lsx_vssrlrni_d_q:
- case LoongArch::BI__builtin_lsx_vssrlrni_du_q:
- case LoongArch::BI__builtin_lsx_vsrani_d_q:
- case LoongArch::BI__builtin_lsx_vsrlrni_d_q:
- case LoongArch::BI__builtin_lsx_vsrlni_d_q:
- return BuiltinConstantArgRange(TheCall, 2, 0, 127);
- case LoongArch::BI__builtin_lsx_vseqi_b:
- case LoongArch::BI__builtin_lsx_vseqi_h:
- case LoongArch::BI__builtin_lsx_vseqi_w:
- case LoongArch::BI__builtin_lsx_vseqi_d:
- case LoongArch::BI__builtin_lsx_vslti_b:
- case LoongArch::BI__builtin_lsx_vslti_h:
- case LoongArch::BI__builtin_lsx_vslti_w:
- case LoongArch::BI__builtin_lsx_vslti_d:
- case LoongArch::BI__builtin_lsx_vslei_b:
- case LoongArch::BI__builtin_lsx_vslei_h:
- case LoongArch::BI__builtin_lsx_vslei_w:
- case LoongArch::BI__builtin_lsx_vslei_d:
- case LoongArch::BI__builtin_lsx_vmaxi_b:
- case LoongArch::BI__builtin_lsx_vmaxi_h:
- case LoongArch::BI__builtin_lsx_vmaxi_w:
- case LoongArch::BI__builtin_lsx_vmaxi_d:
- case LoongArch::BI__builtin_lsx_vmini_b:
- case LoongArch::BI__builtin_lsx_vmini_h:
- case LoongArch::BI__builtin_lsx_vmini_w:
- case LoongArch::BI__builtin_lsx_vmini_d:
- return BuiltinConstantArgRange(TheCall, 1, -16, 15);
- case LoongArch::BI__builtin_lsx_vandi_b:
- case LoongArch::BI__builtin_lsx_vnori_b:
- case LoongArch::BI__builtin_lsx_vori_b:
- case LoongArch::BI__builtin_lsx_vshuf4i_b:
- case LoongArch::BI__builtin_lsx_vshuf4i_h:
- case LoongArch::BI__builtin_lsx_vshuf4i_w:
- case LoongArch::BI__builtin_lsx_vxori_b:
- return BuiltinConstantArgRange(TheCall, 1, 0, 255);
- case LoongArch::BI__builtin_lsx_vbitseli_b:
- case LoongArch::BI__builtin_lsx_vshuf4i_d:
- case LoongArch::BI__builtin_lsx_vextrins_b:
- case LoongArch::BI__builtin_lsx_vextrins_h:
- case LoongArch::BI__builtin_lsx_vextrins_w:
- case LoongArch::BI__builtin_lsx_vextrins_d:
- case LoongArch::BI__builtin_lsx_vpermi_w:
- return BuiltinConstantArgRange(TheCall, 2, 0, 255);
- case LoongArch::BI__builtin_lsx_vpickve2gr_b:
- case LoongArch::BI__builtin_lsx_vpickve2gr_bu:
- case LoongArch::BI__builtin_lsx_vreplvei_b:
- return BuiltinConstantArgRange(TheCall, 1, 0, 15);
- case LoongArch::BI__builtin_lsx_vinsgr2vr_b:
- return BuiltinConstantArgRange(TheCall, 2, 0, 15);
- case LoongArch::BI__builtin_lsx_vpickve2gr_h:
- case LoongArch::BI__builtin_lsx_vpickve2gr_hu:
- case LoongArch::BI__builtin_lsx_vreplvei_h:
- return BuiltinConstantArgRange(TheCall, 1, 0, 7);
- case LoongArch::BI__builtin_lsx_vinsgr2vr_h:
- return BuiltinConstantArgRange(TheCall, 2, 0, 7);
- case LoongArch::BI__builtin_lsx_vpickve2gr_w:
- case LoongArch::BI__builtin_lsx_vpickve2gr_wu:
- case LoongArch::BI__builtin_lsx_vreplvei_w:
- return BuiltinConstantArgRange(TheCall, 1, 0, 3);
- case LoongArch::BI__builtin_lsx_vinsgr2vr_w:
- return BuiltinConstantArgRange(TheCall, 2, 0, 3);
- case LoongArch::BI__builtin_lsx_vpickve2gr_d:
- case LoongArch::BI__builtin_lsx_vpickve2gr_du:
- case LoongArch::BI__builtin_lsx_vreplvei_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 1);
- case LoongArch::BI__builtin_lsx_vinsgr2vr_d:
- return BuiltinConstantArgRange(TheCall, 2, 0, 1);
- case LoongArch::BI__builtin_lsx_vstelm_b:
- return BuiltinConstantArgRange(TheCall, 2, -128, 127) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 15);
- case LoongArch::BI__builtin_lsx_vstelm_h:
- return BuiltinConstantArgRange(TheCall, 2, -256, 254) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 7);
- case LoongArch::BI__builtin_lsx_vstelm_w:
- return BuiltinConstantArgRange(TheCall, 2, -512, 508) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 3);
- case LoongArch::BI__builtin_lsx_vstelm_d:
- return BuiltinConstantArgRange(TheCall, 2, -1024, 1016) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 1);
- case LoongArch::BI__builtin_lsx_vldrepl_b:
- case LoongArch::BI__builtin_lsx_vld:
- return BuiltinConstantArgRange(TheCall, 1, -2048, 2047);
- case LoongArch::BI__builtin_lsx_vldrepl_h:
- return BuiltinConstantArgRange(TheCall, 1, -2048, 2046);
- case LoongArch::BI__builtin_lsx_vldrepl_w:
- return BuiltinConstantArgRange(TheCall, 1, -2048, 2044);
- case LoongArch::BI__builtin_lsx_vldrepl_d:
- return BuiltinConstantArgRange(TheCall, 1, -2048, 2040);
- case LoongArch::BI__builtin_lsx_vst:
- return BuiltinConstantArgRange(TheCall, 2, -2048, 2047);
- case LoongArch::BI__builtin_lsx_vldi:
- return BuiltinConstantArgRange(TheCall, 0, -4096, 4095);
- case LoongArch::BI__builtin_lsx_vrepli_b:
- case LoongArch::BI__builtin_lsx_vrepli_h:
- case LoongArch::BI__builtin_lsx_vrepli_w:
- case LoongArch::BI__builtin_lsx_vrepli_d:
- return BuiltinConstantArgRange(TheCall, 0, -512, 511);
-
- // LASX intrinsics.
- case LoongArch::BI__builtin_lasx_xvbitclri_b:
- case LoongArch::BI__builtin_lasx_xvbitrevi_b:
- case LoongArch::BI__builtin_lasx_xvbitseti_b:
- case LoongArch::BI__builtin_lasx_xvsat_b:
- case LoongArch::BI__builtin_lasx_xvsat_bu:
- case LoongArch::BI__builtin_lasx_xvslli_b:
- case LoongArch::BI__builtin_lasx_xvsrai_b:
- case LoongArch::BI__builtin_lasx_xvsrari_b:
- case LoongArch::BI__builtin_lasx_xvsrli_b:
- case LoongArch::BI__builtin_lasx_xvsllwil_h_b:
- case LoongArch::BI__builtin_lasx_xvsllwil_hu_bu:
- case LoongArch::BI__builtin_lasx_xvrotri_b:
- case LoongArch::BI__builtin_lasx_xvsrlri_b:
- return BuiltinConstantArgRange(TheCall, 1, 0, 7);
- case LoongArch::BI__builtin_lasx_xvbitclri_h:
- case LoongArch::BI__builtin_lasx_xvbitrevi_h:
- case LoongArch::BI__builtin_lasx_xvbitseti_h:
- case LoongArch::BI__builtin_lasx_xvsat_h:
- case LoongArch::BI__builtin_lasx_xvsat_hu:
- case LoongArch::BI__builtin_lasx_xvslli_h:
- case LoongArch::BI__builtin_lasx_xvsrai_h:
- case LoongArch::BI__builtin_lasx_xvsrari_h:
- case LoongArch::BI__builtin_lasx_xvsrli_h:
- case LoongArch::BI__builtin_lasx_xvsllwil_w_h:
- case LoongArch::BI__builtin_lasx_xvsllwil_wu_hu:
- case LoongArch::BI__builtin_lasx_xvrotri_h:
- case LoongArch::BI__builtin_lasx_xvsrlri_h:
- return BuiltinConstantArgRange(TheCall, 1, 0, 15);
- case LoongArch::BI__builtin_lasx_xvssrarni_b_h:
- case LoongArch::BI__builtin_lasx_xvssrarni_bu_h:
- case LoongArch::BI__builtin_lasx_xvssrani_b_h:
- case LoongArch::BI__builtin_lasx_xvssrani_bu_h:
- case LoongArch::BI__builtin_lasx_xvsrarni_b_h:
- case LoongArch::BI__builtin_lasx_xvsrlni_b_h:
- case LoongArch::BI__builtin_lasx_xvsrlrni_b_h:
- case LoongArch::BI__builtin_lasx_xvssrlni_b_h:
- case LoongArch::BI__builtin_lasx_xvssrlni_bu_h:
- case LoongArch::BI__builtin_lasx_xvssrlrni_b_h:
- case LoongArch::BI__builtin_lasx_xvssrlrni_bu_h:
- case LoongArch::BI__builtin_lasx_xvsrani_b_h:
- return BuiltinConstantArgRange(TheCall, 2, 0, 15);
- case LoongArch::BI__builtin_lasx_xvslei_bu:
- case LoongArch::BI__builtin_lasx_xvslei_hu:
- case LoongArch::BI__builtin_lasx_xvslei_wu:
- case LoongArch::BI__builtin_lasx_xvslei_du:
- case LoongArch::BI__builtin_lasx_xvslti_bu:
- case LoongArch::BI__builtin_lasx_xvslti_hu:
- case LoongArch::BI__builtin_lasx_xvslti_wu:
- case LoongArch::BI__builtin_lasx_xvslti_du:
- case LoongArch::BI__builtin_lasx_xvmaxi_bu:
- case LoongArch::BI__builtin_lasx_xvmaxi_hu:
- case LoongArch::BI__builtin_lasx_xvmaxi_wu:
- case LoongArch::BI__builtin_lasx_xvmaxi_du:
- case LoongArch::BI__builtin_lasx_xvmini_bu:
- case LoongArch::BI__builtin_lasx_xvmini_hu:
- case LoongArch::BI__builtin_lasx_xvmini_wu:
- case LoongArch::BI__builtin_lasx_xvmini_du:
- case LoongArch::BI__builtin_lasx_xvaddi_bu:
- case LoongArch::BI__builtin_lasx_xvaddi_hu:
- case LoongArch::BI__builtin_lasx_xvaddi_wu:
- case LoongArch::BI__builtin_lasx_xvaddi_du:
- case LoongArch::BI__builtin_lasx_xvbitclri_w:
- case LoongArch::BI__builtin_lasx_xvbitrevi_w:
- case LoongArch::BI__builtin_lasx_xvbitseti_w:
- case LoongArch::BI__builtin_lasx_xvsat_w:
- case LoongArch::BI__builtin_lasx_xvsat_wu:
- case LoongArch::BI__builtin_lasx_xvslli_w:
- case LoongArch::BI__builtin_lasx_xvsrai_w:
- case LoongArch::BI__builtin_lasx_xvsrari_w:
- case LoongArch::BI__builtin_lasx_xvsrli_w:
- case LoongArch::BI__builtin_lasx_xvsllwil_d_w:
- case LoongArch::BI__builtin_lasx_xvsllwil_du_wu:
- case LoongArch::BI__builtin_lasx_xvsrlri_w:
- case LoongArch::BI__builtin_lasx_xvrotri_w:
- case LoongArch::BI__builtin_lasx_xvsubi_bu:
- case LoongArch::BI__builtin_lasx_xvsubi_hu:
- case LoongArch::BI__builtin_lasx_xvsubi_wu:
- case LoongArch::BI__builtin_lasx_xvsubi_du:
- case LoongArch::BI__builtin_lasx_xvbsrl_v:
- case LoongArch::BI__builtin_lasx_xvbsll_v:
- return BuiltinConstantArgRange(TheCall, 1, 0, 31);
- case LoongArch::BI__builtin_lasx_xvssrarni_h_w:
- case LoongArch::BI__builtin_lasx_xvssrarni_hu_w:
- case LoongArch::BI__builtin_lasx_xvssrani_h_w:
- case LoongArch::BI__builtin_lasx_xvssrani_hu_w:
- case LoongArch::BI__builtin_lasx_xvsrarni_h_w:
- case LoongArch::BI__builtin_lasx_xvsrani_h_w:
- case LoongArch::BI__builtin_lasx_xvfrstpi_b:
- case LoongArch::BI__builtin_lasx_xvfrstpi_h:
- case LoongArch::BI__builtin_lasx_xvsrlni_h_w:
- case LoongArch::BI__builtin_lasx_xvsrlrni_h_w:
- case LoongArch::BI__builtin_lasx_xvssrlni_h_w:
- case LoongArch::BI__builtin_lasx_xvssrlni_hu_w:
- case LoongArch::BI__builtin_lasx_xvssrlrni_h_w:
- case LoongArch::BI__builtin_lasx_xvssrlrni_hu_w:
- return BuiltinConstantArgRange(TheCall, 2, 0, 31);
- case LoongArch::BI__builtin_lasx_xvbitclri_d:
- case LoongArch::BI__builtin_lasx_xvbitrevi_d:
- case LoongArch::BI__builtin_lasx_xvbitseti_d:
- case LoongArch::BI__builtin_lasx_xvsat_d:
- case LoongArch::BI__builtin_lasx_xvsat_du:
- case LoongArch::BI__builtin_lasx_xvslli_d:
- case LoongArch::BI__builtin_lasx_xvsrai_d:
- case LoongArch::BI__builtin_lasx_xvsrli_d:
- case LoongArch::BI__builtin_lasx_xvsrari_d:
- case LoongArch::BI__builtin_lasx_xvrotri_d:
- case LoongArch::BI__builtin_lasx_xvsrlri_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 63);
- case LoongArch::BI__builtin_lasx_xvssrarni_w_d:
- case LoongArch::BI__builtin_lasx_xvssrarni_wu_d:
- case LoongArch::BI__builtin_lasx_xvssrani_w_d:
- case LoongArch::BI__builtin_lasx_xvssrani_wu_d:
- case LoongArch::BI__builtin_lasx_xvsrarni_w_d:
- case LoongArch::BI__builtin_lasx_xvsrlni_w_d:
- case LoongArch::BI__builtin_lasx_xvsrlrni_w_d:
- case LoongArch::BI__builtin_lasx_xvssrlni_w_d:
- case LoongArch::BI__builtin_lasx_xvssrlni_wu_d:
- case LoongArch::BI__builtin_lasx_xvssrlrni_w_d:
- case LoongArch::BI__builtin_lasx_xvssrlrni_wu_d:
- case LoongArch::BI__builtin_lasx_xvsrani_w_d:
- return BuiltinConstantArgRange(TheCall, 2, 0, 63);
- case LoongArch::BI__builtin_lasx_xvssrarni_d_q:
- case LoongArch::BI__builtin_lasx_xvssrarni_du_q:
- case LoongArch::BI__builtin_lasx_xvssrani_d_q:
- case LoongArch::BI__builtin_lasx_xvssrani_du_q:
- case LoongArch::BI__builtin_lasx_xvsrarni_d_q:
- case LoongArch::BI__builtin_lasx_xvssrlni_d_q:
- case LoongArch::BI__builtin_lasx_xvssrlni_du_q:
- case LoongArch::BI__builtin_lasx_xvssrlrni_d_q:
- case LoongArch::BI__builtin_lasx_xvssrlrni_du_q:
- case LoongArch::BI__builtin_lasx_xvsrani_d_q:
- case LoongArch::BI__builtin_lasx_xvsrlni_d_q:
- case LoongArch::BI__builtin_lasx_xvsrlrni_d_q:
- return BuiltinConstantArgRange(TheCall, 2, 0, 127);
- case LoongArch::BI__builtin_lasx_xvseqi_b:
- case LoongArch::BI__builtin_lasx_xvseqi_h:
- case LoongArch::BI__builtin_lasx_xvseqi_w:
- case LoongArch::BI__builtin_lasx_xvseqi_d:
- case LoongArch::BI__builtin_lasx_xvslti_b:
- case LoongArch::BI__builtin_lasx_xvslti_h:
- case LoongArch::BI__builtin_lasx_xvslti_w:
- case LoongArch::BI__builtin_lasx_xvslti_d:
- case LoongArch::BI__builtin_lasx_xvslei_b:
- case LoongArch::BI__builtin_lasx_xvslei_h:
- case LoongArch::BI__builtin_lasx_xvslei_w:
- case LoongArch::BI__builtin_lasx_xvslei_d:
- case LoongArch::BI__builtin_lasx_xvmaxi_b:
- case LoongArch::BI__builtin_lasx_xvmaxi_h:
- case LoongArch::BI__builtin_lasx_xvmaxi_w:
- case LoongArch::BI__builtin_lasx_xvmaxi_d:
- case LoongArch::BI__builtin_lasx_xvmini_b:
- case LoongArch::BI__builtin_lasx_xvmini_h:
- case LoongArch::BI__builtin_lasx_xvmini_w:
- case LoongArch::BI__builtin_lasx_xvmini_d:
- return BuiltinConstantArgRange(TheCall, 1, -16, 15);
- case LoongArch::BI__builtin_lasx_xvandi_b:
- case LoongArch::BI__builtin_lasx_xvnori_b:
- case LoongArch::BI__builtin_lasx_xvori_b:
- case LoongArch::BI__builtin_lasx_xvshuf4i_b:
- case LoongArch::BI__builtin_lasx_xvshuf4i_h:
- case LoongArch::BI__builtin_lasx_xvshuf4i_w:
- case LoongArch::BI__builtin_lasx_xvxori_b:
- case LoongArch::BI__builtin_lasx_xvpermi_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 255);
- case LoongArch::BI__builtin_lasx_xvbitseli_b:
- case LoongArch::BI__builtin_lasx_xvshuf4i_d:
- case LoongArch::BI__builtin_lasx_xvextrins_b:
- case LoongArch::BI__builtin_lasx_xvextrins_h:
- case LoongArch::BI__builtin_lasx_xvextrins_w:
- case LoongArch::BI__builtin_lasx_xvextrins_d:
- case LoongArch::BI__builtin_lasx_xvpermi_q:
- case LoongArch::BI__builtin_lasx_xvpermi_w:
- return BuiltinConstantArgRange(TheCall, 2, 0, 255);
- case LoongArch::BI__builtin_lasx_xvrepl128vei_b:
- return BuiltinConstantArgRange(TheCall, 1, 0, 15);
- case LoongArch::BI__builtin_lasx_xvrepl128vei_h:
- case LoongArch::BI__builtin_lasx_xvpickve2gr_w:
- case LoongArch::BI__builtin_lasx_xvpickve2gr_wu:
- case LoongArch::BI__builtin_lasx_xvpickve_w_f:
- case LoongArch::BI__builtin_lasx_xvpickve_w:
- return BuiltinConstantArgRange(TheCall, 1, 0, 7);
- case LoongArch::BI__builtin_lasx_xvinsgr2vr_w:
- case LoongArch::BI__builtin_lasx_xvinsve0_w:
- return BuiltinConstantArgRange(TheCall, 2, 0, 7);
- case LoongArch::BI__builtin_lasx_xvrepl128vei_w:
- case LoongArch::BI__builtin_lasx_xvpickve2gr_d:
- case LoongArch::BI__builtin_lasx_xvpickve2gr_du:
- case LoongArch::BI__builtin_lasx_xvpickve_d_f:
- case LoongArch::BI__builtin_lasx_xvpickve_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 3);
- case LoongArch::BI__builtin_lasx_xvinsve0_d:
- case LoongArch::BI__builtin_lasx_xvinsgr2vr_d:
- return BuiltinConstantArgRange(TheCall, 2, 0, 3);
- case LoongArch::BI__builtin_lasx_xvstelm_b:
- return BuiltinConstantArgRange(TheCall, 2, -128, 127) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 31);
- case LoongArch::BI__builtin_lasx_xvstelm_h:
- return BuiltinConstantArgRange(TheCall, 2, -256, 254) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 15);
- case LoongArch::BI__builtin_lasx_xvstelm_w:
- return BuiltinConstantArgRange(TheCall, 2, -512, 508) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 7);
- case LoongArch::BI__builtin_lasx_xvstelm_d:
- return BuiltinConstantArgRange(TheCall, 2, -1024, 1016) ||
- BuiltinConstantArgRange(TheCall, 3, 0, 3);
- case LoongArch::BI__builtin_lasx_xvrepl128vei_d:
- return BuiltinConstantArgRange(TheCall, 1, 0, 1);
- case LoongArch::BI__builtin_lasx_xvldrepl_b:
- case LoongArch::BI__builtin_lasx_xvld:
- return BuiltinConstantArgRange(TheCall, 1, -2048, 2047);
- case LoongArch::BI__builtin_lasx_xvldrepl_h:
- return BuiltinConstantArgRange(TheCall, 1, -2048, 2046);
- case LoongArch::BI__builtin_lasx_xvldrepl_w:
- return BuiltinConstantArgRange(TheCall, 1, -2048, 2044);
- case LoongArch::BI__builtin_lasx_xvldrepl_d:
- return BuiltinConstantArgRange(TheCall, 1, -2048, 2040);
- case LoongArch::BI__builtin_lasx_xvst:
- return BuiltinConstantArgRange(TheCall, 2, -2048, 2047);
- case LoongArch::BI__builtin_lasx_xvldi:
- return BuiltinConstantArgRange(TheCall, 0, -4096, 4095);
- case LoongArch::BI__builtin_lasx_xvrepli_b:
- case LoongArch::BI__builtin_lasx_xvrepli_h:
- case LoongArch::BI__builtin_lasx_xvrepli_w:
- case LoongArch::BI__builtin_lasx_xvrepli_d:
- return BuiltinConstantArgRange(TheCall, 0, -512, 511);
- }
- return false;
-}
-
-bool Sema::CheckMipsBuiltinFunctionCall(const TargetInfo &TI,
- unsigned BuiltinID, CallExpr *TheCall) {
- return CheckMipsBuiltinCpu(TI, BuiltinID, TheCall) ||
- CheckMipsBuiltinArgument(BuiltinID, TheCall);
-}
-
-bool Sema::CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
- CallExpr *TheCall) {
-
- if (Mips::BI__builtin_mips_addu_qb <= BuiltinID &&
- BuiltinID <= Mips::BI__builtin_mips_lwx) {
- if (!TI.hasFeature("dsp"))
- return Diag(TheCall->getBeginLoc(), diag::err_mips_builtin_requires_dsp);
- }
-
- if (Mips::BI__builtin_mips_absq_s_qb <= BuiltinID &&
- BuiltinID <= Mips::BI__builtin_mips_subuh_r_qb) {
- if (!TI.hasFeature("dspr2"))
- return Diag(TheCall->getBeginLoc(),
- diag::err_mips_builtin_requires_dspr2);
- }
-
- if (Mips::BI__builtin_msa_add_a_b <= BuiltinID &&
- BuiltinID <= Mips::BI__builtin_msa_xori_b) {
- if (!TI.hasFeature("msa"))
- return Diag(TheCall->getBeginLoc(), diag::err_mips_builtin_requires_msa);
- }
-
- return false;
-}
-
-// CheckMipsBuiltinArgument - Checks the constant value passed to the
-// intrinsic is correct. The switch statement is ordered by DSP, MSA. The
-// ordering for DSP is unspecified. MSA is ordered by the data format used
-// by the underlying instruction i.e., df/m, df/n and then by size.
-//
-// FIXME: The size tests here should instead be tablegen'd along with the
-// definitions from include/clang/Basic/BuiltinsMips.def.
-// FIXME: GCC is strict on signedness for some of these intrinsics, we should
-// be too.
-bool Sema::CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) {
- unsigned i = 0, l = 0, u = 0, m = 0;
- switch (BuiltinID) {
- default: return false;
- case Mips::BI__builtin_mips_wrdsp: i = 1; l = 0; u = 63; break;
- case Mips::BI__builtin_mips_rddsp: i = 0; l = 0; u = 63; break;
- case Mips::BI__builtin_mips_append: i = 2; l = 0; u = 31; break;
- case Mips::BI__builtin_mips_balign: i = 2; l = 0; u = 3; break;
- case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break;
- case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break;
- case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break;
- // MSA intrinsics. Instructions (which the intrinsics maps to) which use the
- // df/m field.
- // These intrinsics take an unsigned 3 bit immediate.
- case Mips::BI__builtin_msa_bclri_b:
- case Mips::BI__builtin_msa_bnegi_b:
- case Mips::BI__builtin_msa_bseti_b:
- case Mips::BI__builtin_msa_sat_s_b:
- case Mips::BI__builtin_msa_sat_u_b:
- case Mips::BI__builtin_msa_slli_b:
- case Mips::BI__builtin_msa_srai_b:
- case Mips::BI__builtin_msa_srari_b:
- case Mips::BI__builtin_msa_srli_b:
- case Mips::BI__builtin_msa_srlri_b: i = 1; l = 0; u = 7; break;
- case Mips::BI__builtin_msa_binsli_b:
- case Mips::BI__builtin_msa_binsri_b: i = 2; l = 0; u = 7; break;
- // These intrinsics take an unsigned 4 bit immediate.
- case Mips::BI__builtin_msa_bclri_h:
- case Mips::BI__builtin_msa_bnegi_h:
- case Mips::BI__builtin_msa_bseti_h:
- case Mips::BI__builtin_msa_sat_s_h:
- case Mips::BI__builtin_msa_sat_u_h:
- case Mips::BI__builtin_msa_slli_h:
- case Mips::BI__builtin_msa_srai_h:
- case Mips::BI__builtin_msa_srari_h:
- case Mips::BI__builtin_msa_srli_h:
- case Mips::BI__builtin_msa_srlri_h: i = 1; l = 0; u = 15; break;
- case Mips::BI__builtin_msa_binsli_h:
- case Mips::BI__builtin_msa_binsri_h: i = 2; l = 0; u = 15; break;
- // These intrinsics take an unsigned 5 bit immediate.
- // The first block of intrinsics actually have an unsigned 5 bit field,
- // not a df/n field.
- case Mips::BI__builtin_msa_cfcmsa:
- case Mips::BI__builtin_msa_ctcmsa: i = 0; l = 0; u = 31; break;
- case Mips::BI__builtin_msa_clei_u_b:
- case Mips::BI__builtin_msa_clei_u_h:
- case Mips::BI__builtin_msa_clei_u_w:
- case Mips::BI__builtin_msa_clei_u_d:
- case Mips::BI__builtin_msa_clti_u_b:
- case Mips::BI__builtin_msa_clti_u_h:
- case Mips::BI__builtin_msa_clti_u_w:
- case Mips::BI__builtin_msa_clti_u_d:
- case Mips::BI__builtin_msa_maxi_u_b:
- case Mips::BI__builtin_msa_maxi_u_h:
- case Mips::BI__builtin_msa_maxi_u_w:
- case Mips::BI__builtin_msa_maxi_u_d:
- case Mips::BI__builtin_msa_mini_u_b:
- case Mips::BI__builtin_msa_mini_u_h:
- case Mips::BI__builtin_msa_mini_u_w:
- case Mips::BI__builtin_msa_mini_u_d:
- case Mips::BI__builtin_msa_addvi_b:
- case Mips::BI__builtin_msa_addvi_h:
- case Mips::BI__builtin_msa_addvi_w:
- case Mips::BI__builtin_msa_addvi_d:
- case Mips::BI__builtin_msa_bclri_w:
- case Mips::BI__builtin_msa_bnegi_w:
- case Mips::BI__builtin_msa_bseti_w:
- case Mips::BI__builtin_msa_sat_s_w:
- case Mips::BI__builtin_msa_sat_u_w:
- case Mips::BI__builtin_msa_slli_w:
- case Mips::BI__builtin_msa_srai_w:
- case Mips::BI__builtin_msa_srari_w:
- case Mips::BI__builtin_msa_srli_w:
- case Mips::BI__builtin_msa_srlri_w:
- case Mips::BI__builtin_msa_subvi_b:
- case Mips::BI__builtin_msa_subvi_h:
- case Mips::BI__builtin_msa_subvi_w:
- case Mips::BI__builtin_msa_subvi_d: i = 1; l = 0; u = 31; break;
- case Mips::BI__builtin_msa_binsli_w:
- case Mips::BI__builtin_msa_binsri_w: i = 2; l = 0; u = 31; break;
- // These intrinsics take an unsigned 6 bit immediate.
- case Mips::BI__builtin_msa_bclri_d:
- case Mips::BI__builtin_msa_bnegi_d:
- case Mips::BI__builtin_msa_bseti_d:
- case Mips::BI__builtin_msa_sat_s_d:
- case Mips::BI__builtin_msa_sat_u_d:
- case Mips::BI__builtin_msa_slli_d:
- case Mips::BI__builtin_msa_srai_d:
- case Mips::BI__builtin_msa_srari_d:
- case Mips::BI__builtin_msa_srli_d:
- case Mips::BI__builtin_msa_srlri_d: i = 1; l = 0; u = 63; break;
- case Mips::BI__builtin_msa_binsli_d:
- case Mips::BI__builtin_msa_binsri_d: i = 2; l = 0; u = 63; break;
- // These intrinsics take a signed 5 bit immediate.
- case Mips::BI__builtin_msa_ceqi_b:
- case Mips::BI__builtin_msa_ceqi_h:
- case Mips::BI__builtin_msa_ceqi_w:
- case Mips::BI__builtin_msa_ceqi_d:
- case Mips::BI__builtin_msa_clti_s_b:
- case Mips::BI__builtin_msa_clti_s_h:
- case Mips::BI__builtin_msa_clti_s_w:
- case Mips::BI__builtin_msa_clti_s_d:
- case Mips::BI__builtin_msa_clei_s_b:
- case Mips::BI__builtin_msa_clei_s_h:
- case Mips::BI__builtin_msa_clei_s_w:
- case Mips::BI__builtin_msa_clei_s_d:
- case Mips::BI__builtin_msa_maxi_s_b:
- case Mips::BI__builtin_msa_maxi_s_h:
- case Mips::BI__builtin_msa_maxi_s_w:
- case Mips::BI__builtin_msa_maxi_s_d:
- case Mips::BI__builtin_msa_mini_s_b:
- case Mips::BI__builtin_msa_mini_s_h:
- case Mips::BI__builtin_msa_mini_s_w:
- case Mips::BI__builtin_msa_mini_s_d: i = 1; l = -16; u = 15; break;
- // These intrinsics take an unsigned 8 bit immediate.
- case Mips::BI__builtin_msa_andi_b:
- case Mips::BI__builtin_msa_nori_b:
- case Mips::BI__builtin_msa_ori_b:
- case Mips::BI__builtin_msa_shf_b:
- case Mips::BI__builtin_msa_shf_h:
- case Mips::BI__builtin_msa_shf_w:
- case Mips::BI__builtin_msa_xori_b: i = 1; l = 0; u = 255; break;
- case Mips::BI__builtin_msa_bseli_b:
- case Mips::BI__builtin_msa_bmnzi_b:
- case Mips::BI__builtin_msa_bmzi_b: i = 2; l = 0; u = 255; break;
- // df/n format
- // These intrinsics take an unsigned 4 bit immediate.
- case Mips::BI__builtin_msa_copy_s_b:
- case Mips::BI__builtin_msa_copy_u_b:
- case Mips::BI__builtin_msa_insve_b:
- case Mips::BI__builtin_msa_splati_b: i = 1; l = 0; u = 15; break;
- case Mips::BI__builtin_msa_sldi_b: i = 2; l = 0; u = 15; break;
- // These intrinsics take an unsigned 3 bit immediate.
- case Mips::BI__builtin_msa_copy_s_h:
- case Mips::BI__builtin_msa_copy_u_h:
- case Mips::BI__builtin_msa_insve_h:
- case Mips::BI__builtin_msa_splati_h: i = 1; l = 0; u = 7; break;
- case Mips::BI__builtin_msa_sldi_h: i = 2; l = 0; u = 7; break;
- // These intrinsics take an unsigned 2 bit immediate.
- case Mips::BI__builtin_msa_copy_s_w:
- case Mips::BI__builtin_msa_copy_u_w:
- case Mips::BI__builtin_msa_insve_w:
- case Mips::BI__builtin_msa_splati_w: i = 1; l = 0; u = 3; break;
- case Mips::BI__builtin_msa_sldi_w: i = 2; l = 0; u = 3; break;
- // These intrinsics take an unsigned 1 bit immediate.
- case Mips::BI__builtin_msa_copy_s_d:
- case Mips::BI__builtin_msa_copy_u_d:
- case Mips::BI__builtin_msa_insve_d:
- case Mips::BI__builtin_msa_splati_d: i = 1; l = 0; u = 1; break;
- case Mips::BI__builtin_msa_sldi_d: i = 2; l = 0; u = 1; break;
- // Memory offsets and immediate loads.
- // These intrinsics take a signed 10 bit immediate.
- case Mips::BI__builtin_msa_ldi_b: i = 0; l = -128; u = 255; break;
- case Mips::BI__builtin_msa_ldi_h:
- case Mips::BI__builtin_msa_ldi_w:
- case Mips::BI__builtin_msa_ldi_d: i = 0; l = -512; u = 511; break;
- case Mips::BI__builtin_msa_ld_b: i = 1; l = -512; u = 511; m = 1; break;
- case Mips::BI__builtin_msa_ld_h: i = 1; l = -1024; u = 1022; m = 2; break;
- case Mips::BI__builtin_msa_ld_w: i = 1; l = -2048; u = 2044; m = 4; break;
- case Mips::BI__builtin_msa_ld_d: i = 1; l = -4096; u = 4088; m = 8; break;
- case Mips::BI__builtin_msa_ldr_d: i = 1; l = -4096; u = 4088; m = 8; break;
- case Mips::BI__builtin_msa_ldr_w: i = 1; l = -2048; u = 2044; m = 4; break;
- case Mips::BI__builtin_msa_st_b: i = 2; l = -512; u = 511; m = 1; break;
- case Mips::BI__builtin_msa_st_h: i = 2; l = -1024; u = 1022; m = 2; break;
- case Mips::BI__builtin_msa_st_w: i = 2; l = -2048; u = 2044; m = 4; break;
- case Mips::BI__builtin_msa_st_d: i = 2; l = -4096; u = 4088; m = 8; break;
- case Mips::BI__builtin_msa_str_d: i = 2; l = -4096; u = 4088; m = 8; break;
- case Mips::BI__builtin_msa_str_w: i = 2; l = -2048; u = 2044; m = 4; break;
- }
-
- if (!m)
- return BuiltinConstantArgRange(TheCall, i, l, u);
-
- return BuiltinConstantArgRange(TheCall, i, l, u) ||
- BuiltinConstantArgMultiple(TheCall, i, m);
-}
-
-/// DecodePPCMMATypeFromStr - This decodes one PPC MMA type descriptor from Str,
-/// advancing the pointer over the consumed characters. The decoded type is
-/// returned. If the decoded type represents a constant integer with a
-/// constraint on its value then Mask is set to that value. The type descriptors
-/// used in Str are specific to PPC MMA builtins and are documented in the file
-/// defining the PPC builtins.
-static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str,
- unsigned &Mask) {
- bool RequireICE = false;
- ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;
- switch (*Str++) {
- case 'V':
- return Context.getVectorType(Context.UnsignedCharTy, 16,
- VectorKind::AltiVecVector);
- case 'i': {
- char *End;
- unsigned size = strtoul(Str, &End, 10);
- assert(End != Str && "Missing constant parameter constraint");
- Str = End;
- Mask = size;
- return Context.IntTy;
- }
- case 'W': {
- char *End;
- unsigned size = strtoul(Str, &End, 10);
- assert(End != Str && "Missing PowerPC MMA type size");
- Str = End;
- QualType Type;
- switch (size) {
- #define PPC_VECTOR_TYPE(typeName, Id, size) \
- case size: Type = Context.Id##Ty; break;
- #include "clang/Basic/PPCTypes.def"
- default: llvm_unreachable("Invalid PowerPC MMA vector type");
- }
- bool CheckVectorArgs = false;
- while (!CheckVectorArgs) {
- switch (*Str++) {
- case '*':
- Type = Context.getPointerType(Type);
- break;
- case 'C':
- Type = Type.withConst();
- break;
- default:
- CheckVectorArgs = true;
- --Str;
- break;
- }
- }
- return Type;
- }
- default:
- return Context.DecodeTypeStr(--Str, Context, Error, RequireICE, true);
- }
-}
-
-static bool isPPC_64Builtin(unsigned BuiltinID) {
- // These builtins only work on PPC 64bit targets.
- switch (BuiltinID) {
- case PPC::BI__builtin_divde:
- case PPC::BI__builtin_divdeu:
- case PPC::BI__builtin_bpermd:
- case PPC::BI__builtin_pdepd:
- case PPC::BI__builtin_pextd:
- case PPC::BI__builtin_ppc_ldarx:
- case PPC::BI__builtin_ppc_stdcx:
- case PPC::BI__builtin_ppc_tdw:
- case PPC::BI__builtin_ppc_trapd:
- case PPC::BI__builtin_ppc_cmpeqb:
- case PPC::BI__builtin_ppc_setb:
- case PPC::BI__builtin_ppc_mulhd:
- case PPC::BI__builtin_ppc_mulhdu:
- case PPC::BI__builtin_ppc_maddhd:
- case PPC::BI__builtin_ppc_maddhdu:
- case PPC::BI__builtin_ppc_maddld:
- case PPC::BI__builtin_ppc_load8r:
- case PPC::BI__builtin_ppc_store8r:
- case PPC::BI__builtin_ppc_insert_exp:
- case PPC::BI__builtin_ppc_extract_sig:
- case PPC::BI__builtin_ppc_addex:
- case PPC::BI__builtin_darn:
- case PPC::BI__builtin_darn_raw:
- case PPC::BI__builtin_ppc_compare_and_swaplp:
- case PPC::BI__builtin_ppc_fetch_and_addlp:
- case PPC::BI__builtin_ppc_fetch_and_andlp:
- case PPC::BI__builtin_ppc_fetch_and_orlp:
- case PPC::BI__builtin_ppc_fetch_and_swaplp:
- return true;
- }
- return false;
-}
-
/// Returns true if the argument consists of one contiguous run of 1s with any
/// number of 0s on either side. The 1s are allowed to wrap from LSB to MSB, so
/// 0x000FFF0, 0x0000FFFF, 0xFF0000FF, 0x0 are all runs. 0x0F0F0000 is not,
@@ -5287,182 +3322,6 @@ bool Sema::ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum) {
<< ArgNum << Arg->getSourceRange();
}
-bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
- CallExpr *TheCall) {
- unsigned i = 0, l = 0, u = 0;
- bool IsTarget64Bit = TI.getTypeWidth(TI.getIntPtrType()) == 64;
- llvm::APSInt Result;
-
- if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
- return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
- << TheCall->getSourceRange();
-
- switch (BuiltinID) {
- default: return false;
- case PPC::BI__builtin_altivec_crypto_vshasigmaw:
- case PPC::BI__builtin_altivec_crypto_vshasigmad:
- return BuiltinConstantArgRange(TheCall, 1, 0, 1) ||
- BuiltinConstantArgRange(TheCall, 2, 0, 15);
- case PPC::BI__builtin_altivec_dss:
- return BuiltinConstantArgRange(TheCall, 0, 0, 3);
- case PPC::BI__builtin_tbegin:
- case PPC::BI__builtin_tend:
- return BuiltinConstantArgRange(TheCall, 0, 0, 1);
- case PPC::BI__builtin_tsr:
- return BuiltinConstantArgRange(TheCall, 0, 0, 7);
- case PPC::BI__builtin_tabortwc:
- case PPC::BI__builtin_tabortdc:
- return BuiltinConstantArgRange(TheCall, 0, 0, 31);
- case PPC::BI__builtin_tabortwci:
- case PPC::BI__builtin_tabortdci:
- return BuiltinConstantArgRange(TheCall, 0, 0, 31) ||
- BuiltinConstantArgRange(TheCall, 2, 0, 31);
- // According to GCC 'Basic PowerPC Built-in Functions Available on ISA 2.05',
- // __builtin_(un)pack_longdouble are available only if long double uses IBM
- // extended double representation.
- case PPC::BI__builtin_unpack_longdouble:
- if (BuiltinConstantArgRange(TheCall, 1, 0, 1))
- return true;
- [[fallthrough]];
- case PPC::BI__builtin_pack_longdouble:
- if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())
- return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_requires_abi)
- << "ibmlongdouble";
- return false;
- case PPC::BI__builtin_altivec_dst:
- case PPC::BI__builtin_altivec_dstt:
- case PPC::BI__builtin_altivec_dstst:
- case PPC::BI__builtin_altivec_dststt:
- return BuiltinConstantArgRange(TheCall, 2, 0, 3);
- case PPC::BI__builtin_vsx_xxpermdi:
- case PPC::BI__builtin_vsx_xxsldwi:
- return BuiltinVSX(TheCall);
- case PPC::BI__builtin_unpack_vector_int128:
- return BuiltinConstantArgRange(TheCall, 1, 0, 1);
- case PPC::BI__builtin_altivec_vgnb:
- return BuiltinConstantArgRange(TheCall, 1, 2, 7);
- case PPC::BI__builtin_vsx_xxeval:
- return BuiltinConstantArgRange(TheCall, 3, 0, 255);
- case PPC::BI__builtin_altivec_vsldbi:
- return BuiltinConstantArgRange(TheCall, 2, 0, 7);
- case PPC::BI__builtin_altivec_vsrdbi:
- return BuiltinConstantArgRange(TheCall, 2, 0, 7);
- case PPC::BI__builtin_vsx_xxpermx:
- return BuiltinConstantArgRange(TheCall, 3, 0, 7);
- case PPC::BI__builtin_ppc_tw:
- case PPC::BI__builtin_ppc_tdw:
- return BuiltinConstantArgRange(TheCall, 2, 1, 31);
- case PPC::BI__builtin_ppc_cmprb:
- return BuiltinConstantArgRange(TheCall, 0, 0, 1);
- // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must
- // be a constant that represents a contiguous bit field.
- case PPC::BI__builtin_ppc_rlwnm:
- return ValueIsRunOfOnes(TheCall, 2);
- case PPC::BI__builtin_ppc_rlwimi:
- return BuiltinConstantArgRange(TheCall, 2, 0, 31) ||
- ValueIsRunOfOnes(TheCall, 3);
- case PPC::BI__builtin_ppc_rldimi:
- return BuiltinConstantArgRange(TheCall, 2, 0, 63) ||
- ValueIsRunOfOnes(TheCall, 3);
- case PPC::BI__builtin_ppc_addex: {
- if (BuiltinConstantArgRange(TheCall, 2, 0, 3))
- return true;
- // Output warning for reserved values 1 to 3.
- int ArgValue =
- TheCall->getArg(2)->getIntegerConstantExpr(Context)->getSExtValue();
- if (ArgValue != 0)
- Diag(TheCall->getBeginLoc(), diag::warn_argument_undefined_behaviour)
- << ArgValue;
- return false;
- }
- case PPC::BI__builtin_ppc_mtfsb0:
- case PPC::BI__builtin_ppc_mtfsb1:
- return BuiltinConstantArgRange(TheCall, 0, 0, 31);
- case PPC::BI__builtin_ppc_mtfsf:
- return BuiltinConstantArgRange(TheCall, 0, 0, 255);
- case PPC::BI__builtin_ppc_mtfsfi:
- return BuiltinConstantArgRange(TheCall, 0, 0, 7) ||
- BuiltinConstantArgRange(TheCall, 1, 0, 15);
- case PPC::BI__builtin_ppc_alignx:
- return BuiltinConstantArgPower2(TheCall, 0);
- case PPC::BI__builtin_ppc_rdlam:
- return ValueIsRunOfOnes(TheCall, 2);
- case PPC::BI__builtin_vsx_ldrmb:
- case PPC::BI__builtin_vsx_strmb:
- return BuiltinConstantArgRange(TheCall, 1, 1, 16);
- case PPC::BI__builtin_altivec_vcntmbb:
- case PPC::BI__builtin_altivec_vcntmbh:
- case PPC::BI__builtin_altivec_vcntmbw:
- case PPC::BI__builtin_altivec_vcntmbd:
- return BuiltinConstantArgRange(TheCall, 1, 0, 1);
- case PPC::BI__builtin_vsx_xxgenpcvbm:
- case PPC::BI__builtin_vsx_xxgenpcvhm:
- case PPC::BI__builtin_vsx_xxgenpcvwm:
- case PPC::BI__builtin_vsx_xxgenpcvdm:
- return BuiltinConstantArgRange(TheCall, 1, 0, 3);
- case PPC::BI__builtin_ppc_test_data_class: {
- // Check if the first argument of the __builtin_ppc_test_data_class call is
- // valid. The argument must be 'float' or 'double' or '__float128'.
- QualType ArgType = TheCall->getArg(0)->getType();
- if (ArgType != QualType(Context.FloatTy) &&
- ArgType != QualType(Context.DoubleTy) &&
- ArgType != QualType(Context.Float128Ty))
- return Diag(TheCall->getBeginLoc(),
- diag::err_ppc_invalid_test_data_class_type);
- return BuiltinConstantArgRange(TheCall, 1, 0, 127);
- }
- case PPC::BI__builtin_ppc_maxfe:
- case PPC::BI__builtin_ppc_minfe:
- case PPC::BI__builtin_ppc_maxfl:
- case PPC::BI__builtin_ppc_minfl:
- case PPC::BI__builtin_ppc_maxfs:
- case PPC::BI__builtin_ppc_minfs: {
- if (Context.getTargetInfo().getTriple().isOSAIX() &&
- (BuiltinID == PPC::BI__builtin_ppc_maxfe ||
- BuiltinID == PPC::BI__builtin_ppc_minfe))
- return Diag(TheCall->getBeginLoc(), diag::err_target_unsupported_type)
- << "builtin" << true << 128 << QualType(Context.LongDoubleTy)
- << false << Context.getTargetInfo().getTriple().str();
- // Argument type should be exact.
- QualType ArgType = QualType(Context.LongDoubleTy);
- if (BuiltinID == PPC::BI__builtin_ppc_maxfl ||
- BuiltinID == PPC::BI__builtin_ppc_minfl)
- ArgType = QualType(Context.DoubleTy);
- else if (BuiltinID == PPC::BI__builtin_ppc_maxfs ||
- BuiltinID == PPC::BI__builtin_ppc_minfs)
- ArgType = QualType(Context.FloatTy);
- for (unsigned I = 0, E = TheCall->getNumArgs(); I < E; ++I)
- if (TheCall->getArg(I)->getType() != ArgType)
- return Diag(TheCall->getBeginLoc(),
- diag::err_typecheck_convert_incompatible)
- << TheCall->getArg(I)->getType() << ArgType << 1 << 0 << 0;
- return false;
- }
-#define CUSTOM_BUILTIN(Name, Intr, Types, Acc, Feature) \
- case PPC::BI__builtin_##Name: \
- return BuiltinPPCMMACall(TheCall, BuiltinID, Types);
-#include "clang/Basic/BuiltinsPPC.def"
- }
- return BuiltinConstantArgRange(TheCall, i, l, u);
-}
-
-// Check if the given type is a non-pointer PPC MMA type. This function is used
-// in Sema to prevent invalid uses of restricted PPC MMA types.
-bool Sema::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) {
- if (Type->isPointerType() || Type->isArrayType())
- return false;
-
- QualType CoreType = Type.getCanonicalType().getUnqualifiedType();
-#define PPC_VECTOR_TYPE(Name, Id, Size) || CoreType == Context.Id##Ty
- if (false
-#include "clang/Basic/PPCTypes.def"
- ) {
- Diag(TypeLoc, diag::err_ppc_invalid_use_mma_type);
- return true;
- }
- return false;
-}
-
// Helper function for CheckHLSLBuiltinFunctionCall
bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
assert(TheCall->getNumArgs() > 1);
@@ -5685,201 +3544,6 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return false;
}
-bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall) {
- // position of memory order and scope arguments in the builtin
- unsigned OrderIndex, ScopeIndex;
- switch (BuiltinID) {
- case AMDGPU::BI__builtin_amdgcn_global_load_lds: {
- constexpr const int SizeIdx = 2;
- llvm::APSInt Size;
- Expr *ArgExpr = TheCall->getArg(SizeIdx);
- ExprResult R = VerifyIntegerConstantExpression(ArgExpr, &Size);
- if (R.isInvalid())
- return true;
- switch (Size.getSExtValue()) {
- case 1:
- case 2:
- case 4:
- return false;
- default:
- Diag(ArgExpr->getExprLoc(),
- diag::err_amdgcn_global_load_lds_size_invalid_value)
- << ArgExpr->getSourceRange();
- Diag(ArgExpr->getExprLoc(),
- diag::note_amdgcn_global_load_lds_size_valid_value)
- << ArgExpr->getSourceRange();
- return true;
- }
- }
- case AMDGPU::BI__builtin_amdgcn_get_fpenv:
- case AMDGPU::BI__builtin_amdgcn_set_fpenv:
- return false;
- case AMDGPU::BI__builtin_amdgcn_atomic_inc32:
- case AMDGPU::BI__builtin_amdgcn_atomic_inc64:
- case AMDGPU::BI__builtin_amdgcn_atomic_dec32:
- case AMDGPU::BI__builtin_amdgcn_atomic_dec64:
- OrderIndex = 2;
- ScopeIndex = 3;
- break;
- case AMDGPU::BI__builtin_amdgcn_fence:
- OrderIndex = 0;
- ScopeIndex = 1;
- break;
- default:
- return false;
- }
-
- ExprResult Arg = TheCall->getArg(OrderIndex);
- auto ArgExpr = Arg.get();
- Expr::EvalResult ArgResult;
-
- if (!ArgExpr->EvaluateAsInt(ArgResult, Context))
- return Diag(ArgExpr->getExprLoc(), diag::err_typecheck_expect_int)
- << ArgExpr->getType();
- auto Ord = ArgResult.Val.getInt().getZExtValue();
-
- // Check validity of memory ordering as per C11 / C++11's memody model.
- // Only fence needs check. Atomic dec/inc allow all memory orders.
- if (!llvm::isValidAtomicOrderingCABI(Ord))
- return Diag(ArgExpr->getBeginLoc(),
- diag::warn_atomic_op_has_invalid_memory_order)
- << 0 << ArgExpr->getSourceRange();
- switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) {
- case llvm::AtomicOrderingCABI::relaxed:
- case llvm::AtomicOrderingCABI::consume:
- if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence)
- return Diag(ArgExpr->getBeginLoc(),
- diag::warn_atomic_op_has_invalid_memory_order)
- << 0 << ArgExpr->getSourceRange();
- break;
- case llvm::AtomicOrderingCABI::acquire:
- case llvm::AtomicOrderingCABI::release:
- case llvm::AtomicOrderingCABI::acq_rel:
- case llvm::AtomicOrderingCABI::seq_cst:
- break;
- }
-
- Arg = TheCall->getArg(ScopeIndex);
- ArgExpr = Arg.get();
- Expr::EvalResult ArgResult1;
- // Check that sync scope is a constant literal
- if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, Context))
- return Diag(ArgExpr->getExprLoc(), diag::err_expr_not_string_literal)
- << ArgExpr->getType();
-
- return false;
-}
-
-bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall) {
- if (BuiltinID == SystemZ::BI__builtin_tabort) {
- Expr *Arg = TheCall->getArg(0);
- if (std::optional<llvm::APSInt> AbortCode =
- Arg->getIntegerConstantExpr(Context))
- if (AbortCode->getSExtValue() >= 0 && AbortCode->getSExtValue() < 256)
- return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code)
- << Arg->getSourceRange();
- }
-
- // 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 SystemZ::BI__builtin_s390_lcbb: i = 1; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_verimb:
- case SystemZ::BI__builtin_s390_verimh:
- case SystemZ::BI__builtin_s390_verimf:
- case SystemZ::BI__builtin_s390_verimg: i = 3; l = 0; u = 255; break;
- case SystemZ::BI__builtin_s390_vfaeb:
- case SystemZ::BI__builtin_s390_vfaeh:
- case SystemZ::BI__builtin_s390_vfaef:
- case SystemZ::BI__builtin_s390_vfaebs:
- case SystemZ::BI__builtin_s390_vfaehs:
- case SystemZ::BI__builtin_s390_vfaefs:
- case SystemZ::BI__builtin_s390_vfaezb:
- case SystemZ::BI__builtin_s390_vfaezh:
- case SystemZ::BI__builtin_s390_vfaezf:
- case SystemZ::BI__builtin_s390_vfaezbs:
- case SystemZ::BI__builtin_s390_vfaezhs:
- case SystemZ::BI__builtin_s390_vfaezfs: i = 2; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_vfisb:
- case SystemZ::BI__builtin_s390_vfidb:
- return BuiltinConstantArgRange(TheCall, 1, 0, 15) ||
- BuiltinConstantArgRange(TheCall, 2, 0, 15);
- case SystemZ::BI__builtin_s390_vftcisb:
- case SystemZ::BI__builtin_s390_vftcidb: i = 1; l = 0; u = 4095; break;
- case SystemZ::BI__builtin_s390_vlbb: i = 1; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_vpdi: i = 2; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_vsldb: i = 2; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_vstrcb:
- case SystemZ::BI__builtin_s390_vstrch:
- case SystemZ::BI__builtin_s390_vstrcf:
- case SystemZ::BI__builtin_s390_vstrczb:
- case SystemZ::BI__builtin_s390_vstrczh:
- case SystemZ::BI__builtin_s390_vstrczf:
- case SystemZ::BI__builtin_s390_vstrcbs:
- case SystemZ::BI__builtin_s390_vstrchs:
- case SystemZ::BI__builtin_s390_vstrcfs:
- case SystemZ::BI__builtin_s390_vstrczbs:
- case SystemZ::BI__builtin_s390_vstrczhs:
- case SystemZ::BI__builtin_s390_vstrczfs: i = 3; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_vmslg: i = 3; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_vfminsb:
- case SystemZ::BI__builtin_s390_vfmaxsb:
- case SystemZ::BI__builtin_s390_vfmindb:
- case SystemZ::BI__builtin_s390_vfmaxdb: i = 2; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_vsld: i = 2; l = 0; u = 7; break;
- case SystemZ::BI__builtin_s390_vsrd: i = 2; l = 0; u = 7; break;
- case SystemZ::BI__builtin_s390_vclfnhs:
- case SystemZ::BI__builtin_s390_vclfnls:
- case SystemZ::BI__builtin_s390_vcfn:
- case SystemZ::BI__builtin_s390_vcnf: i = 1; l = 0; u = 15; break;
- case SystemZ::BI__builtin_s390_vcrnfs: i = 2; l = 0; u = 15; break;
- }
- return BuiltinConstantArgRange(TheCall, i, l, u);
-}
-
-bool Sema::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
- unsigned BuiltinID,
- CallExpr *TheCall) {
- switch (BuiltinID) {
- case WebAssembly::BI__builtin_wasm_ref_null_extern:
- return BuiltinWasmRefNullExtern(TheCall);
- case WebAssembly::BI__builtin_wasm_ref_null_func:
- return BuiltinWasmRefNullFunc(TheCall);
- case WebAssembly::BI__builtin_wasm_table_get:
- return BuiltinWasmTableGet(TheCall);
- case WebAssembly::BI__builtin_wasm_table_set:
- return BuiltinWasmTableSet(TheCall);
- case WebAssembly::BI__builtin_wasm_table_size:
- return BuiltinWasmTableSize(TheCall);
- case WebAssembly::BI__builtin_wasm_table_grow:
- return BuiltinWasmTableGrow(TheCall);
- case WebAssembly::BI__builtin_wasm_table_fill:
- return BuiltinWasmTableFill(TheCall);
- case WebAssembly::BI__builtin_wasm_table_copy:
- return BuiltinWasmTableCopy(TheCall);
- }
-
- return false;
-}
-
-bool Sema::CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI,
- unsigned BuiltinID,
- CallExpr *TheCall) {
- switch (BuiltinID) {
- case NVPTX::BI__nvvm_cp_async_ca_shared_global_4:
- case NVPTX::BI__nvvm_cp_async_ca_shared_global_8:
- case NVPTX::BI__nvvm_cp_async_ca_shared_global_16:
- case NVPTX::BI__nvvm_cp_async_cg_shared_global_16:
- return checkArgCountAtMost(TheCall, 3);
- }
-
- return false;
-}
-
/// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo
/// parameter with the FormatAttr's correct format_idx and firstDataArg.
/// Returns true when the format fits the function and the FormatStringInfo has
@@ -6107,40 +3771,6 @@ static void CheckNonNullArguments(Sema &S,
}
}
-// 16 byte ByVal alignment not due to a vector member is not honoured by XL
-// on AIX. Emit a warning here that users are generating binary incompatible
-// code to be safe.
-// Here we try to get information about the alignment of the struct member
-// from the struct passed to the caller function. We only warn when the struct
-// is passed byval, hence the series of checks and early returns if we are a not
-// passing a struct byval.
-void Sema::checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg) {
- const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg->IgnoreParens());
- if (!ICE)
- return;
-
- const auto *DR = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
- if (!DR)
- return;
-
- const auto *PD = dyn_cast<ParmVarDecl>(DR->getDecl());
- if (!PD || !PD->getType()->isRecordType())
- return;
-
- QualType ArgType = Arg->getType();
- for (const FieldDecl *FD :
- ArgType->castAs<RecordType>()->getDecl()->fields()) {
- if (const auto *AA = FD->getAttr<AlignedAttr>()) {
- CharUnits Alignment =
- Context.toCharUnitsFromBits(AA->getAlignment(Context));
- if (Alignment.getQuantity() == 16) {
- Diag(FD->getLocation(), diag::warn_not_xl_compatible) << FD;
- Diag(Loc, diag::note_misaligned_member_used_here) << PD;
- }
- }
- }
-}
-
/// Warn if a pointer or reference argument passed to a function points to an
/// object that is less aligned than the parameter. This can happen when
/// creating a typedef with a lower alignment than the original type and then
@@ -6257,7 +3887,7 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
FDecl->hasLinkage() &&
FDecl->getFormalLinkage() != Linkage::Internal &&
CallType == VariadicDoesNotApply)
- checkAIXMemberAlignment((Arg->getExprLoc()), Arg);
+ PPC().checkAIXMemberAlignment((Arg->getExprLoc()), Arg);
QualType ParamTy = Proto->getParamType(ArgIdx);
if (ParamTy->isSizelessVectorType())
@@ -6293,10 +3923,10 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
bool IsCalleeStreamingCompatible =
ExtInfo.AArch64SMEAttributes &
FunctionType::SME_PStateSMCompatibleMask;
- ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
+ SemaARM::ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
if (!IsCalleeStreamingCompatible &&
- (CallerFnType == ArmStreamingCompatible ||
- ((CallerFnType == ArmStreaming) ^ IsCalleeStreaming))) {
+ (CallerFnType == SemaARM::ArmStreamingCompatible ||
+ ((CallerFnType == SemaARM::ArmStreaming) ^ IsCalleeStreaming))) {
if (IsScalableArg)
Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
<< /*IsArg=*/true;
@@ -7159,35 +4789,6 @@ static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) {
return false;
}
-bool Sema::BuiltinWasmRefNullExtern(CallExpr *TheCall) {
- if (TheCall->getNumArgs() != 0)
- return true;
-
- TheCall->setType(Context.getWebAssemblyExternrefType());
-
- return false;
-}
-
-bool Sema::BuiltinWasmRefNullFunc(CallExpr *TheCall) {
- if (TheCall->getNumArgs() != 0) {
- Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_many_args)
- << 0 /*function call*/ << /*expected*/ 0 << TheCall->getNumArgs()
- << /*is non object*/ 0;
- return true;
- }
-
- // This custom type checking code ensures that the nodes are as expected
- // in order to later on generate the necessary builtin.
- QualType Pointee = Context.getFunctionType(Context.VoidTy, {}, {});
- QualType Type = Context.getPointerType(Pointee);
- Pointee = Context.getAddrSpaceQualType(Pointee, LangAS::wasm_funcref);
- Type = Context.getAttributedType(attr::WebAssemblyFuncref, Type,
- Context.getPointerType(Pointee));
- TheCall->setType(Type);
-
- return false;
-}
-
/// We have a call to a function like __sync_fetch_and_add, which is an
/// overloaded function based on the pointer type of its first argument.
/// The main BuildCallExpr routines have already promoted the types of
@@ -8063,55 +5664,6 @@ bool Sema::BuiltinComplex(CallExpr *TheCall) {
return false;
}
-// Customized Sema Checking for VSX builtins that have the following signature:
-// vector [...] builtinName(vector [...], vector [...], const int);
-// Which takes the same type of vectors (any legal vector type) for the first
-// two arguments and takes compile time constant for the third argument.
-// Example builtins are :
-// vector double vec_xxpermdi(vector double, vector double, int);
-// vector short vec_xxsldwi(vector short, vector short, int);
-bool Sema::BuiltinVSX(CallExpr *TheCall) {
- unsigned ExpectedNumArgs = 3;
- if (checkArgCount(TheCall, ExpectedNumArgs))
- return true;
-
- // Check the third argument is a compile time constant
- if (!TheCall->getArg(2)->isIntegerConstantExpr(Context))
- return Diag(TheCall->getBeginLoc(),
- diag::err_vsx_builtin_nonconstant_argument)
- << 3 /* argument index */ << TheCall->getDirectCallee()
- << SourceRange(TheCall->getArg(2)->getBeginLoc(),
- TheCall->getArg(2)->getEndLoc());
-
- QualType Arg1Ty = TheCall->getArg(0)->getType();
- QualType Arg2Ty = TheCall->getArg(1)->getType();
-
- // Check the type of argument 1 and argument 2 are vectors.
- SourceLocation BuiltinLoc = TheCall->getBeginLoc();
- if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
- (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
- return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
- << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
- << SourceRange(TheCall->getArg(0)->getBeginLoc(),
- TheCall->getArg(1)->getEndLoc());
- }
-
- // Check the first two arguments are the same type.
- if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {
- return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
- << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
- << SourceRange(TheCall->getArg(0)->getBeginLoc(),
- TheCall->getArg(1)->getEndLoc());
- }
-
- // When default clang type checking is turned off and the customized type
- // checking is used, the returning type of the function must be explicitly
- // set. Otherwise it is _Bool by default.
- TheCall->setType(Arg1Ty);
-
- return false;
-}
-
/// BuiltinShuffleVector - Handle __builtin_shufflevector.
// This is declared to take (...), so we have to check everything.
ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
@@ -8629,360 +6181,6 @@ bool Sema::BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum,
<< Arg->getSourceRange();
}
-/// BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions
-bool Sema::BuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall) {
- if (BuiltinID == AArch64::BI__builtin_arm_irg) {
- if (checkArgCount(TheCall, 2))
- return true;
- Expr *Arg0 = TheCall->getArg(0);
- Expr *Arg1 = TheCall->getArg(1);
-
- ExprResult FirstArg = 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 = 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 (checkArgCount(TheCall, 2))
- return true;
-
- Expr *Arg0 = TheCall->getArg(0);
- ExprResult FirstArg = 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 BuiltinConstantArgRange(TheCall, 1, 0, 15);
- }
-
- if (BuiltinID == AArch64::BI__builtin_arm_gmi) {
- if (checkArgCount(TheCall, 2))
- return true;
- Expr *Arg0 = TheCall->getArg(0);
- Expr *Arg1 = TheCall->getArg(1);
-
- ExprResult FirstArg = 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 (checkArgCount(TheCall, 1))
- return true;
- Expr *Arg0 = TheCall->getArg(0);
- ExprResult FirstArg = 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 = DefaultFunctionArrayLvalueConversion(ArgA);
- ExprResult ArgExprB = 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 = ImpCastExprToType(ArgExprA.get(), ArgTypeB, CK_NullToPointer);
-
- if (isNull(ArgB))
- ArgExprB = 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 Sema::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> Ranges;
- if (FiveFields)
- Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 15, 15, 7});
- else
- Ranges.append({15, 7, 15});
-
- for (unsigned i=0; i<Fields.size(); ++i) {
- int IntField;
- ValidString &= !Fields[i].getAsInteger(10, IntField);
- ValidString &= (IntField >= 0 && IntField <= Ranges[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 BuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit);
- }
-
- return false;
-}
-
-/// BuiltinPPCMMACall - Check the call to a PPC MMA builtin for validity.
-/// Emit an error and return true on failure; return false on success.
-/// TypeStr is a string containing the type descriptor of the value returned by
-/// the builtin and the descriptors of the expected type of the arguments.
-bool Sema::BuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
- const char *TypeStr) {
-
- assert((TypeStr[0] != '\0') &&
- "Invalid types in PPC MMA builtin declaration");
-
- unsigned Mask = 0;
- unsigned ArgNum = 0;
-
- // The first type in TypeStr is the type of the value returned by the
- // builtin. So we first read that type and change the type of TheCall.
- QualType type = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
- TheCall->setType(type);
-
- while (*TypeStr != '\0') {
- Mask = 0;
- QualType ExpectedType = DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
- if (ArgNum >= TheCall->getNumArgs()) {
- ArgNum++;
- break;
- }
-
- Expr *Arg = TheCall->getArg(ArgNum);
- QualType PassedType = Arg->getType();
- QualType StrippedRVType = PassedType.getCanonicalType();
-
- // Strip Restrict/Volatile qualifiers.
- if (StrippedRVType.isRestrictQualified() ||
- StrippedRVType.isVolatileQualified())
- StrippedRVType = StrippedRVType.getCanonicalType().getUnqualifiedType();
-
- // The only case where the argument type and expected type are allowed to
- // mismatch is if the argument type is a non-void pointer (or array) and
- // expected type is a void pointer.
- if (StrippedRVType != ExpectedType)
- if (!(ExpectedType->isVoidPointerType() &&
- (StrippedRVType->isPointerType() || StrippedRVType->isArrayType())))
- return Diag(Arg->getBeginLoc(),
- diag::err_typecheck_convert_incompatible)
- << PassedType << ExpectedType << 1 << 0 << 0;
-
- // If the value of the Mask is not 0, we have a constraint in the size of
- // the integer argument so here we ensure the argument is a constant that
- // is in the valid range.
- if (Mask != 0 && BuiltinConstantArgRange(TheCall, ArgNum, 0, Mask, true))
- return true;
-
- ArgNum++;
- }
-
- // In case we exited early from the previous loop, there are other types to
- // read from TypeStr. So we need to read them all to ensure we have the right
- // number of arguments in TheCall and if it is not the case, to display a
- // better error message.
- while (*TypeStr != '\0') {
- (void) DecodePPCMMATypeFromStr(Context, TypeStr, Mask);
- ArgNum++;
- }
- if (checkArgCount(TheCall, ArgNum))
- return true;
-
- return false;
-}
-
/// BuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
/// This checks that the target supports __builtin_longjmp and
/// that val is a constant 1.
@@ -12712,7 +9910,7 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
// PPC MMA non-pointer types are not allowed as return type. Checking the type
// here prevent the user from using a PPC MMA type as trailing return type.
if (Context.getTargetInfo().getTriple().isPPC64())
- CheckPPCMMAType(RetValExp->getType(), ReturnLoc);
+ PPC().CheckPPCMMAType(RetValExp->getType(), ReturnLoc);
}
/// Check for comparisons of floating-point values using == and !=. Issue a
@@ -18390,168 +15588,6 @@ ExprResult Sema::BuiltinMatrixColumnMajorStore(CallExpr *TheCall,
return CallResult;
}
-/// Checks the argument at the given index is a WebAssembly table and if it
-/// is, sets ElTy to the element type.
-static bool CheckWasmBuiltinArgIsTable(Sema &S, CallExpr *E, unsigned ArgIndex,
- QualType &ElTy) {
- Expr *ArgExpr = E->getArg(ArgIndex);
- const auto *ATy = dyn_cast<ArrayType>(ArgExpr->getType());
- if (!ATy || !ATy->getElementType().isWebAssemblyReferenceType()) {
- return S.Diag(ArgExpr->getBeginLoc(),
- diag::err_wasm_builtin_arg_must_be_table_type)
- << ArgIndex + 1 << ArgExpr->getSourceRange();
- }
- ElTy = ATy->getElementType();
- return false;
-}
-
-/// Checks the argument at the given index is an integer.
-static bool CheckWasmBuiltinArgIsInteger(Sema &S, CallExpr *E,
- unsigned ArgIndex) {
- Expr *ArgExpr = E->getArg(ArgIndex);
- if (!ArgExpr->getType()->isIntegerType()) {
- return S.Diag(ArgExpr->getBeginLoc(),
- diag::err_wasm_builtin_arg_must_be_integer_type)
- << ArgIndex + 1 << ArgExpr->getSourceRange();
- }
- return false;
-}
-
-/// Check that the first argument is a WebAssembly table, and the second
-/// is an index to use as index into the table.
-bool Sema::BuiltinWasmTableGet(CallExpr *TheCall) {
- if (checkArgCount(TheCall, 2))
- return true;
-
- QualType ElTy;
- if (CheckWasmBuiltinArgIsTable(*this, TheCall, 0, ElTy))
- return true;
-
- if (CheckWasmBuiltinArgIsInteger(*this, TheCall, 1))
- return true;
-
- // If all is well, we set the type of TheCall to be the type of the
- // element of the table.
- // i.e. a table.get on an externref table has type externref,
- // or whatever the type of the table element is.
- TheCall->setType(ElTy);
-
- return false;
-}
-
-/// Check that the first argumnet is a WebAssembly table, the second is
-/// an index to use as index into the table and the third is the reference
-/// type to set into the table.
-bool Sema::BuiltinWasmTableSet(CallExpr *TheCall) {
- if (checkArgCount(TheCall, 3))
- return true;
-
- QualType ElTy;
- if (CheckWasmBuiltinArgIsTable(*this, TheCall, 0, ElTy))
- return true;
-
- if (CheckWasmBuiltinArgIsInteger(*this, TheCall, 1))
- return true;
-
- if (!Context.hasSameType(ElTy, TheCall->getArg(2)->getType()))
- return true;
-
- return false;
-}
-
-/// Check that the argument is a WebAssembly table.
-bool Sema::BuiltinWasmTableSize(CallExpr *TheCall) {
- if (checkArgCount(TheCall, 1))
- return true;
-
- QualType ElTy;
- if (CheckWasmBuiltinArgIsTable(*this, TheCall, 0, ElTy))
- return true;
-
- return false;
-}
-
-/// Check that the first argument is a WebAssembly table, the second is the
-/// value to use for new elements (of a type matching the table type), the
-/// third value is an integer.
-bool Sema::BuiltinWasmTableGrow(CallExpr *TheCall) {
- if (checkArgCount(TheCall, 3))
- return true;
-
- QualType ElTy;
- if (CheckWasmBuiltinArgIsTable(*this, TheCall, 0, ElTy))
- return true;
-
- Expr *NewElemArg = TheCall->getArg(1);
- if (!Context.hasSameType(ElTy, NewElemArg->getType())) {
- return Diag(NewElemArg->getBeginLoc(),
- diag::err_wasm_builtin_arg_must_match_table_element_type)
- << 2 << 1 << NewElemArg->getSourceRange();
- }
-
- if (CheckWasmBuiltinArgIsInteger(*this, TheCall, 2))
- return true;
-
- return false;
-}
-
-/// Check that the first argument is a WebAssembly table, the second is an
-/// integer, the third is the value to use to fill the table (of a type
-/// matching the table type), and the fourth is an integer.
-bool Sema::BuiltinWasmTableFill(CallExpr *TheCall) {
- if (checkArgCount(TheCall, 4))
- return true;
-
- QualType ElTy;
- if (CheckWasmBuiltinArgIsTable(*this, TheCall, 0, ElTy))
- return true;
-
- if (CheckWasmBuiltinArgIsInteger(*this, TheCall, 1))
- return true;
-
- Expr *NewElemArg = TheCall->getArg(2);
- if (!Context.hasSameType(ElTy, NewElemArg->getType())) {
- return Diag(NewElemArg->getBeginLoc(),
- diag::err_wasm_builtin_arg_must_match_table_element_type)
- << 3 << 1 << NewElemArg->getSourceRange();
- }
-
- if (CheckWasmBuiltinArgIsInteger(*this, TheCall, 3))
- return true;
-
- return false;
-}
-
-/// Check that the first argument is a WebAssembly table, the second is also a
-/// WebAssembly table (of the same element type), and the third to fifth
-/// arguments are integers.
-bool Sema::BuiltinWasmTableCopy(CallExpr *TheCall) {
- if (checkArgCount(TheCall, 5))
- return true;
-
- QualType XElTy;
- if (CheckWasmBuiltinArgIsTable(*this, TheCall, 0, XElTy))
- return true;
-
- QualType YElTy;
- if (CheckWasmBuiltinArgIsTable(*this, TheCall, 1, YElTy))
- return true;
-
- Expr *TableYArg = TheCall->getArg(1);
- if (!Context.hasSameType(XElTy, YElTy)) {
- return Diag(TableYArg->getBeginLoc(),
- diag::err_wasm_builtin_arg_must_match_table_element_type)
- << 2 << 1 << TableYArg->getSourceRange();
- }
-
- for (int I = 2; I <= 4; I++) {
- if (CheckWasmBuiltinArgIsInteger(*this, TheCall, I))
- return true;
- }
-
- return false;
-}
-
/// \brief Enforce the bounds of a TCB
/// CheckTCBEnforcement - Enforces that every function in a named TCB only
/// directly calls other functions in the same TCB as marked by the enforce_tcb