| //===- SemaChecking.cpp - Extra Semantic Checking -------------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements extra semantic analysis beyond what is enforced |
| // by the C type system. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/AST/APValue.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/Attr.h" |
| #include "clang/AST/AttrIterator.h" |
| #include "clang/AST/CharUnits.h" |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/DeclBase.h" |
| #include "clang/AST/DeclCXX.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/AST/DeclarationName.h" |
| #include "clang/AST/EvaluatedExprVisitor.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/ExprObjC.h" |
| #include "clang/AST/ExprOpenMP.h" |
| #include "clang/AST/NSAPI.h" |
| #include "clang/AST/NonTrivialTypeVisitor.h" |
| #include "clang/AST/OperationKinds.h" |
| #include "clang/AST/Stmt.h" |
| #include "clang/AST/TemplateBase.h" |
| #include "clang/AST/Type.h" |
| #include "clang/AST/TypeLoc.h" |
| #include "clang/AST/UnresolvedSet.h" |
| #include "clang/Analysis/Analyses/FormatString.h" |
| #include "clang/Basic/AddressSpaces.h" |
| #include "clang/Basic/CharInfo.h" |
| #include "clang/Basic/Diagnostic.h" |
| #include "clang/Basic/IdentifierTable.h" |
| #include "clang/Basic/LLVM.h" |
| #include "clang/Basic/LangOptions.h" |
| #include "clang/Basic/OpenCLOptions.h" |
| #include "clang/Basic/OperatorKinds.h" |
| #include "clang/Basic/PartialDiagnostic.h" |
| #include "clang/Basic/SourceLocation.h" |
| #include "clang/Basic/SourceManager.h" |
| #include "clang/Basic/Specifiers.h" |
| #include "clang/Basic/SyncScope.h" |
| #include "clang/Basic/TargetBuiltins.h" |
| #include "clang/Basic/TargetCXXABI.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/Basic/TypeTraits.h" |
| #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering. |
| #include "clang/Sema/Initialization.h" |
| #include "clang/Sema/Lookup.h" |
| #include "clang/Sema/Ownership.h" |
| #include "clang/Sema/Scope.h" |
| #include "clang/Sema/ScopeInfo.h" |
| #include "clang/Sema/Sema.h" |
| #include "clang/Sema/SemaInternal.h" |
| #include "llvm/ADT/APFloat.h" |
| #include "llvm/ADT/APInt.h" |
| #include "llvm/ADT/APSInt.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/FoldingSet.h" |
| #include "llvm/ADT/None.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/SmallBitVector.h" |
| #include "llvm/ADT/SmallPtrSet.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/StringSwitch.h" |
| #include "llvm/ADT/Triple.h" |
| #include "llvm/Support/AtomicOrdering.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/ConvertUTF.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/Format.h" |
| #include "llvm/Support/Locale.h" |
| #include "llvm/Support/MathExtras.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include <algorithm> |
| #include <cassert> |
| #include <cstddef> |
| #include <cstdint> |
| #include <functional> |
| #include <limits> |
| #include <string> |
| #include <tuple> |
| #include <utility> |
| |
| using namespace clang; |
| using namespace sema; |
| |
| SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, |
| unsigned ByteNo) const { |
| return SL->getLocationOfByte(ByteNo, getSourceManager(), LangOpts, |
| Context.getTargetInfo()); |
| } |
| |
| /// Checks that a call expression's argument count is the desired number. |
| /// This is useful when doing custom type-checking. Returns true on error. |
| static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) { |
| unsigned argCount = call->getNumArgs(); |
| if (argCount == desiredArgCount) return false; |
| |
| if (argCount < desiredArgCount) |
| return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args) |
| << 0 /*function call*/ << desiredArgCount << argCount |
| << call->getSourceRange(); |
| |
| // Highlight all the excess arguments. |
| SourceRange range(call->getArg(desiredArgCount)->getLocStart(), |
| call->getArg(argCount - 1)->getLocEnd()); |
| |
| return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args) |
| << 0 /*function call*/ << desiredArgCount << argCount |
| << call->getArg(1)->getSourceRange(); |
| } |
| |
| /// Check that the first argument to __builtin_annotation is an integer |
| /// and the second argument is a non-wide string literal. |
| static bool SemaBuiltinAnnotation(Sema &S, CallExpr *TheCall) { |
| if (checkArgCount(S, TheCall, 2)) |
| return true; |
| |
| // First argument should be an integer. |
| Expr *ValArg = TheCall->getArg(0); |
| QualType Ty = ValArg->getType(); |
| if (!Ty->isIntegerType()) { |
| S.Diag(ValArg->getLocStart(), diag::err_builtin_annotation_first_arg) |
| << ValArg->getSourceRange(); |
| return true; |
| } |
| |
| // Second argument should be a constant string. |
| Expr *StrArg = TheCall->getArg(1)->IgnoreParenCasts(); |
| StringLiteral *Literal = dyn_cast<StringLiteral>(StrArg); |
| if (!Literal || !Literal->isAscii()) { |
| S.Diag(StrArg->getLocStart(), diag::err_builtin_annotation_second_arg) |
| << StrArg->getSourceRange(); |
| return true; |
| } |
| |
| TheCall->setType(Ty); |
| return false; |
| } |
| |
| static bool SemaBuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) { |
| // We need at least one argument. |
| if (TheCall->getNumArgs() < 1) { |
| S.Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) |
| << 0 << 1 << TheCall->getNumArgs() |
| << TheCall->getCallee()->getSourceRange(); |
| return true; |
| } |
| |
| // All arguments should be wide string literals. |
| for (Expr *Arg : TheCall->arguments()) { |
| auto *Literal = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts()); |
| if (!Literal || !Literal->isWide()) { |
| S.Diag(Arg->getLocStart(), diag::err_msvc_annotation_wide_str) |
| << Arg->getSourceRange(); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /// Check that the argument to __builtin_addressof is a glvalue, and set the |
| /// result type to the corresponding pointer type. |
| static bool SemaBuiltinAddressof(Sema &S, CallExpr *TheCall) { |
| if (checkArgCount(S, TheCall, 1)) |
| return true; |
| |
| ExprResult Arg(TheCall->getArg(0)); |
| QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getLocStart()); |
| if (ResultType.isNull()) |
| return true; |
| |
| TheCall->setArg(0, Arg.get()); |
| TheCall->setType(ResultType); |
| return false; |
| } |
| |
| static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { |
| if (checkArgCount(S, TheCall, 3)) |
| return true; |
| |
| // First two arguments should be integers. |
| for (unsigned I = 0; I < 2; ++I) { |
| ExprResult Arg = TheCall->getArg(I); |
| QualType Ty = Arg.get()->getType(); |
| if (!Ty->isIntegerType()) { |
| S.Diag(Arg.get()->getLocStart(), diag::err_overflow_builtin_must_be_int) |
| << Ty << Arg.get()->getSourceRange(); |
| return true; |
| } |
| InitializedEntity Entity = InitializedEntity::InitializeParameter( |
| S.getASTContext(), Ty, /*consume*/ false); |
| Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg); |
| if (Arg.isInvalid()) |
| return true; |
| TheCall->setArg(I, Arg.get()); |
| } |
| |
| // Third argument should be a pointer to a non-const integer. |
| // IRGen correctly handles volatile, restrict, and address spaces, and |
| // the other qualifiers aren't possible. |
| { |
| ExprResult Arg = TheCall->getArg(2); |
| QualType Ty = Arg.get()->getType(); |
| const auto *PtrTy = Ty->getAs<PointerType>(); |
| if (!(PtrTy && PtrTy->getPointeeType()->isIntegerType() && |
| !PtrTy->getPointeeType().isConstQualified())) { |
| S.Diag(Arg.get()->getLocStart(), |
| diag::err_overflow_builtin_must_be_ptr_int) |
| << Ty << Arg.get()->getSourceRange(); |
| return true; |
| } |
| InitializedEntity Entity = InitializedEntity::InitializeParameter( |
| S.getASTContext(), Ty, /*consume*/ false); |
| Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg); |
| if (Arg.isInvalid()) |
| return true; |
| TheCall->setArg(2, Arg.get()); |
| } |
| return false; |
| } |
| |
| static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl, |
| CallExpr *TheCall, unsigned SizeIdx, |
| unsigned DstSizeIdx) { |
| if (TheCall->getNumArgs() <= SizeIdx || |
| TheCall->getNumArgs() <= DstSizeIdx) |
| return; |
| |
| const Expr *SizeArg = TheCall->getArg(SizeIdx); |
| const Expr *DstSizeArg = TheCall->getArg(DstSizeIdx); |
| |
| llvm::APSInt Size, DstSize; |
| |
| // find out if both sizes are known at compile time |
| if (!SizeArg->EvaluateAsInt(Size, S.Context) || |
| !DstSizeArg->EvaluateAsInt(DstSize, S.Context)) |
| return; |
| |
| if (Size.ule(DstSize)) |
| return; |
| |
| // confirmed overflow so generate the diagnostic. |
| IdentifierInfo *FnName = FDecl->getIdentifier(); |
| SourceLocation SL = TheCall->getLocStart(); |
| SourceRange SR = TheCall->getSourceRange(); |
| |
| S.Diag(SL, diag::warn_memcpy_chk_overflow) << SR << FnName; |
| } |
| |
| static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { |
| if (checkArgCount(S, BuiltinCall, 2)) |
| return true; |
| |
| SourceLocation BuiltinLoc = BuiltinCall->getLocStart(); |
| Expr *Builtin = BuiltinCall->getCallee()->IgnoreImpCasts(); |
| Expr *Call = BuiltinCall->getArg(0); |
| Expr *Chain = BuiltinCall->getArg(1); |
| |
| if (Call->getStmtClass() != Stmt::CallExprClass) { |
| S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_not_call) |
| << Call->getSourceRange(); |
| return true; |
| } |
| |
| auto CE = cast<CallExpr>(Call); |
| if (CE->getCallee()->getType()->isBlockPointerType()) { |
| S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_block_call) |
| << Call->getSourceRange(); |
| return true; |
| } |
| |
| const Decl *TargetDecl = CE->getCalleeDecl(); |
| if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) |
| if (FD->getBuiltinID()) { |
| S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_builtin_call) |
| << Call->getSourceRange(); |
| return true; |
| } |
| |
| if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) { |
| S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_pdtor_call) |
| << Call->getSourceRange(); |
| return true; |
| } |
| |
| ExprResult ChainResult = S.UsualUnaryConversions(Chain); |
| if (ChainResult.isInvalid()) |
| return true; |
| if (!ChainResult.get()->getType()->isPointerType()) { |
| S.Diag(BuiltinLoc, diag::err_second_argument_to_cwsc_not_pointer) |
| << Chain->getSourceRange(); |
| return true; |
| } |
| |
| QualType ReturnTy = CE->getCallReturnType(S.Context); |
| QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() }; |
| QualType BuiltinTy = S.Context.getFunctionType( |
| ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo()); |
| QualType BuiltinPtrTy = S.Context.getPointerType(BuiltinTy); |
| |
| Builtin = |
| S.ImpCastExprToType(Builtin, BuiltinPtrTy, CK_BuiltinFnToFnPtr).get(); |
| |
| BuiltinCall->setType(CE->getType()); |
| BuiltinCall->setValueKind(CE->getValueKind()); |
| BuiltinCall->setObjectKind(CE->getObjectKind()); |
| BuiltinCall->setCallee(Builtin); |
| BuiltinCall->setArg(1, ChainResult.get()); |
| |
| return false; |
| } |
| |
| static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall, |
| Scope::ScopeFlags NeededScopeFlags, |
| unsigned DiagID) { |
| // Scopes aren't available during instantiation. Fortunately, builtin |
| // functions cannot be template args so they cannot be formed through template |
| // instantiation. Therefore checking once during the parse is sufficient. |
| if (SemaRef.inTemplateInstantiation()) |
| return false; |
| |
| Scope *S = SemaRef.getCurScope(); |
| while (S && !S->isSEHExceptScope()) |
| S = S->getParent(); |
| if (!S || !(S->getFlags() & NeededScopeFlags)) { |
| auto *DRE = cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); |
| SemaRef.Diag(TheCall->getExprLoc(), DiagID) |
| << DRE->getDecl()->getIdentifier(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static inline bool isBlockPointer(Expr *Arg) { |
| return Arg->getType()->isBlockPointerType(); |
| } |
| |
| /// OpenCL C v2.0, s6.13.17.2 - Checks that the block parameters are all local |
| /// void*, which is a requirement of device side enqueue. |
| static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) { |
| const BlockPointerType *BPT = |
| cast<BlockPointerType>(BlockArg->getType().getCanonicalType()); |
| ArrayRef<QualType> Params = |
| BPT->getPointeeType()->getAs<FunctionProtoType>()->getParamTypes(); |
| unsigned ArgCounter = 0; |
| bool IllegalParams = false; |
| // Iterate through the block parameters until either one is found that is not |
| // a local void*, or the block is valid. |
| for (ArrayRef<QualType>::iterator I = Params.begin(), E = Params.end(); |
| I != E; ++I, ++ArgCounter) { |
| if (!(*I)->isPointerType() || !(*I)->getPointeeType()->isVoidType() || |
| (*I)->getPointeeType().getQualifiers().getAddressSpace() != |
| LangAS::opencl_local) { |
| // Get the location of the error. If a block literal has been passed |
| // (BlockExpr) then we can point straight to the offending argument, |
| // else we just point to the variable reference. |
| SourceLocation ErrorLoc; |
| if (isa<BlockExpr>(BlockArg)) { |
| BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl(); |
| ErrorLoc = BD->getParamDecl(ArgCounter)->getLocStart(); |
| } else if (isa<DeclRefExpr>(BlockArg)) { |
| ErrorLoc = cast<DeclRefExpr>(BlockArg)->getLocStart(); |
| } |
| S.Diag(ErrorLoc, |
| diag::err_opencl_enqueue_kernel_blocks_non_local_void_args); |
| IllegalParams = true; |
| } |
| } |
| |
| return IllegalParams; |
| } |
| |
| static bool checkOpenCLSubgroupExt(Sema &S, CallExpr *Call) { |
| if (!S.getOpenCLOptions().isEnabled("cl_khr_subgroups")) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_requires_extension) |
| << 1 << Call->getDirectCallee() << "cl_khr_subgroups"; |
| return true; |
| } |
| return false; |
| } |
| |
| static bool SemaOpenCLBuiltinNDRangeAndBlock(Sema &S, CallExpr *TheCall) { |
| if (checkArgCount(S, TheCall, 2)) |
| return true; |
| |
| if (checkOpenCLSubgroupExt(S, TheCall)) |
| return true; |
| |
| // First argument is an ndrange_t type. |
| Expr *NDRangeArg = TheCall->getArg(0); |
| if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") { |
| S.Diag(NDRangeArg->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << "'ndrange_t'"; |
| return true; |
| } |
| |
| Expr *BlockArg = TheCall->getArg(1); |
| if (!isBlockPointer(BlockArg)) { |
| S.Diag(BlockArg->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << "block"; |
| return true; |
| } |
| return checkOpenCLBlockArgs(S, BlockArg); |
| } |
| |
| /// OpenCL C v2.0, s6.13.17.6 - Check the argument to the |
| /// get_kernel_work_group_size |
| /// and get_kernel_preferred_work_group_size_multiple builtin functions. |
| static bool SemaOpenCLBuiltinKernelWorkGroupSize(Sema &S, CallExpr *TheCall) { |
| if (checkArgCount(S, TheCall, 1)) |
| return true; |
| |
| Expr *BlockArg = TheCall->getArg(0); |
| if (!isBlockPointer(BlockArg)) { |
| S.Diag(BlockArg->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << "block"; |
| return true; |
| } |
| return checkOpenCLBlockArgs(S, BlockArg); |
| } |
| |
| /// Diagnose integer type and any valid implicit conversion to it. |
| static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, |
| const QualType &IntType); |
| |
| static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall, |
| unsigned Start, unsigned End) { |
| bool IllegalParams = false; |
| for (unsigned I = Start; I <= End; ++I) |
| IllegalParams |= checkOpenCLEnqueueIntType(S, TheCall->getArg(I), |
| S.Context.getSizeType()); |
| return IllegalParams; |
| } |
| |
| /// OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all |
| /// 'local void*' parameter of passed block. |
| static bool checkOpenCLEnqueueVariadicArgs(Sema &S, CallExpr *TheCall, |
| Expr *BlockArg, |
| unsigned NumNonVarArgs) { |
| const BlockPointerType *BPT = |
| cast<BlockPointerType>(BlockArg->getType().getCanonicalType()); |
| unsigned NumBlockParams = |
| BPT->getPointeeType()->getAs<FunctionProtoType>()->getNumParams(); |
| unsigned TotalNumArgs = TheCall->getNumArgs(); |
| |
| // For each argument passed to the block, a corresponding uint needs to |
| // be passed to describe the size of the local memory. |
| if (TotalNumArgs != NumBlockParams + NumNonVarArgs) { |
| S.Diag(TheCall->getLocStart(), |
| diag::err_opencl_enqueue_kernel_local_size_args); |
| return true; |
| } |
| |
| // Check that the sizes of the local memory are specified by integers. |
| return checkOpenCLEnqueueLocalSizeArgs(S, TheCall, NumNonVarArgs, |
| TotalNumArgs - 1); |
| } |
| |
| /// OpenCL C v2.0, s6.13.17 - Enqueue kernel function contains four different |
| /// overload formats specified in Table 6.13.17.1. |
| /// int enqueue_kernel(queue_t queue, |
| /// kernel_enqueue_flags_t flags, |
| /// const ndrange_t ndrange, |
| /// void (^block)(void)) |
| /// int enqueue_kernel(queue_t queue, |
| /// kernel_enqueue_flags_t flags, |
| /// const ndrange_t ndrange, |
| /// uint num_events_in_wait_list, |
| /// clk_event_t *event_wait_list, |
| /// clk_event_t *event_ret, |
| /// void (^block)(void)) |
| /// int enqueue_kernel(queue_t queue, |
| /// kernel_enqueue_flags_t flags, |
| /// const ndrange_t ndrange, |
| /// void (^block)(local void*, ...), |
| /// uint size0, ...) |
| /// int enqueue_kernel(queue_t queue, |
| /// kernel_enqueue_flags_t flags, |
| /// const ndrange_t ndrange, |
| /// uint num_events_in_wait_list, |
| /// clk_event_t *event_wait_list, |
| /// clk_event_t *event_ret, |
| /// void (^block)(local void*, ...), |
| /// uint size0, ...) |
| static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) { |
| unsigned NumArgs = TheCall->getNumArgs(); |
| |
| if (NumArgs < 4) { |
| S.Diag(TheCall->getLocStart(), diag::err_typecheck_call_too_few_args); |
| return true; |
| } |
| |
| Expr *Arg0 = TheCall->getArg(0); |
| Expr *Arg1 = TheCall->getArg(1); |
| Expr *Arg2 = TheCall->getArg(2); |
| Expr *Arg3 = TheCall->getArg(3); |
| |
| // First argument always needs to be a queue_t type. |
| if (!Arg0->getType()->isQueueT()) { |
| S.Diag(TheCall->getArg(0)->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << S.Context.OCLQueueTy; |
| return true; |
| } |
| |
| // Second argument always needs to be a kernel_enqueue_flags_t enum value. |
| if (!Arg1->getType()->isIntegerType()) { |
| S.Diag(TheCall->getArg(1)->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)"; |
| return true; |
| } |
| |
| // Third argument is always an ndrange_t type. |
| if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") { |
| S.Diag(TheCall->getArg(2)->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << "'ndrange_t'"; |
| return true; |
| } |
| |
| // With four arguments, there is only one form that the function could be |
| // called in: no events and no variable arguments. |
| if (NumArgs == 4) { |
| // check that the last argument is the right block type. |
| if (!isBlockPointer(Arg3)) { |
| S.Diag(Arg3->getLocStart(), diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << "block"; |
| return true; |
| } |
| // we have a block type, check the prototype |
| const BlockPointerType *BPT = |
| cast<BlockPointerType>(Arg3->getType().getCanonicalType()); |
| if (BPT->getPointeeType()->getAs<FunctionProtoType>()->getNumParams() > 0) { |
| S.Diag(Arg3->getLocStart(), |
| diag::err_opencl_enqueue_kernel_blocks_no_args); |
| return true; |
| } |
| return false; |
| } |
| // we can have block + varargs. |
| if (isBlockPointer(Arg3)) |
| return (checkOpenCLBlockArgs(S, Arg3) || |
| checkOpenCLEnqueueVariadicArgs(S, TheCall, Arg3, 4)); |
| // last two cases with either exactly 7 args or 7 args and varargs. |
| if (NumArgs >= 7) { |
| // check common block argument. |
| Expr *Arg6 = TheCall->getArg(6); |
| if (!isBlockPointer(Arg6)) { |
| S.Diag(Arg6->getLocStart(), diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << "block"; |
| return true; |
| } |
| if (checkOpenCLBlockArgs(S, Arg6)) |
| return true; |
| |
| // Forth argument has to be any integer type. |
| if (!Arg3->getType()->isIntegerType()) { |
| S.Diag(TheCall->getArg(3)->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() << "integer"; |
| return true; |
| } |
| // check remaining common arguments. |
| Expr *Arg4 = TheCall->getArg(4); |
| Expr *Arg5 = TheCall->getArg(5); |
| |
| // Fifth argument is always passed as a pointer to clk_event_t. |
| if (!Arg4->isNullPointerConstant(S.Context, |
| Expr::NPC_ValueDependentIsNotNull) && |
| !Arg4->getType()->getPointeeOrArrayElementType()->isClkEventT()) { |
| S.Diag(TheCall->getArg(4)->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() |
| << S.Context.getPointerType(S.Context.OCLClkEventTy); |
| return true; |
| } |
| |
| // Sixth argument is always passed as a pointer to clk_event_t. |
| if (!Arg5->isNullPointerConstant(S.Context, |
| Expr::NPC_ValueDependentIsNotNull) && |
| !(Arg5->getType()->isPointerType() && |
| Arg5->getType()->getPointeeType()->isClkEventT())) { |
| S.Diag(TheCall->getArg(5)->getLocStart(), |
| diag::err_opencl_builtin_expected_type) |
| << TheCall->getDirectCallee() |
| << S.Context.getPointerType(S.Context.OCLClkEventTy); |
| return true; |
| } |
| |
| if (NumArgs == 7) |
| return false; |
| |
| return checkOpenCLEnqueueVariadicArgs(S, TheCall, Arg6, 7); |
| } |
| |
| // None of the specific case has been detected, give generic error |
| S.Diag(TheCall->getLocStart(), |
| diag::err_opencl_enqueue_kernel_incorrect_args); |
| return true; |
| } |
| |
| /// Returns OpenCL access qual. |
| static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) { |
| return D->getAttr<OpenCLAccessAttr>(); |
| } |
| |
| /// Returns true if pipe element type is different from the pointer. |
| static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) { |
| const Expr *Arg0 = Call->getArg(0); |
| // First argument type should always be pipe. |
| if (!Arg0->getType()->isPipeType()) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) |
| << Call->getDirectCallee() << Arg0->getSourceRange(); |
| return true; |
| } |
| OpenCLAccessAttr *AccessQual = |
| getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl()); |
| // Validates the access qualifier is compatible with the call. |
| // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should only be |
| // read_only and write_only, and assumed to be read_only if no qualifier is |
| // specified. |
| switch (Call->getDirectCallee()->getBuiltinID()) { |
| case Builtin::BIread_pipe: |
| case Builtin::BIreserve_read_pipe: |
| case Builtin::BIcommit_read_pipe: |
| case Builtin::BIwork_group_reserve_read_pipe: |
| case Builtin::BIsub_group_reserve_read_pipe: |
| case Builtin::BIwork_group_commit_read_pipe: |
| case Builtin::BIsub_group_commit_read_pipe: |
| if (!(!AccessQual || AccessQual->isReadOnly())) { |
| S.Diag(Arg0->getLocStart(), |
| diag::err_opencl_builtin_pipe_invalid_access_modifier) |
| << "read_only" << Arg0->getSourceRange(); |
| return true; |
| } |
| break; |
| case Builtin::BIwrite_pipe: |
| case Builtin::BIreserve_write_pipe: |
| case Builtin::BIcommit_write_pipe: |
| case Builtin::BIwork_group_reserve_write_pipe: |
| case Builtin::BIsub_group_reserve_write_pipe: |
| case Builtin::BIwork_group_commit_write_pipe: |
| case Builtin::BIsub_group_commit_write_pipe: |
| if (!(AccessQual && AccessQual->isWriteOnly())) { |
| S.Diag(Arg0->getLocStart(), |
| diag::err_opencl_builtin_pipe_invalid_access_modifier) |
| << "write_only" << Arg0->getSourceRange(); |
| return true; |
| } |
| break; |
| default: |
| break; |
| } |
| return false; |
| } |
| |
| /// Returns true if pipe element type is different from the pointer. |
| static bool checkOpenCLPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) { |
| const Expr *Arg0 = Call->getArg(0); |
| const Expr *ArgIdx = Call->getArg(Idx); |
| const PipeType *PipeTy = cast<PipeType>(Arg0->getType()); |
| const QualType EltTy = PipeTy->getElementType(); |
| const PointerType *ArgTy = ArgIdx->getType()->getAs<PointerType>(); |
| // The Idx argument should be a pointer and the type of the pointer and |
| // the type of pipe element should also be the same. |
| if (!ArgTy || |
| !S.Context.hasSameType( |
| EltTy, ArgTy->getPointeeType()->getCanonicalTypeInternal())) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) |
| << Call->getDirectCallee() << S.Context.getPointerType(EltTy) |
| << ArgIdx->getType() << ArgIdx->getSourceRange(); |
| return true; |
| } |
| return false; |
| } |
| |
| // Performs semantic analysis for the read/write_pipe call. |
| // \param S Reference to the semantic analyzer. |
| // \param Call A pointer to the builtin call. |
| // \return True if a semantic error has been found, false otherwise. |
| static bool SemaBuiltinRWPipe(Sema &S, CallExpr *Call) { |
| // OpenCL v2.0 s6.13.16.2 - The built-in read/write |
| // functions have two forms. |
| switch (Call->getNumArgs()) { |
| case 2: |
| if (checkOpenCLPipeArg(S, Call)) |
| return true; |
| // The call with 2 arguments should be |
| // read/write_pipe(pipe T, T*). |
| // Check packet type T. |
| if (checkOpenCLPipePacketType(S, Call, 1)) |
| return true; |
| break; |
| |
| case 4: { |
| if (checkOpenCLPipeArg(S, Call)) |
| return true; |
| // The call with 4 arguments should be |
| // read/write_pipe(pipe T, reserve_id_t, uint, T*). |
| // Check reserve_id_t. |
| if (!Call->getArg(1)->getType()->isReserveIDT()) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) |
| << Call->getDirectCallee() << S.Context.OCLReserveIDTy |
| << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); |
| return true; |
| } |
| |
| // Check the index. |
| const Expr *Arg2 = Call->getArg(2); |
| if (!Arg2->getType()->isIntegerType() && |
| !Arg2->getType()->isUnsignedIntegerType()) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) |
| << Call->getDirectCallee() << S.Context.UnsignedIntTy |
| << Arg2->getType() << Arg2->getSourceRange(); |
| return true; |
| } |
| |
| // Check packet type T. |
| if (checkOpenCLPipePacketType(S, Call, 3)) |
| return true; |
| } break; |
| default: |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_arg_num) |
| << Call->getDirectCallee() << Call->getSourceRange(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // Performs a semantic analysis on the {work_group_/sub_group_ |
| // /_}reserve_{read/write}_pipe |
| // \param S Reference to the semantic analyzer. |
| // \param Call The call to the builtin function to be analyzed. |
| // \return True if a semantic error was found, false otherwise. |
| static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) { |
| if (checkArgCount(S, Call, 2)) |
| return true; |
| |
| if (checkOpenCLPipeArg(S, Call)) |
| return true; |
| |
| // Check the reserve size. |
| if (!Call->getArg(1)->getType()->isIntegerType() && |
| !Call->getArg(1)->getType()->isUnsignedIntegerType()) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) |
| << Call->getDirectCallee() << S.Context.UnsignedIntTy |
| << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); |
| return true; |
| } |
| |
| // Since return type of reserve_read/write_pipe built-in function is |
| // reserve_id_t, which is not defined in the builtin def file , we used int |
| // as return type and need to override the return type of these functions. |
| Call->setType(S.Context.OCLReserveIDTy); |
| |
| return false; |
| } |
| |
| // Performs a semantic analysis on {work_group_/sub_group_ |
| // /_}commit_{read/write}_pipe |
| // \param S Reference to the semantic analyzer. |
| // \param Call The call to the builtin function to be analyzed. |
| // \return True if a semantic error was found, false otherwise. |
| static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { |
| if (checkArgCount(S, Call, 2)) |
| return true; |
| |
| if (checkOpenCLPipeArg(S, Call)) |
| return true; |
| |
| // Check reserve_id_t. |
| if (!Call->getArg(1)->getType()->isReserveIDT()) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) |
| << Call->getDirectCallee() << S.Context.OCLReserveIDTy |
| << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // Performs a semantic analysis on the call to built-in Pipe |
| // Query Functions. |
| // \param S Reference to the semantic analyzer. |
| // \param Call The call to the builtin function to be analyzed. |
| // \return True if a semantic error was found, false otherwise. |
| static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { |
| if (checkArgCount(S, Call, 1)) |
| return true; |
| |
| if (!Call->getArg(0)->getType()->isPipeType()) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) |
| << Call->getDirectCallee() << Call->getArg(0)->getSourceRange(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // OpenCL v2.0 s6.13.9 - Address space qualifier functions. |
| // Performs semantic analysis for the to_global/local/private call. |
| // \param S Reference to the semantic analyzer. |
| // \param BuiltinID ID of the builtin function. |
| // \param Call A pointer to the builtin call. |
| // \return True if a semantic error has been found, false otherwise. |
| static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, |
| CallExpr *Call) { |
| if (Call->getNumArgs() != 1) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num) |
| << Call->getDirectCallee() << Call->getSourceRange(); |
| return true; |
| } |
| |
| auto RT = Call->getArg(0)->getType(); |
| if (!RT->isPointerType() || RT->getPointeeType() |
| .getAddressSpace() == LangAS::opencl_constant) { |
| S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg) |
| << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange(); |
| return true; |
| } |
| |
| RT = RT->getPointeeType(); |
| auto Qual = RT.getQualifiers(); |
| switch (BuiltinID) { |
| case Builtin::BIto_global: |
| Qual.setAddressSpace(LangAS::opencl_global); |
| break; |
| case Builtin::BIto_local: |
| Qual.setAddressSpace(LangAS::opencl_local); |
| break; |
| case Builtin::BIto_private: |
| Qual.setAddressSpace(LangAS::opencl_private); |
| break; |
| default: |
| llvm_unreachable("Invalid builtin function"); |
| } |
| Call->setType(S.Context.getPointerType(S.Context.getQualifiedType( |
| RT.getUnqualifiedType(), Qual))); |
| |
| return false; |
| } |
| |
| // Emit an error and return true if the current architecture is not in the list |
| // of supported architectures. |
| static bool |
| CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall, |
| ArrayRef<llvm::Triple::ArchType> SupportedArchs) { |
| llvm::Triple::ArchType CurArch = |
| S.getASTContext().getTargetInfo().getTriple().getArch(); |
| if (llvm::is_contained(SupportedArchs, CurArch)) |
| return false; |
| S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported) |
| << TheCall->getSourceRange(); |
| return true; |
| } |
| |
| ExprResult |
| Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, |
| CallExpr *TheCall) { |
| ExprResult TheCallResult(TheCall); |
| |
| // Find out if any arguments are required to be integer constant expressions. |
| unsigned ICEArguments = 0; |
| ASTContext::GetBuiltinTypeError Error; |
| Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); |
| if (Error != ASTContext::GE_None) |
| ICEArguments = 0; // Don't diagnose previously diagnosed errors. |
| |
| // If any arguments are required to be ICE's, check and diagnose. |
| for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { |
| // Skip arguments not required to be ICE's. |
| if ((ICEArguments & (1 << ArgNo)) == 0) continue; |
| |
| llvm::APSInt Result; |
| if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) |
| return true; |
| ICEArguments &= ~(1 << ArgNo); |
| } |
| |
| switch (BuiltinID) { |
| case Builtin::BI__builtin___CFStringMakeConstantString: |
| assert(TheCall->getNumArgs() == 1 && |
| "Wrong # arguments to builtin CFStringMakeConstantString"); |
| if (CheckObjCString(TheCall->getArg(0))) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_ms_va_start: |
| case Builtin::BI__builtin_stdarg_start: |
| case Builtin::BI__builtin_va_start: |
| if (SemaBuiltinVAStart(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__va_start: { |
| switch (Context.getTargetInfo().getTriple().getArch()) { |
| case llvm::Triple::arm: |
| case llvm::Triple::thumb: |
| if (SemaBuiltinVAStartARMMicrosoft(TheCall)) |
| return ExprError(); |
| break; |
| default: |
| if (SemaBuiltinVAStart(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| } |
| break; |
| } |
| |
| // The acquire, release, and no fence variants are ARM and AArch64 only. |
| case Builtin::BI_interlockedbittestandset_acq: |
| case Builtin::BI_interlockedbittestandset_rel: |
| case Builtin::BI_interlockedbittestandset_nf: |
| case Builtin::BI_interlockedbittestandreset_acq: |
| case Builtin::BI_interlockedbittestandreset_rel: |
| case Builtin::BI_interlockedbittestandreset_nf: |
| if (CheckBuiltinTargetSupport( |
| *this, BuiltinID, TheCall, |
| {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64})) |
| return ExprError(); |
| break; |
| |
| // The 64-bit bittest variants are x64, ARM, and AArch64 only. |
| case Builtin::BI_bittest64: |
| case Builtin::BI_bittestandcomplement64: |
| case Builtin::BI_bittestandreset64: |
| case Builtin::BI_bittestandset64: |
| case Builtin::BI_interlockedbittestandreset64: |
| case Builtin::BI_interlockedbittestandset64: |
| if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall, |
| {llvm::Triple::x86_64, llvm::Triple::arm, |
| llvm::Triple::thumb, llvm::Triple::aarch64})) |
| return ExprError(); |
| break; |
| |
| case Builtin::BI__builtin_isgreater: |
| case Builtin::BI__builtin_isgreaterequal: |
| case Builtin::BI__builtin_isless: |
| case Builtin::BI__builtin_islessequal: |
| case Builtin::BI__builtin_islessgreater: |
| case Builtin::BI__builtin_isunordered: |
| if (SemaBuiltinUnorderedCompare(TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_fpclassify: |
| if (SemaBuiltinFPClassification(TheCall, 6)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_isfinite: |
| case Builtin::BI__builtin_isinf: |
| case Builtin::BI__builtin_isinf_sign: |
| case Builtin::BI__builtin_isnan: |
| case Builtin::BI__builtin_isnormal: |
| case Builtin::BI__builtin_signbit: |
| case Builtin::BI__builtin_signbitf: |
| case Builtin::BI__builtin_signbitl: |
| if (SemaBuiltinFPClassification(TheCall, 1)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_shufflevector: |
| return SemaBuiltinShuffleVector(TheCall); |
| // TheCall will be freed by the smart pointer here, but that's fine, since |
| // SemaBuiltinShuffleVector guts it, but then doesn't release it. |
| case Builtin::BI__builtin_prefetch: |
| if (SemaBuiltinPrefetch(TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_alloca_with_align: |
| if (SemaBuiltinAllocaWithAlign(TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__assume: |
| case Builtin::BI__builtin_assume: |
| if (SemaBuiltinAssume(TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_assume_aligned: |
| if (SemaBuiltinAssumeAligned(TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_object_size: |
| if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_longjmp: |
| if (SemaBuiltinLongjmp(TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_setjmp: |
| if (SemaBuiltinSetjmp(TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI_setjmp: |
| case Builtin::BI_setjmpex: |
| if (checkArgCount(*this, TheCall, 1)) |
| return true; |
| break; |
| case Builtin::BI__builtin_classify_type: |
| if (checkArgCount(*this, TheCall, 1)) return true; |
| TheCall->setType(Context.IntTy); |
| break; |
| case Builtin::BI__builtin_constant_p: |
| if (checkArgCount(*this, TheCall, 1)) return true; |
| TheCall->setType(Context.IntTy); |
| break; |
| case Builtin::BI__sync_fetch_and_add: |
| case Builtin::BI__sync_fetch_and_add_1: |
| case Builtin::BI__sync_fetch_and_add_2: |
| case Builtin::BI__sync_fetch_and_add_4: |
| case Builtin::BI__sync_fetch_and_add_8: |
| case Builtin::BI__sync_fetch_and_add_16: |
| case Builtin::BI__sync_fetch_and_sub: |
| case Builtin::BI__sync_fetch_and_sub_1: |
| case Builtin::BI__sync_fetch_and_sub_2: |
| case Builtin::BI__sync_fetch_and_sub_4: |
| case Builtin::BI__sync_fetch_and_sub_8: |
| case Builtin::BI__sync_fetch_and_sub_16: |
| case Builtin::BI__sync_fetch_and_or: |
| case Builtin::BI__sync_fetch_and_or_1: |
| case Builtin::BI__sync_fetch_and_or_2: |
| case Builtin::BI__sync_fetch_and_or_4: |
| case Builtin::BI__sync_fetch_and_or_8: |
| case Builtin::BI__sync_fetch_and_or_16: |
| case Builtin::BI__sync_fetch_and_and: |
| case Builtin::BI__sync_fetch_and_and_1: |
| case Builtin::BI__sync_fetch_and_and_2: |
| case Builtin::BI__sync_fetch_and_and_4: |
| case Builtin::BI__sync_fetch_and_and_8: |
| case Builtin::BI__sync_fetch_and_and_16: |
| case Builtin::BI__sync_fetch_and_xor: |
| case Builtin::BI__sync_fetch_and_xor_1: |
| case Builtin::BI__sync_fetch_and_xor_2: |
| case Builtin::BI__sync_fetch_and_xor_4: |
| case Builtin::BI__sync_fetch_and_xor_8: |
| case Builtin::BI__sync_fetch_and_xor_16: |
| case Builtin::BI__sync_fetch_and_nand: |
| case Builtin::BI__sync_fetch_and_nand_1: |
| case Builtin::BI__sync_fetch_and_nand_2: |
| case Builtin::BI__sync_fetch_and_nand_4: |
| case Builtin::BI__sync_fetch_and_nand_8: |
| case Builtin::BI__sync_fetch_and_nand_16: |
| case Builtin::BI__sync_add_and_fetch: |
| case Builtin::BI__sync_add_and_fetch_1: |
| case Builtin::BI__sync_add_and_fetch_2: |
| case Builtin::BI__sync_add_and_fetch_4: |
| case Builtin::BI__sync_add_and_fetch_8: |
| case Builtin::BI__sync_add_and_fetch_16: |
| case Builtin::BI__sync_sub_and_fetch: |
| case Builtin::BI__sync_sub_and_fetch_1: |
| case Builtin::BI__sync_sub_and_fetch_2: |
| case Builtin::BI__sync_sub_and_fetch_4: |
| case Builtin::BI__sync_sub_and_fetch_8: |
| case Builtin::BI__sync_sub_and_fetch_16: |
| case Builtin::BI__sync_and_and_fetch: |
| case Builtin::BI__sync_and_and_fetch_1: |
| case Builtin::BI__sync_and_and_fetch_2: |
| case Builtin::BI__sync_and_and_fetch_4: |
| case Builtin::BI__sync_and_and_fetch_8: |
| case Builtin::BI__sync_and_and_fetch_16: |
| case Builtin::BI__sync_or_and_fetch: |
| case Builtin::BI__sync_or_and_fetch_1: |
| case Builtin::BI__sync_or_and_fetch_2: |
| case Builtin::BI__sync_or_and_fetch_4: |
| case Builtin::BI__sync_or_and_fetch_8: |
| case Builtin::BI__sync_or_and_fetch_16: |
| case Builtin::BI__sync_xor_and_fetch: |
| case Builtin::BI__sync_xor_and_fetch_1: |
| case Builtin::BI__sync_xor_and_fetch_2: |
| case Builtin::BI__sync_xor_and_fetch_4: |
| case Builtin::BI__sync_xor_and_fetch_8: |
| case Builtin::BI__sync_xor_and_fetch_16: |
| case Builtin::BI__sync_nand_and_fetch: |
| case Builtin::BI__sync_nand_and_fetch_1: |
| case Builtin::BI__sync_nand_and_fetch_2: |
| case Builtin::BI__sync_nand_and_fetch_4: |
| case Builtin::BI__sync_nand_and_fetch_8: |
| case Builtin::BI__sync_nand_and_fetch_16: |
| case Builtin::BI__sync_val_compare_and_swap: |
| case Builtin::BI__sync_val_compare_and_swap_1: |
| case Builtin::BI__sync_val_compare_and_swap_2: |
| case Builtin::BI__sync_val_compare_and_swap_4: |
| case Builtin::BI__sync_val_compare_and_swap_8: |
| case Builtin::BI__sync_val_compare_and_swap_16: |
| case Builtin::BI__sync_bool_compare_and_swap: |
| case Builtin::BI__sync_bool_compare_and_swap_1: |
| case Builtin::BI__sync_bool_compare_and_swap_2: |
| case Builtin::BI__sync_bool_compare_and_swap_4: |
| case Builtin::BI__sync_bool_compare_and_swap_8: |
| case Builtin::BI__sync_bool_compare_and_swap_16: |
| case Builtin::BI__sync_lock_test_and_set: |
| case Builtin::BI__sync_lock_test_and_set_1: |
| case Builtin::BI__sync_lock_test_and_set_2: |
| case Builtin::BI__sync_lock_test_and_set_4: |
| case Builtin::BI__sync_lock_test_and_set_8: |
| case Builtin::BI__sync_lock_test_and_set_16: |
| case Builtin::BI__sync_lock_release: |
| case Builtin::BI__sync_lock_release_1: |
| case Builtin::BI__sync_lock_release_2: |
| case Builtin::BI__sync_lock_release_4: |
| case Builtin::BI__sync_lock_release_8: |
| case Builtin::BI__sync_lock_release_16: |
| case Builtin::BI__sync_swap: |
| case Builtin::BI__sync_swap_1: |
| case Builtin::BI__sync_swap_2: |
| case Builtin::BI__sync_swap_4: |
| case Builtin::BI__sync_swap_8: |
| case Builtin::BI__sync_swap_16: |
| return SemaBuiltinAtomicOverloaded(TheCallResult); |
| case Builtin::BI__builtin_nontemporal_load: |
| case Builtin::BI__builtin_nontemporal_store: |
| return SemaBuiltinNontemporalOverloaded(TheCallResult); |
| #define BUILTIN(ID, TYPE, ATTRS) |
| #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ |
| case Builtin::BI##ID: \ |
| return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID); |
| #include "clang/Basic/Builtins.def" |
| case Builtin::BI__annotation: |
| if (SemaBuiltinMSVCAnnotation(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_annotation: |
| if (SemaBuiltinAnnotation(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_addressof: |
| if (SemaBuiltinAddressof(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_add_overflow: |
| case Builtin::BI__builtin_sub_overflow: |
| case Builtin::BI__builtin_mul_overflow: |
| if (SemaBuiltinOverflow(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_operator_new: |
| case Builtin::BI__builtin_operator_delete: { |
| bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete; |
| ExprResult Res = |
| SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete); |
| if (Res.isInvalid()) |
| CorrectDelayedTyposInExpr(TheCallResult.get()); |
| return Res; |
| } |
| case Builtin::BI__builtin_dump_struct: { |
| // We first want to ensure we are called with 2 arguments |
| if (checkArgCount(*this, TheCall, 2)) |
| return ExprError(); |
| // Ensure that the first argument is of type 'struct XX *' |
| const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); |
| const QualType PtrArgType = PtrArg->getType(); |
| if (!PtrArgType->isPointerType() || |
| !PtrArgType->getPointeeType()->isRecordType()) { |
| Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) |
| << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType |
| << "structure pointer"; |
| return ExprError(); |
| } |
| |
| // Ensure that the second argument is of type 'FunctionType' |
| const Expr *FnPtrArg = TheCall->getArg(1)->IgnoreImpCasts(); |
| const QualType FnPtrArgType = FnPtrArg->getType(); |
| if (!FnPtrArgType->isPointerType()) { |
| Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) |
| << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 |
| << 2 << FnPtrArgType << "'int (*)(const char *, ...)'"; |
| return ExprError(); |
| } |
| |
| const auto *FuncType = |
| FnPtrArgType->getPointeeType()->getAs<FunctionType>(); |
| |
| if (!FuncType) { |
| Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) |
| << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 |
| << 2 << FnPtrArgType << "'int (*)(const char *, ...)'"; |
| return ExprError(); |
| } |
| |
| if (const auto *FT = dyn_cast<FunctionProtoType>(FuncType)) { |
| if (!FT->getNumParams()) { |
| Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) |
| << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 |
| << 2 << FnPtrArgType << "'int (*)(const char *, ...)'"; |
| return ExprError(); |
| } |
| QualType PT = FT->getParamType(0); |
| if (!FT->isVariadic() || FT->getReturnType() != Context.IntTy || |
| !PT->isPointerType() || !PT->getPointeeType()->isCharType() || |
| !PT->getPointeeType().isConstQualified()) { |
| Diag(FnPtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) |
| << FnPtrArgType << "'int (*)(const char *, ...)'" << 1 << 0 << 3 |
| << 2 << FnPtrArgType << "'int (*)(const char *, ...)'"; |
| return ExprError(); |
| } |
| } |
| |
| TheCall->setType(Context.IntTy); |
| break; |
| } |
| |
| // check secure string manipulation functions where overflows |
| // are detectable at compile time |
| case Builtin::BI__builtin___memcpy_chk: |
| case Builtin::BI__builtin___memmove_chk: |
| case Builtin::BI__builtin___memset_chk: |
| case Builtin::BI__builtin___strlcat_chk: |
| case Builtin::BI__builtin___strlcpy_chk: |
| case Builtin::BI__builtin___strncat_chk: |
| case Builtin::BI__builtin___strncpy_chk: |
| case Builtin::BI__builtin___stpncpy_chk: |
| SemaBuiltinMemChkCall(*this, FDecl, TheCall, 2, 3); |
| break; |
| case Builtin::BI__builtin___memccpy_chk: |
| SemaBuiltinMemChkCall(*this, FDecl, TheCall, 3, 4); |
| break; |
| case Builtin::BI__builtin___snprintf_chk: |
| case Builtin::BI__builtin___vsnprintf_chk: |
| SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3); |
| break; |
| case Builtin::BI__builtin_call_with_static_chain: |
| if (SemaBuiltinCallWithStaticChain(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__exception_code: |
| case Builtin::BI_exception_code: |
| if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHExceptScope, |
| diag::err_seh___except_block)) |
| return ExprError(); |
| break; |
| case Builtin::BI__exception_info: |
| case Builtin::BI_exception_info: |
| if (SemaBuiltinSEHScopeCheck(*this, TheCall, Scope::SEHFilterScope, |
| diag::err_seh___except_filter)) |
| return ExprError(); |
| break; |
| case Builtin::BI__GetExceptionInfo: |
| if (checkArgCount(*this, TheCall, 1)) |
| return ExprError(); |
| |
| if (CheckCXXThrowOperand( |
| TheCall->getLocStart(), |
| Context.getExceptionObjectType(FDecl->getParamDecl(0)->getType()), |
| TheCall)) |
| return ExprError(); |
| |
| TheCall->setType(Context.VoidPtrTy); |
| break; |
| // OpenCL v2.0, s6.13.16 - Pipe functions |
| case Builtin::BIread_pipe: |
| case Builtin::BIwrite_pipe: |
| // Since those two functions are declared with var args, we need a semantic |
| // check for the argument. |
| if (SemaBuiltinRWPipe(*this, TheCall)) |
| return ExprError(); |
| TheCall->setType(Context.IntTy); |
| break; |
| case Builtin::BIreserve_read_pipe: |
| case Builtin::BIreserve_write_pipe: |
| case Builtin::BIwork_group_reserve_read_pipe: |
| case Builtin::BIwork_group_reserve_write_pipe: |
| if (SemaBuiltinReserveRWPipe(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BIsub_group_reserve_read_pipe: |
| case Builtin::BIsub_group_reserve_write_pipe: |
| if (checkOpenCLSubgroupExt(*this, TheCall) || |
| SemaBuiltinReserveRWPipe(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BIcommit_read_pipe: |
| case Builtin::BIcommit_write_pipe: |
| case Builtin::BIwork_group_commit_read_pipe: |
| case Builtin::BIwork_group_commit_write_pipe: |
| if (SemaBuiltinCommitRWPipe(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BIsub_group_commit_read_pipe: |
| case Builtin::BIsub_group_commit_write_pipe: |
| if (checkOpenCLSubgroupExt(*this, TheCall) || |
| SemaBuiltinCommitRWPipe(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BIget_pipe_num_packets: |
| case Builtin::BIget_pipe_max_packets: |
| if (SemaBuiltinPipePackets(*this, TheCall)) |
| return ExprError(); |
| TheCall->setType(Context.UnsignedIntTy); |
| break; |
| case Builtin::BIto_global: |
| case Builtin::BIto_local: |
| case Builtin::BIto_private: |
| if (SemaOpenCLBuiltinToAddr(*this, BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| // OpenCL v2.0, s6.13.17 - Enqueue kernel functions. |
| case Builtin::BIenqueue_kernel: |
| if (SemaOpenCLBuiltinEnqueueKernel(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BIget_kernel_work_group_size: |
| case Builtin::BIget_kernel_preferred_work_group_size_multiple: |
| if (SemaOpenCLBuiltinKernelWorkGroupSize(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BIget_kernel_max_sub_group_size_for_ndrange: |
| case Builtin::BIget_kernel_sub_group_count_for_ndrange: |
| if (SemaOpenCLBuiltinNDRangeAndBlock(*this, TheCall)) |
| return ExprError(); |
| break; |
| case Builtin::BI__builtin_os_log_format: |
| case Builtin::BI__builtin_os_log_format_buffer_size: |
| if (SemaBuiltinOSLogFormat(TheCall)) |
| return ExprError(); |
| break; |
| } |
| |
| // Since the target specific builtins for each arch overlap, only check those |
| // of the arch we are compiling for. |
| if (Context.BuiltinInfo.isTSBuiltin(BuiltinID)) { |
| switch (Context.getTargetInfo().getTriple().getArch()) { |
| case llvm::Triple::arm: |
| case llvm::Triple::armeb: |
| case llvm::Triple::thumb: |
| case llvm::Triple::thumbeb: |
| if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| case llvm::Triple::aarch64: |
| case llvm::Triple::aarch64_be: |
| if (CheckAArch64BuiltinFunctionCall(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| case llvm::Triple::hexagon: |
| if (CheckHexagonBuiltinFunctionCall(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| case llvm::Triple::mips: |
| case llvm::Triple::mipsel: |
| case llvm::Triple::mips64: |
| case llvm::Triple::mips64el: |
| if (CheckMipsBuiltinFunctionCall(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| case llvm::Triple::systemz: |
| if (CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| case llvm::Triple::x86: |
| case llvm::Triple::x86_64: |
| if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| case llvm::Triple::ppc: |
| case llvm::Triple::ppc64: |
| case llvm::Triple::ppc64le: |
| if (CheckPPCBuiltinFunctionCall(BuiltinID, TheCall)) |
| return ExprError(); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| 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; |
| } |
| 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; |
| } |
| llvm_unreachable("Invalid NeonTypeFlag!"); |
| } |
| |
| bool Sema::CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { |
| 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 (SemaBuiltinConstantArg(TheCall, ImmArg, Result)) |
| return true; |
| |
| TV = Result.getLimitedValue(64); |
| if ((TV > 63) || (mask & (1ULL << TV)) == 0) |
| return Diag(TheCall->getLocStart(), 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 = Context.getTargetInfo().getTriple().getArch(); |
| bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 || |
| Arch == llvm::Triple::aarch64_be; |
| bool IsInt64Long = |
| Context.getTargetInfo().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->getLocStart(), 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 SemaBuiltinConstantArgRange(TheCall, i, l, u + l); |
| } |
| |
| 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(*this, 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->getLocStart(), diag::err_atomic_builtin_must_be_pointer) |
| << PointerArg->getType() << 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->getLocStart(), 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->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intfltptr) |
| << PointerArg->getType() << 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->getLocStart(), 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->getLocStart(), 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(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 SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) || |
| SemaBuiltinConstantArgRange(TheCall, 2, 0, 1); |
| } |
| |
| if (BuiltinID == ARM::BI__builtin_arm_rsr64 || |
| BuiltinID == ARM::BI__builtin_arm_wsr64) |
| return SemaBuiltinARMSpecialReg(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 SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true); |
| |
| if (CheckNeonBuiltinFunctionCall(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 SemaBuiltinConstantArgRange(TheCall, 1, 1, 32); |
| case ARM::BI__builtin_arm_usat: |
| return SemaBuiltinConstantArgRange(TheCall, 1, 0, 31); |
| case ARM::BI__builtin_arm_ssat16: |
| return SemaBuiltinConstantArgRange(TheCall, 1, 1, 16); |
| case ARM::BI__builtin_arm_usat16: |
| return SemaBuiltinConstantArgRange(TheCall, 1, 0, 15); |
| case ARM::BI__builtin_arm_vcvtr_f: |
| case ARM::BI__builtin_arm_vcvtr_d: |
| return SemaBuiltinConstantArgRange(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 SemaBuiltinConstantArgRange(TheCall, 0, 0, 15); |
| } |
| } |
| |
| bool Sema::CheckAArch64BuiltinFunctionCall(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 SemaBuiltinConstantArgRange(TheCall, 1, 0, 1) || |
| SemaBuiltinConstantArgRange(TheCall, 2, 0, 2) || |
| SemaBuiltinConstantArgRange(TheCall, 3, 0, 1) || |
| SemaBuiltinConstantArgRange(TheCall, 4, 0, 1); |
| } |
| |
| if (BuiltinID == AArch64::BI__builtin_arm_rsr64 || |
| BuiltinID == AArch64::BI__builtin_arm_wsr64) |
| return SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true); |
| |
| 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 SemaBuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true); |
| |
| if (CheckNeonBuiltinFunctionCall(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; |
| } |
| |
| return SemaBuiltinConstantArgRange(TheCall, i, l, u + l); |
| } |
| |
| bool Sema::CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall) { |
| static const std::map<unsigned, std::vector<StringRef>> ValidCPU = { |
| { Hexagon::BI__builtin_HEXAGON_A6_vcmpbeq_notany, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_A6_vminub_RdP, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffb, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_M6_vabsdiffub, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_nac, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_p_xacc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_nac, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_rol_i_r_xacc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_vsplatrbp, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_vtrunehb_ppp, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_S6_vtrunohb_ppp, {"v62", "v65"} }, |
| }; |
| |
| static const std::map<unsigned, std::vector<StringRef>> ValidHVX = { |
| { Hexagon::BI__builtin_HEXAGON_V6_extractw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_extractw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_hi, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_hi_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_lo, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_lo_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_lvsplatb_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_lvsplath, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_lvsplath_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_lvsplatw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_and_n_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_not, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_not_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_or_n_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_scalar2v2_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_pred_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_shuffeqh_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_shuffeqw_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsb, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsb_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsb_sat_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffub_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffuh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsdiffw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsh_sat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vabsw_sat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddb_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddbsat_dv_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddclbh_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddclbw_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddh_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddhsat_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddhw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddhw_acc_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddubh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddubh_acc_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddubsat_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddububb_sat_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduhsat_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduhw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduhw_acc_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vadduwsat_dv_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddw_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaddwsat_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_valignb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_valignb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_valignbi, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_valignbi_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vand, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vand_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandnqrt_acc_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandqrt, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandqrt_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandvnqv_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandvqv, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandvqv_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandvrt, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vandvrt_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslh_acc_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslhv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslhv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslw_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslwv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vaslwv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrh_acc_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhbrndsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhbsat_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhubrndsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhubsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrhv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasruhubrndsat_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasruhubsat_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhrndsat_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasruwuhsat_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrw_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwhrndsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwhsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhrndsat_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwuhsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vasrwv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vassign, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vassign_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vassignp, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vassignp_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgb, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgb_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgbrnd_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavghrnd_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgub, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgub_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgubrnd_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavguh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavguh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavguhrnd_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavguw, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavguw_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavguwrnd_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vavgwrnd_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vcl0h, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vcl0h_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vcl0w, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vcl0w_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vcombine, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vcombine_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vd0, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vd0_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdd0, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdd0_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdealb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdealb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdealb4w_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdealh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdealh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdealvdd_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdelta, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdelta_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpybus_dv_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhb_dv_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhisat_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsat_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsuisat_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhsusat_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdmpyhvsat_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vdsaduh_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqb_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqb_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqb_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqb_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqb_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqh_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqh_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqh_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqh_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqh_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqw_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqw_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqw_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqw_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_veqw_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtb_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtb_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtb_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgth, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgth_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgth_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgth_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgth_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgth_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgth_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtub, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtub_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtub_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtub_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtub_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuh_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtuw_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtw_and_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtw_or_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vgtw_xor_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vinsertwr_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlalignb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlalignb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlalignbi_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrb, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrb_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrhv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlsrwv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlut4, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlut4_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvbi_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_nm_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvvb_oracci_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwhi_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_nm_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vlutvwh_oracci_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxb, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxb_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxub, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxub_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxuh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmaxw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminb, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminb_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminub, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminub_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminuh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminuh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminw, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vminw_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabus, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabus_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabusv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabuu_acc_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpabuuv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpahb, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpahb_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpahhsat_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpauhb_acc_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpauhuhsat_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpsuhuhsat_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybus, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybus_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybusv_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpybv_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyewuh_64_128B, {"v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyh_acc_128B, {"v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsat_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhsrs_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhss_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhus_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhv_acc_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyhvsrs_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyieoh_128B, {"v60", "v62", "v65"} }, |
| { Hexagon::BI__builtin_HEXAGON_V6_vmpyiewh_acc, {"v60", "v62", "v65"} }, |
|