1ed35a92cSVlad Serebrennikov //===------ SemaARM.cpp ---------- ARM target-specific routines -----------===// 2ed35a92cSVlad Serebrennikov // 3ed35a92cSVlad Serebrennikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ed35a92cSVlad Serebrennikov // See https://llvm.org/LICENSE.txt for license information. 5ed35a92cSVlad Serebrennikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ed35a92cSVlad Serebrennikov // 7ed35a92cSVlad Serebrennikov //===----------------------------------------------------------------------===// 8ed35a92cSVlad Serebrennikov // 9ed35a92cSVlad Serebrennikov // This file implements semantic analysis functions specific to ARM. 10ed35a92cSVlad Serebrennikov // 11ed35a92cSVlad Serebrennikov //===----------------------------------------------------------------------===// 12ed35a92cSVlad Serebrennikov 13ed35a92cSVlad Serebrennikov #include "clang/Sema/SemaARM.h" 14ed35a92cSVlad Serebrennikov #include "clang/Basic/DiagnosticSema.h" 15ed35a92cSVlad Serebrennikov #include "clang/Basic/TargetBuiltins.h" 1627d37ee4SVlad Serebrennikov #include "clang/Basic/TargetInfo.h" 17ed35a92cSVlad Serebrennikov #include "clang/Sema/Initialization.h" 186b755b0cSVlad Serebrennikov #include "clang/Sema/ParsedAttr.h" 19ed35a92cSVlad Serebrennikov #include "clang/Sema/Sema.h" 20ed35a92cSVlad Serebrennikov 21ed35a92cSVlad Serebrennikov namespace clang { 22ed35a92cSVlad Serebrennikov 23ed35a92cSVlad Serebrennikov SemaARM::SemaARM(Sema &S) : SemaBase(S) {} 24ed35a92cSVlad Serebrennikov 25ed35a92cSVlad Serebrennikov /// BuiltinARMMemoryTaggingCall - Handle calls of memory tagging extensions 26ed35a92cSVlad Serebrennikov bool SemaARM::BuiltinARMMemoryTaggingCall(unsigned BuiltinID, 27ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 28ed35a92cSVlad Serebrennikov ASTContext &Context = getASTContext(); 29ed35a92cSVlad Serebrennikov 30ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_irg) { 31ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 2)) 32ed35a92cSVlad Serebrennikov return true; 33ed35a92cSVlad Serebrennikov Expr *Arg0 = TheCall->getArg(0); 34ed35a92cSVlad Serebrennikov Expr *Arg1 = TheCall->getArg(1); 35ed35a92cSVlad Serebrennikov 36ed35a92cSVlad Serebrennikov ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0); 37ed35a92cSVlad Serebrennikov if (FirstArg.isInvalid()) 38ed35a92cSVlad Serebrennikov return true; 39ed35a92cSVlad Serebrennikov QualType FirstArgType = FirstArg.get()->getType(); 40ed35a92cSVlad Serebrennikov if (!FirstArgType->isAnyPointerType()) 41ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer) 42ed35a92cSVlad Serebrennikov << "first" << FirstArgType << Arg0->getSourceRange(); 43ed35a92cSVlad Serebrennikov TheCall->setArg(0, FirstArg.get()); 44ed35a92cSVlad Serebrennikov 45ed35a92cSVlad Serebrennikov ExprResult SecArg = SemaRef.DefaultLvalueConversion(Arg1); 46ed35a92cSVlad Serebrennikov if (SecArg.isInvalid()) 47ed35a92cSVlad Serebrennikov return true; 48ed35a92cSVlad Serebrennikov QualType SecArgType = SecArg.get()->getType(); 49ed35a92cSVlad Serebrennikov if (!SecArgType->isIntegerType()) 50ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer) 51ed35a92cSVlad Serebrennikov << "second" << SecArgType << Arg1->getSourceRange(); 52ed35a92cSVlad Serebrennikov 53ed35a92cSVlad Serebrennikov // Derive the return type from the pointer argument. 54ed35a92cSVlad Serebrennikov TheCall->setType(FirstArgType); 55ed35a92cSVlad Serebrennikov return false; 56ed35a92cSVlad Serebrennikov } 57ed35a92cSVlad Serebrennikov 58ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_addg) { 59ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 2)) 60ed35a92cSVlad Serebrennikov return true; 61ed35a92cSVlad Serebrennikov 62ed35a92cSVlad Serebrennikov Expr *Arg0 = TheCall->getArg(0); 63ed35a92cSVlad Serebrennikov ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0); 64ed35a92cSVlad Serebrennikov if (FirstArg.isInvalid()) 65ed35a92cSVlad Serebrennikov return true; 66ed35a92cSVlad Serebrennikov QualType FirstArgType = FirstArg.get()->getType(); 67ed35a92cSVlad Serebrennikov if (!FirstArgType->isAnyPointerType()) 68ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer) 69ed35a92cSVlad Serebrennikov << "first" << FirstArgType << Arg0->getSourceRange(); 70ed35a92cSVlad Serebrennikov TheCall->setArg(0, FirstArg.get()); 71ed35a92cSVlad Serebrennikov 72ed35a92cSVlad Serebrennikov // Derive the return type from the pointer argument. 73ed35a92cSVlad Serebrennikov TheCall->setType(FirstArgType); 74ed35a92cSVlad Serebrennikov 75ed35a92cSVlad Serebrennikov // Second arg must be an constant in range [0,15] 76ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15); 77ed35a92cSVlad Serebrennikov } 78ed35a92cSVlad Serebrennikov 79ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_gmi) { 80ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 2)) 81ed35a92cSVlad Serebrennikov return true; 82ed35a92cSVlad Serebrennikov Expr *Arg0 = TheCall->getArg(0); 83ed35a92cSVlad Serebrennikov Expr *Arg1 = TheCall->getArg(1); 84ed35a92cSVlad Serebrennikov 85ed35a92cSVlad Serebrennikov ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0); 86ed35a92cSVlad Serebrennikov if (FirstArg.isInvalid()) 87ed35a92cSVlad Serebrennikov return true; 88ed35a92cSVlad Serebrennikov QualType FirstArgType = FirstArg.get()->getType(); 89ed35a92cSVlad Serebrennikov if (!FirstArgType->isAnyPointerType()) 90ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer) 91ed35a92cSVlad Serebrennikov << "first" << FirstArgType << Arg0->getSourceRange(); 92ed35a92cSVlad Serebrennikov 93ed35a92cSVlad Serebrennikov QualType SecArgType = Arg1->getType(); 94ed35a92cSVlad Serebrennikov if (!SecArgType->isIntegerType()) 95ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_integer) 96ed35a92cSVlad Serebrennikov << "second" << SecArgType << Arg1->getSourceRange(); 97ed35a92cSVlad Serebrennikov TheCall->setType(Context.IntTy); 98ed35a92cSVlad Serebrennikov return false; 99ed35a92cSVlad Serebrennikov } 100ed35a92cSVlad Serebrennikov 101ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_ldg || 102ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_stg) { 103ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, 1)) 104ed35a92cSVlad Serebrennikov return true; 105ed35a92cSVlad Serebrennikov Expr *Arg0 = TheCall->getArg(0); 106ed35a92cSVlad Serebrennikov ExprResult FirstArg = SemaRef.DefaultFunctionArrayLvalueConversion(Arg0); 107ed35a92cSVlad Serebrennikov if (FirstArg.isInvalid()) 108ed35a92cSVlad Serebrennikov return true; 109ed35a92cSVlad Serebrennikov 110ed35a92cSVlad Serebrennikov QualType FirstArgType = FirstArg.get()->getType(); 111ed35a92cSVlad Serebrennikov if (!FirstArgType->isAnyPointerType()) 112ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_must_be_pointer) 113ed35a92cSVlad Serebrennikov << "first" << FirstArgType << Arg0->getSourceRange(); 114ed35a92cSVlad Serebrennikov TheCall->setArg(0, FirstArg.get()); 115ed35a92cSVlad Serebrennikov 116ed35a92cSVlad Serebrennikov // Derive the return type from the pointer argument. 117ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_ldg) 118ed35a92cSVlad Serebrennikov TheCall->setType(FirstArgType); 119ed35a92cSVlad Serebrennikov return false; 120ed35a92cSVlad Serebrennikov } 121ed35a92cSVlad Serebrennikov 122ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_subp) { 123ed35a92cSVlad Serebrennikov Expr *ArgA = TheCall->getArg(0); 124ed35a92cSVlad Serebrennikov Expr *ArgB = TheCall->getArg(1); 125ed35a92cSVlad Serebrennikov 126ed35a92cSVlad Serebrennikov ExprResult ArgExprA = SemaRef.DefaultFunctionArrayLvalueConversion(ArgA); 127ed35a92cSVlad Serebrennikov ExprResult ArgExprB = SemaRef.DefaultFunctionArrayLvalueConversion(ArgB); 128ed35a92cSVlad Serebrennikov 129ed35a92cSVlad Serebrennikov if (ArgExprA.isInvalid() || ArgExprB.isInvalid()) 130ed35a92cSVlad Serebrennikov return true; 131ed35a92cSVlad Serebrennikov 132ed35a92cSVlad Serebrennikov QualType ArgTypeA = ArgExprA.get()->getType(); 133ed35a92cSVlad Serebrennikov QualType ArgTypeB = ArgExprB.get()->getType(); 134ed35a92cSVlad Serebrennikov 135ed35a92cSVlad Serebrennikov auto isNull = [&](Expr *E) -> bool { 136ed35a92cSVlad Serebrennikov return E->isNullPointerConstant(Context, 137ed35a92cSVlad Serebrennikov Expr::NPC_ValueDependentIsNotNull); 138ed35a92cSVlad Serebrennikov }; 139ed35a92cSVlad Serebrennikov 140ed35a92cSVlad Serebrennikov // argument should be either a pointer or null 141ed35a92cSVlad Serebrennikov if (!ArgTypeA->isAnyPointerType() && !isNull(ArgA)) 142ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer) 143ed35a92cSVlad Serebrennikov << "first" << ArgTypeA << ArgA->getSourceRange(); 144ed35a92cSVlad Serebrennikov 145ed35a92cSVlad Serebrennikov if (!ArgTypeB->isAnyPointerType() && !isNull(ArgB)) 146ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_arg_null_or_pointer) 147ed35a92cSVlad Serebrennikov << "second" << ArgTypeB << ArgB->getSourceRange(); 148ed35a92cSVlad Serebrennikov 149ed35a92cSVlad Serebrennikov // Ensure Pointee types are compatible 150ed35a92cSVlad Serebrennikov if (ArgTypeA->isAnyPointerType() && !isNull(ArgA) && 151ed35a92cSVlad Serebrennikov ArgTypeB->isAnyPointerType() && !isNull(ArgB)) { 152ed35a92cSVlad Serebrennikov QualType pointeeA = ArgTypeA->getPointeeType(); 153ed35a92cSVlad Serebrennikov QualType pointeeB = ArgTypeB->getPointeeType(); 154ed35a92cSVlad Serebrennikov if (!Context.typesAreCompatible( 155ed35a92cSVlad Serebrennikov Context.getCanonicalType(pointeeA).getUnqualifiedType(), 156ed35a92cSVlad Serebrennikov Context.getCanonicalType(pointeeB).getUnqualifiedType())) { 157ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), 158ed35a92cSVlad Serebrennikov diag::err_typecheck_sub_ptr_compatible) 159ed35a92cSVlad Serebrennikov << ArgTypeA << ArgTypeB << ArgA->getSourceRange() 160ed35a92cSVlad Serebrennikov << ArgB->getSourceRange(); 161ed35a92cSVlad Serebrennikov } 162ed35a92cSVlad Serebrennikov } 163ed35a92cSVlad Serebrennikov 164ed35a92cSVlad Serebrennikov // at least one argument should be pointer type 165ed35a92cSVlad Serebrennikov if (!ArgTypeA->isAnyPointerType() && !ArgTypeB->isAnyPointerType()) 166ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_memtag_any2arg_pointer) 167ed35a92cSVlad Serebrennikov << ArgTypeA << ArgTypeB << ArgA->getSourceRange(); 168ed35a92cSVlad Serebrennikov 169ed35a92cSVlad Serebrennikov if (isNull(ArgA)) // adopt type of the other pointer 170ed35a92cSVlad Serebrennikov ArgExprA = 171ed35a92cSVlad Serebrennikov SemaRef.ImpCastExprToType(ArgExprA.get(), ArgTypeB, CK_NullToPointer); 172ed35a92cSVlad Serebrennikov 173ed35a92cSVlad Serebrennikov if (isNull(ArgB)) 174ed35a92cSVlad Serebrennikov ArgExprB = 175ed35a92cSVlad Serebrennikov SemaRef.ImpCastExprToType(ArgExprB.get(), ArgTypeA, CK_NullToPointer); 176ed35a92cSVlad Serebrennikov 177ed35a92cSVlad Serebrennikov TheCall->setArg(0, ArgExprA.get()); 178ed35a92cSVlad Serebrennikov TheCall->setArg(1, ArgExprB.get()); 179ed35a92cSVlad Serebrennikov TheCall->setType(Context.LongLongTy); 180ed35a92cSVlad Serebrennikov return false; 181ed35a92cSVlad Serebrennikov } 182ed35a92cSVlad Serebrennikov assert(false && "Unhandled ARM MTE intrinsic"); 183ed35a92cSVlad Serebrennikov return true; 184ed35a92cSVlad Serebrennikov } 185ed35a92cSVlad Serebrennikov 186ed35a92cSVlad Serebrennikov /// BuiltinARMSpecialReg - Handle a check if argument ArgNum of CallExpr 187ed35a92cSVlad Serebrennikov /// TheCall is an ARM/AArch64 special register string literal. 188ed35a92cSVlad Serebrennikov bool SemaARM::BuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, 189ed35a92cSVlad Serebrennikov int ArgNum, unsigned ExpectedFieldNum, 190ed35a92cSVlad Serebrennikov bool AllowName) { 191ed35a92cSVlad Serebrennikov bool IsARMBuiltin = BuiltinID == ARM::BI__builtin_arm_rsr64 || 192ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_wsr64 || 193ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_rsr || 194ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_rsrp || 195ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_wsr || 196ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_wsrp; 197ed35a92cSVlad Serebrennikov bool IsAArch64Builtin = BuiltinID == AArch64::BI__builtin_arm_rsr64 || 198ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsr64 || 199ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_rsr128 || 200ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsr128 || 201ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_rsr || 202ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_rsrp || 203ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsr || 204ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsrp; 205ed35a92cSVlad Serebrennikov assert((IsARMBuiltin || IsAArch64Builtin) && "Unexpected ARM builtin."); 206ed35a92cSVlad Serebrennikov 207ed35a92cSVlad Serebrennikov // We can't check the value of a dependent argument. 208ed35a92cSVlad Serebrennikov Expr *Arg = TheCall->getArg(ArgNum); 209ed35a92cSVlad Serebrennikov if (Arg->isTypeDependent() || Arg->isValueDependent()) 210ed35a92cSVlad Serebrennikov return false; 211ed35a92cSVlad Serebrennikov 212ed35a92cSVlad Serebrennikov // Check if the argument is a string literal. 213ed35a92cSVlad Serebrennikov if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) 214ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal) 215ed35a92cSVlad Serebrennikov << Arg->getSourceRange(); 216ed35a92cSVlad Serebrennikov 217ed35a92cSVlad Serebrennikov // Check the type of special register given. 218ed35a92cSVlad Serebrennikov StringRef Reg = cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString(); 219ed35a92cSVlad Serebrennikov SmallVector<StringRef, 6> Fields; 220ed35a92cSVlad Serebrennikov Reg.split(Fields, ":"); 221ed35a92cSVlad Serebrennikov 222ed35a92cSVlad Serebrennikov if (Fields.size() != ExpectedFieldNum && !(AllowName && Fields.size() == 1)) 223ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg) 224ed35a92cSVlad Serebrennikov << Arg->getSourceRange(); 225ed35a92cSVlad Serebrennikov 226ed35a92cSVlad Serebrennikov // If the string is the name of a register then we cannot check that it is 227ed35a92cSVlad Serebrennikov // valid here but if the string is of one the forms described in ACLE then we 228ed35a92cSVlad Serebrennikov // can check that the supplied fields are integers and within the valid 229ed35a92cSVlad Serebrennikov // ranges. 230ed35a92cSVlad Serebrennikov if (Fields.size() > 1) { 231ed35a92cSVlad Serebrennikov bool FiveFields = Fields.size() == 5; 232ed35a92cSVlad Serebrennikov 233ed35a92cSVlad Serebrennikov bool ValidString = true; 234ed35a92cSVlad Serebrennikov if (IsARMBuiltin) { 235ed35a92cSVlad Serebrennikov ValidString &= Fields[0].starts_with_insensitive("cp") || 236ed35a92cSVlad Serebrennikov Fields[0].starts_with_insensitive("p"); 237ed35a92cSVlad Serebrennikov if (ValidString) 238ed35a92cSVlad Serebrennikov Fields[0] = Fields[0].drop_front( 239ed35a92cSVlad Serebrennikov Fields[0].starts_with_insensitive("cp") ? 2 : 1); 240ed35a92cSVlad Serebrennikov 241ed35a92cSVlad Serebrennikov ValidString &= Fields[2].starts_with_insensitive("c"); 242ed35a92cSVlad Serebrennikov if (ValidString) 243ed35a92cSVlad Serebrennikov Fields[2] = Fields[2].drop_front(1); 244ed35a92cSVlad Serebrennikov 245ed35a92cSVlad Serebrennikov if (FiveFields) { 246ed35a92cSVlad Serebrennikov ValidString &= Fields[3].starts_with_insensitive("c"); 247ed35a92cSVlad Serebrennikov if (ValidString) 248ed35a92cSVlad Serebrennikov Fields[3] = Fields[3].drop_front(1); 249ed35a92cSVlad Serebrennikov } 250ed35a92cSVlad Serebrennikov } 251ed35a92cSVlad Serebrennikov 252ed35a92cSVlad Serebrennikov SmallVector<int, 5> Ranges; 253ed35a92cSVlad Serebrennikov if (FiveFields) 254ed35a92cSVlad Serebrennikov Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 15, 15, 7}); 255ed35a92cSVlad Serebrennikov else 256ed35a92cSVlad Serebrennikov Ranges.append({15, 7, 15}); 257ed35a92cSVlad Serebrennikov 258ed35a92cSVlad Serebrennikov for (unsigned i = 0; i < Fields.size(); ++i) { 259ed35a92cSVlad Serebrennikov int IntField; 260ed35a92cSVlad Serebrennikov ValidString &= !Fields[i].getAsInteger(10, IntField); 261ed35a92cSVlad Serebrennikov ValidString &= (IntField >= 0 && IntField <= Ranges[i]); 262ed35a92cSVlad Serebrennikov } 263ed35a92cSVlad Serebrennikov 264ed35a92cSVlad Serebrennikov if (!ValidString) 265ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_arm_invalid_specialreg) 266ed35a92cSVlad Serebrennikov << Arg->getSourceRange(); 267ed35a92cSVlad Serebrennikov } else if (IsAArch64Builtin && Fields.size() == 1) { 268ed35a92cSVlad Serebrennikov // This code validates writes to PSTATE registers. 269ed35a92cSVlad Serebrennikov 270ed35a92cSVlad Serebrennikov // Not a write. 271ed35a92cSVlad Serebrennikov if (TheCall->getNumArgs() != 2) 272ed35a92cSVlad Serebrennikov return false; 273ed35a92cSVlad Serebrennikov 274ed35a92cSVlad Serebrennikov // The 128-bit system register accesses do not touch PSTATE. 275ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_rsr128 || 276ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsr128) 277ed35a92cSVlad Serebrennikov return false; 278ed35a92cSVlad Serebrennikov 279ed35a92cSVlad Serebrennikov // These are the named PSTATE accesses using "MSR (immediate)" instructions, 280ed35a92cSVlad Serebrennikov // along with the upper limit on the immediates allowed. 281ed35a92cSVlad Serebrennikov auto MaxLimit = llvm::StringSwitch<std::optional<unsigned>>(Reg) 282ed35a92cSVlad Serebrennikov .CaseLower("spsel", 15) 283ed35a92cSVlad Serebrennikov .CaseLower("daifclr", 15) 284ed35a92cSVlad Serebrennikov .CaseLower("daifset", 15) 285ed35a92cSVlad Serebrennikov .CaseLower("pan", 15) 286ed35a92cSVlad Serebrennikov .CaseLower("uao", 15) 287ed35a92cSVlad Serebrennikov .CaseLower("dit", 15) 288ed35a92cSVlad Serebrennikov .CaseLower("ssbs", 15) 289ed35a92cSVlad Serebrennikov .CaseLower("tco", 15) 290ed35a92cSVlad Serebrennikov .CaseLower("allint", 1) 291ed35a92cSVlad Serebrennikov .CaseLower("pm", 1) 292ed35a92cSVlad Serebrennikov .Default(std::nullopt); 293ed35a92cSVlad Serebrennikov 294ed35a92cSVlad Serebrennikov // If this is not a named PSTATE, just continue without validating, as this 295ed35a92cSVlad Serebrennikov // will be lowered to an "MSR (register)" instruction directly 296ed35a92cSVlad Serebrennikov if (!MaxLimit) 297ed35a92cSVlad Serebrennikov return false; 298ed35a92cSVlad Serebrennikov 299ed35a92cSVlad Serebrennikov // Here we only allow constants in the range for that pstate, as required by 300ed35a92cSVlad Serebrennikov // the ACLE. 301ed35a92cSVlad Serebrennikov // 302ed35a92cSVlad Serebrennikov // While clang also accepts the names of system registers in its ACLE 303ed35a92cSVlad Serebrennikov // intrinsics, we prevent this with the PSTATE names used in MSR (immediate) 304ed35a92cSVlad Serebrennikov // as the value written via a register is different to the value used as an 305ed35a92cSVlad Serebrennikov // immediate to have the same effect. e.g., for the instruction `msr tco, 306ed35a92cSVlad Serebrennikov // x0`, it is bit 25 of register x0 that is written into PSTATE.TCO, but 307ed35a92cSVlad Serebrennikov // with `msr tco, #imm`, it is bit 0 of xN that is written into PSTATE.TCO. 308ed35a92cSVlad Serebrennikov // 309ed35a92cSVlad Serebrennikov // If a programmer wants to codegen the MSR (register) form of `msr tco, 310ed35a92cSVlad Serebrennikov // xN`, they can still do so by specifying the register using five 311ed35a92cSVlad Serebrennikov // colon-separated numbers in a string. 312ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, *MaxLimit); 313ed35a92cSVlad Serebrennikov } 314ed35a92cSVlad Serebrennikov 315ed35a92cSVlad Serebrennikov return false; 316ed35a92cSVlad Serebrennikov } 317ed35a92cSVlad Serebrennikov 318ed35a92cSVlad Serebrennikov /// getNeonEltType - Return the QualType corresponding to the elements of 319ed35a92cSVlad Serebrennikov /// the vector type specified by the NeonTypeFlags. This is used to check 320ed35a92cSVlad Serebrennikov /// the pointer arguments for Neon load/store intrinsics. 321ed35a92cSVlad Serebrennikov static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context, 322ed35a92cSVlad Serebrennikov bool IsPolyUnsigned, bool IsInt64Long) { 323ed35a92cSVlad Serebrennikov switch (Flags.getEltType()) { 324ed35a92cSVlad Serebrennikov case NeonTypeFlags::Int8: 325ed35a92cSVlad Serebrennikov return Flags.isUnsigned() ? Context.UnsignedCharTy : Context.SignedCharTy; 326ed35a92cSVlad Serebrennikov case NeonTypeFlags::Int16: 327ed35a92cSVlad Serebrennikov return Flags.isUnsigned() ? Context.UnsignedShortTy : Context.ShortTy; 328ed35a92cSVlad Serebrennikov case NeonTypeFlags::Int32: 329ed35a92cSVlad Serebrennikov return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy; 330ed35a92cSVlad Serebrennikov case NeonTypeFlags::Int64: 331ed35a92cSVlad Serebrennikov if (IsInt64Long) 332ed35a92cSVlad Serebrennikov return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy; 333ed35a92cSVlad Serebrennikov else 334ed35a92cSVlad Serebrennikov return Flags.isUnsigned() ? Context.UnsignedLongLongTy 335ed35a92cSVlad Serebrennikov : Context.LongLongTy; 336ed35a92cSVlad Serebrennikov case NeonTypeFlags::Poly8: 337ed35a92cSVlad Serebrennikov return IsPolyUnsigned ? Context.UnsignedCharTy : Context.SignedCharTy; 338ed35a92cSVlad Serebrennikov case NeonTypeFlags::Poly16: 339ed35a92cSVlad Serebrennikov return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy; 340ed35a92cSVlad Serebrennikov case NeonTypeFlags::Poly64: 341ed35a92cSVlad Serebrennikov if (IsInt64Long) 342ed35a92cSVlad Serebrennikov return Context.UnsignedLongTy; 343ed35a92cSVlad Serebrennikov else 344ed35a92cSVlad Serebrennikov return Context.UnsignedLongLongTy; 345ed35a92cSVlad Serebrennikov case NeonTypeFlags::Poly128: 346ed35a92cSVlad Serebrennikov break; 347ed35a92cSVlad Serebrennikov case NeonTypeFlags::Float16: 348ed35a92cSVlad Serebrennikov return Context.HalfTy; 349ed35a92cSVlad Serebrennikov case NeonTypeFlags::Float32: 350ed35a92cSVlad Serebrennikov return Context.FloatTy; 351ed35a92cSVlad Serebrennikov case NeonTypeFlags::Float64: 352ed35a92cSVlad Serebrennikov return Context.DoubleTy; 353ed35a92cSVlad Serebrennikov case NeonTypeFlags::BFloat16: 354ed35a92cSVlad Serebrennikov return Context.BFloat16Ty; 355*87103a01SMomchil Velikov case NeonTypeFlags::MFloat8: 356*87103a01SMomchil Velikov return Context.MFloat8Ty; 357ed35a92cSVlad Serebrennikov } 358ed35a92cSVlad Serebrennikov llvm_unreachable("Invalid NeonTypeFlag!"); 359ed35a92cSVlad Serebrennikov } 360ed35a92cSVlad Serebrennikov 361ed35a92cSVlad Serebrennikov enum ArmSMEState : unsigned { 362ed35a92cSVlad Serebrennikov ArmNoState = 0, 363ed35a92cSVlad Serebrennikov 364ed35a92cSVlad Serebrennikov ArmInZA = 0b01, 365ed35a92cSVlad Serebrennikov ArmOutZA = 0b10, 366ed35a92cSVlad Serebrennikov ArmInOutZA = 0b11, 367ed35a92cSVlad Serebrennikov ArmZAMask = 0b11, 368ed35a92cSVlad Serebrennikov 369ed35a92cSVlad Serebrennikov ArmInZT0 = 0b01 << 2, 370ed35a92cSVlad Serebrennikov ArmOutZT0 = 0b10 << 2, 371ed35a92cSVlad Serebrennikov ArmInOutZT0 = 0b11 << 2, 372ed35a92cSVlad Serebrennikov ArmZT0Mask = 0b11 << 2 373ed35a92cSVlad Serebrennikov }; 374ed35a92cSVlad Serebrennikov 3751f70fcefSSpencerAbson bool SemaARM::CheckImmediateArg(CallExpr *TheCall, unsigned CheckTy, 3761f70fcefSSpencerAbson unsigned ArgIdx, unsigned EltBitWidth, 377a3744f06SSpencer Abson unsigned ContainerBitWidth) { 3781f70fcefSSpencerAbson // Function that checks whether the operand (ArgIdx) is an immediate 3791f70fcefSSpencerAbson // that is one of a given set of values. 3801f70fcefSSpencerAbson auto CheckImmediateInSet = [&](std::initializer_list<int64_t> Set, 381ed35a92cSVlad Serebrennikov int ErrDiag) -> bool { 382ed35a92cSVlad Serebrennikov // We can't check the value of a dependent argument. 3831f70fcefSSpencerAbson Expr *Arg = TheCall->getArg(ArgIdx); 384ed35a92cSVlad Serebrennikov if (Arg->isTypeDependent() || Arg->isValueDependent()) 385ed35a92cSVlad Serebrennikov return false; 386ed35a92cSVlad Serebrennikov 387ed35a92cSVlad Serebrennikov // Check constant-ness first. 388ed35a92cSVlad Serebrennikov llvm::APSInt Imm; 3891f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArg(TheCall, ArgIdx, Imm)) 390ed35a92cSVlad Serebrennikov return true; 391ed35a92cSVlad Serebrennikov 3921f70fcefSSpencerAbson if (std::find(Set.begin(), Set.end(), Imm.getSExtValue()) == Set.end()) 393ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange(); 394ed35a92cSVlad Serebrennikov return false; 395ed35a92cSVlad Serebrennikov }; 396ed35a92cSVlad Serebrennikov 3971f70fcefSSpencerAbson switch ((ImmCheckType)CheckTy) { 3981f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_31: 3991f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 31)) 4001f70fcefSSpencerAbson return true; 401ed35a92cSVlad Serebrennikov break; 4021f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_13: 4031f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 13)) 4041f70fcefSSpencerAbson return true; 405ed35a92cSVlad Serebrennikov break; 4061f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_63: 4071f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 63)) 4081f70fcefSSpencerAbson return true; 409ed35a92cSVlad Serebrennikov break; 4101f70fcefSSpencerAbson case ImmCheckType::ImmCheck1_16: 4111f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 16)) 4121f70fcefSSpencerAbson return true; 413ed35a92cSVlad Serebrennikov break; 4141f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_7: 4151f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 7)) 4161f70fcefSSpencerAbson return true; 417ed35a92cSVlad Serebrennikov break; 4181f70fcefSSpencerAbson case ImmCheckType::ImmCheck1_1: 4191f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 1)) 4201f70fcefSSpencerAbson return true; 421ed35a92cSVlad Serebrennikov break; 4221f70fcefSSpencerAbson case ImmCheckType::ImmCheck1_3: 4231f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 3)) 4241f70fcefSSpencerAbson return true; 425ed35a92cSVlad Serebrennikov break; 4261f70fcefSSpencerAbson case ImmCheckType::ImmCheck1_7: 4271f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 7)) 4281f70fcefSSpencerAbson return true; 429ed35a92cSVlad Serebrennikov break; 4301f70fcefSSpencerAbson case ImmCheckType::ImmCheckExtract: 4311f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 4321f70fcefSSpencerAbson (2048 / EltBitWidth) - 1)) 4331f70fcefSSpencerAbson return true; 434ed35a92cSVlad Serebrennikov break; 4351f70fcefSSpencerAbson case ImmCheckType::ImmCheckCvt: 4361f70fcefSSpencerAbson case ImmCheckType::ImmCheckShiftRight: 4371f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth)) 4381f70fcefSSpencerAbson return true; 439ed35a92cSVlad Serebrennikov break; 4401f70fcefSSpencerAbson case ImmCheckType::ImmCheckShiftRightNarrow: 4411f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, EltBitWidth / 2)) 4421f70fcefSSpencerAbson return true; 443ed35a92cSVlad Serebrennikov break; 4441f70fcefSSpencerAbson case ImmCheckType::ImmCheckShiftLeft: 4451f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1)) 4461f70fcefSSpencerAbson return true; 447ed35a92cSVlad Serebrennikov break; 4481f70fcefSSpencerAbson case ImmCheckType::ImmCheckLaneIndex: 4491f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 450a3744f06SSpencer Abson (ContainerBitWidth / EltBitWidth) - 1)) 4511f70fcefSSpencerAbson return true; 452ed35a92cSVlad Serebrennikov break; 4531f70fcefSSpencerAbson case ImmCheckType::ImmCheckLaneIndexCompRotate: 454a3744f06SSpencer Abson if (SemaRef.BuiltinConstantArgRange( 455a3744f06SSpencer Abson TheCall, ArgIdx, 0, (ContainerBitWidth / (2 * EltBitWidth)) - 1)) 4561f70fcefSSpencerAbson return true; 457ed35a92cSVlad Serebrennikov break; 4581f70fcefSSpencerAbson case ImmCheckType::ImmCheckLaneIndexDot: 459a3744f06SSpencer Abson if (SemaRef.BuiltinConstantArgRange( 460a3744f06SSpencer Abson TheCall, ArgIdx, 0, (ContainerBitWidth / (4 * EltBitWidth)) - 1)) 4611f70fcefSSpencerAbson return true; 462ed35a92cSVlad Serebrennikov break; 4631f70fcefSSpencerAbson case ImmCheckType::ImmCheckComplexRot90_270: 4641f70fcefSSpencerAbson if (CheckImmediateInSet({90, 270}, diag::err_rotation_argument_to_cadd)) 4651f70fcefSSpencerAbson return true; 4661f70fcefSSpencerAbson break; 4671f70fcefSSpencerAbson case ImmCheckType::ImmCheckComplexRotAll90: 4681f70fcefSSpencerAbson if (CheckImmediateInSet({0, 90, 180, 270}, 469ed35a92cSVlad Serebrennikov diag::err_rotation_argument_to_cmla)) 4701f70fcefSSpencerAbson return true; 471ed35a92cSVlad Serebrennikov break; 4721f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_1: 4731f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 1)) 4741f70fcefSSpencerAbson return true; 475ed35a92cSVlad Serebrennikov break; 4761f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_2: 4771f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 2)) 4781f70fcefSSpencerAbson return true; 479ed35a92cSVlad Serebrennikov break; 4801f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_3: 4811f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 3)) 4821f70fcefSSpencerAbson return true; 483ed35a92cSVlad Serebrennikov break; 4841f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_0: 4851f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 0)) 4861f70fcefSSpencerAbson return true; 487ed35a92cSVlad Serebrennikov break; 4881f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_15: 4891f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 15)) 4901f70fcefSSpencerAbson return true; 491ed35a92cSVlad Serebrennikov break; 4921f70fcefSSpencerAbson case ImmCheckType::ImmCheck0_255: 4931f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, 255)) 4941f70fcefSSpencerAbson return true; 495ed35a92cSVlad Serebrennikov break; 4961f70fcefSSpencerAbson case ImmCheckType::ImmCheck1_32: 4971f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 32)) 4981f70fcefSSpencerAbson return true; 4991f70fcefSSpencerAbson break; 5001f70fcefSSpencerAbson case ImmCheckType::ImmCheck1_64: 5011f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 1, 64)) 5021f70fcefSSpencerAbson return true; 5031f70fcefSSpencerAbson break; 5041f70fcefSSpencerAbson case ImmCheckType::ImmCheck2_4_Mul2: 5051f70fcefSSpencerAbson if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 2, 4) || 5061f70fcefSSpencerAbson SemaRef.BuiltinConstantArgMultiple(TheCall, ArgIdx, 2)) 5071f70fcefSSpencerAbson return true; 5081f70fcefSSpencerAbson break; 509ed35a92cSVlad Serebrennikov } 5101f70fcefSSpencerAbson return false; 5111f70fcefSSpencerAbson } 5121f70fcefSSpencerAbson 5131f70fcefSSpencerAbson bool SemaARM::PerformNeonImmChecks( 5141f70fcefSSpencerAbson CallExpr *TheCall, 5151f70fcefSSpencerAbson SmallVectorImpl<std::tuple<int, int, int, int>> &ImmChecks, 5161f70fcefSSpencerAbson int OverloadType) { 5171f70fcefSSpencerAbson bool HasError = false; 5181f70fcefSSpencerAbson 5191f70fcefSSpencerAbson for (const auto &I : ImmChecks) { 520a3744f06SSpencer Abson auto [ArgIdx, CheckTy, ElementBitWidth, VecBitWidth] = I; 5211f70fcefSSpencerAbson 5221f70fcefSSpencerAbson if (OverloadType >= 0) 523a3744f06SSpencer Abson ElementBitWidth = NeonTypeFlags(OverloadType).getEltSizeInBits(); 5241f70fcefSSpencerAbson 525a3744f06SSpencer Abson HasError |= CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 526a3744f06SSpencer Abson VecBitWidth); 5271f70fcefSSpencerAbson } 5281f70fcefSSpencerAbson 5291f70fcefSSpencerAbson return HasError; 5301f70fcefSSpencerAbson } 5311f70fcefSSpencerAbson 5321f70fcefSSpencerAbson bool SemaARM::PerformSVEImmChecks( 5331f70fcefSSpencerAbson CallExpr *TheCall, SmallVectorImpl<std::tuple<int, int, int>> &ImmChecks) { 5341f70fcefSSpencerAbson bool HasError = false; 5351f70fcefSSpencerAbson 5361f70fcefSSpencerAbson for (const auto &I : ImmChecks) { 537a3744f06SSpencer Abson auto [ArgIdx, CheckTy, ElementBitWidth] = I; 5381f70fcefSSpencerAbson HasError |= 539a3744f06SSpencer Abson CheckImmediateArg(TheCall, CheckTy, ArgIdx, ElementBitWidth, 128); 540ed35a92cSVlad Serebrennikov } 541ed35a92cSVlad Serebrennikov 542ed35a92cSVlad Serebrennikov return HasError; 543ed35a92cSVlad Serebrennikov } 544ed35a92cSVlad Serebrennikov 545ed35a92cSVlad Serebrennikov SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD) { 546ed35a92cSVlad Serebrennikov if (FD->hasAttr<ArmLocallyStreamingAttr>()) 547ed35a92cSVlad Serebrennikov return SemaARM::ArmStreaming; 548ed35a92cSVlad Serebrennikov if (const Type *Ty = FD->getType().getTypePtrOrNull()) { 549ed35a92cSVlad Serebrennikov if (const auto *FPT = Ty->getAs<FunctionProtoType>()) { 550ed35a92cSVlad Serebrennikov if (FPT->getAArch64SMEAttributes() & 551ed35a92cSVlad Serebrennikov FunctionType::SME_PStateSMEnabledMask) 552ed35a92cSVlad Serebrennikov return SemaARM::ArmStreaming; 553ed35a92cSVlad Serebrennikov if (FPT->getAArch64SMEAttributes() & 554ed35a92cSVlad Serebrennikov FunctionType::SME_PStateSMCompatibleMask) 555ed35a92cSVlad Serebrennikov return SemaARM::ArmStreamingCompatible; 556ed35a92cSVlad Serebrennikov } 557ed35a92cSVlad Serebrennikov } 558ed35a92cSVlad Serebrennikov return SemaARM::ArmNonStreaming; 559ed35a92cSVlad Serebrennikov } 560ed35a92cSVlad Serebrennikov 5611644a31aSSander de Smalen static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall, 562ed35a92cSVlad Serebrennikov const FunctionDecl *FD, 5631644a31aSSander de Smalen SemaARM::ArmStreamingType BuiltinType, 5641644a31aSSander de Smalen unsigned BuiltinID) { 565ed35a92cSVlad Serebrennikov SemaARM::ArmStreamingType FnType = getArmStreamingFnType(FD); 5661644a31aSSander de Smalen 5671644a31aSSander de Smalen // Check if the intrinsic is available in the right mode, i.e. 5681644a31aSSander de Smalen // * When compiling for SME only, the caller must be in streaming mode. 5691644a31aSSander de Smalen // * When compiling for SVE only, the caller must be in non-streaming mode. 5701644a31aSSander de Smalen // * When compiling for both SVE and SME, the caller can be in either mode. 5711644a31aSSander de Smalen if (BuiltinType == SemaARM::VerifyRuntimeMode) { 5721644a31aSSander de Smalen llvm::StringMap<bool> CallerFeatureMapWithoutSVE; 5731644a31aSSander de Smalen S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSVE, FD); 574f22e6d59SSander de Smalen CallerFeatureMapWithoutSVE["sve"] = false; 5751644a31aSSander de Smalen 5761644a31aSSander de Smalen // Avoid emitting diagnostics for a function that can never compile. 5771644a31aSSander de Smalen if (FnType == SemaARM::ArmStreaming && !CallerFeatureMapWithoutSVE["sme"]) 5781644a31aSSander de Smalen return false; 5791644a31aSSander de Smalen 5801644a31aSSander de Smalen llvm::StringMap<bool> CallerFeatureMapWithoutSME; 5811644a31aSSander de Smalen S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSME, FD); 582f22e6d59SSander de Smalen CallerFeatureMapWithoutSME["sme"] = false; 5831644a31aSSander de Smalen 5841644a31aSSander de Smalen // We know the builtin requires either some combination of SVE flags, or 5851644a31aSSander de Smalen // some combination of SME flags, but we need to figure out which part 5861644a31aSSander de Smalen // of the required features is satisfied by the target features. 5871644a31aSSander de Smalen // 5881644a31aSSander de Smalen // For a builtin with target guard 'sve2p1|sme2', if we compile with 5891644a31aSSander de Smalen // '+sve2p1,+sme', then we know that it satisfies the 'sve2p1' part if we 5901644a31aSSander de Smalen // evaluate the features for '+sve2p1,+sme,+nosme'. 5911644a31aSSander de Smalen // 5921644a31aSSander de Smalen // Similarly, if we compile with '+sve2,+sme2', then we know it satisfies 5931644a31aSSander de Smalen // the 'sme2' part if we evaluate the features for '+sve2,+sme2,+nosve'. 5941644a31aSSander de Smalen StringRef BuiltinTargetGuards( 5951644a31aSSander de Smalen S.Context.BuiltinInfo.getRequiredFeatures(BuiltinID)); 5961644a31aSSander de Smalen bool SatisfiesSVE = Builtin::evaluateRequiredTargetFeatures( 5971644a31aSSander de Smalen BuiltinTargetGuards, CallerFeatureMapWithoutSME); 5981644a31aSSander de Smalen bool SatisfiesSME = Builtin::evaluateRequiredTargetFeatures( 5991644a31aSSander de Smalen BuiltinTargetGuards, CallerFeatureMapWithoutSVE); 6001644a31aSSander de Smalen 6011644a31aSSander de Smalen if ((SatisfiesSVE && SatisfiesSME) || 6021644a31aSSander de Smalen (SatisfiesSVE && FnType == SemaARM::ArmStreamingCompatible)) 6031644a31aSSander de Smalen return false; 6041644a31aSSander de Smalen else if (SatisfiesSVE) 6051644a31aSSander de Smalen BuiltinType = SemaARM::ArmNonStreaming; 6061644a31aSSander de Smalen else if (SatisfiesSME) 607ed35a92cSVlad Serebrennikov BuiltinType = SemaARM::ArmStreaming; 6081644a31aSSander de Smalen else 6091644a31aSSander de Smalen // This should be diagnosed by CodeGen 6101644a31aSSander de Smalen return false; 611ed35a92cSVlad Serebrennikov } 612ed35a92cSVlad Serebrennikov 6131644a31aSSander de Smalen if (FnType != SemaARM::ArmNonStreaming && 614ed35a92cSVlad Serebrennikov BuiltinType == SemaARM::ArmNonStreaming) 6151644a31aSSander de Smalen S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin) 616ed35a92cSVlad Serebrennikov << TheCall->getSourceRange() << "non-streaming"; 6171644a31aSSander de Smalen else if (FnType != SemaARM::ArmStreaming && 6181644a31aSSander de Smalen BuiltinType == SemaARM::ArmStreaming) 6191644a31aSSander de Smalen S.Diag(TheCall->getBeginLoc(), diag::err_attribute_arm_sm_incompat_builtin) 6201644a31aSSander de Smalen << TheCall->getSourceRange() << "streaming"; 6211644a31aSSander de Smalen else 6221644a31aSSander de Smalen return false; 6231644a31aSSander de Smalen 6241644a31aSSander de Smalen return true; 625ed35a92cSVlad Serebrennikov } 626ed35a92cSVlad Serebrennikov 627ed35a92cSVlad Serebrennikov static ArmSMEState getSMEState(unsigned BuiltinID) { 628ed35a92cSVlad Serebrennikov switch (BuiltinID) { 629ed35a92cSVlad Serebrennikov default: 630ed35a92cSVlad Serebrennikov return ArmNoState; 631ed35a92cSVlad Serebrennikov #define GET_SME_BUILTIN_GET_STATE 632ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_sme_builtins_za_state.inc" 633ed35a92cSVlad Serebrennikov #undef GET_SME_BUILTIN_GET_STATE 634ed35a92cSVlad Serebrennikov } 635ed35a92cSVlad Serebrennikov } 636ed35a92cSVlad Serebrennikov 637ed35a92cSVlad Serebrennikov bool SemaARM::CheckSMEBuiltinFunctionCall(unsigned BuiltinID, 638ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 639ed35a92cSVlad Serebrennikov if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) { 640ed35a92cSVlad Serebrennikov std::optional<ArmStreamingType> BuiltinType; 641ed35a92cSVlad Serebrennikov 642ed35a92cSVlad Serebrennikov switch (BuiltinID) { 643ed35a92cSVlad Serebrennikov #define GET_SME_STREAMING_ATTRS 644ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_sme_streaming_attrs.inc" 645ed35a92cSVlad Serebrennikov #undef GET_SME_STREAMING_ATTRS 646ed35a92cSVlad Serebrennikov } 647ed35a92cSVlad Serebrennikov 6481644a31aSSander de Smalen if (BuiltinType && 6491644a31aSSander de Smalen checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID)) 6501644a31aSSander de Smalen return true; 651ed35a92cSVlad Serebrennikov 652ed35a92cSVlad Serebrennikov if ((getSMEState(BuiltinID) & ArmZAMask) && !hasArmZAState(FD)) 653ed35a92cSVlad Serebrennikov Diag(TheCall->getBeginLoc(), 654ed35a92cSVlad Serebrennikov diag::warn_attribute_arm_za_builtin_no_za_state) 655ed35a92cSVlad Serebrennikov << TheCall->getSourceRange(); 656ed35a92cSVlad Serebrennikov 657ed35a92cSVlad Serebrennikov if ((getSMEState(BuiltinID) & ArmZT0Mask) && !hasArmZT0State(FD)) 658ed35a92cSVlad Serebrennikov Diag(TheCall->getBeginLoc(), 659ed35a92cSVlad Serebrennikov diag::warn_attribute_arm_zt0_builtin_no_zt0_state) 660ed35a92cSVlad Serebrennikov << TheCall->getSourceRange(); 661ed35a92cSVlad Serebrennikov } 662ed35a92cSVlad Serebrennikov 663ed35a92cSVlad Serebrennikov // Range check SME intrinsics that take immediate values. 664ed35a92cSVlad Serebrennikov SmallVector<std::tuple<int, int, int>, 3> ImmChecks; 665ed35a92cSVlad Serebrennikov 666ed35a92cSVlad Serebrennikov switch (BuiltinID) { 667ed35a92cSVlad Serebrennikov default: 668ed35a92cSVlad Serebrennikov return false; 669ed35a92cSVlad Serebrennikov #define GET_SME_IMMEDIATE_CHECK 670ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_sme_sema_rangechecks.inc" 671ed35a92cSVlad Serebrennikov #undef GET_SME_IMMEDIATE_CHECK 672ed35a92cSVlad Serebrennikov } 673ed35a92cSVlad Serebrennikov 6741f70fcefSSpencerAbson return PerformSVEImmChecks(TheCall, ImmChecks); 675ed35a92cSVlad Serebrennikov } 676ed35a92cSVlad Serebrennikov 677ed35a92cSVlad Serebrennikov bool SemaARM::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, 678ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 679ed35a92cSVlad Serebrennikov if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) { 680ed35a92cSVlad Serebrennikov std::optional<ArmStreamingType> BuiltinType; 681ed35a92cSVlad Serebrennikov 682ed35a92cSVlad Serebrennikov switch (BuiltinID) { 683ed35a92cSVlad Serebrennikov #define GET_SVE_STREAMING_ATTRS 684ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_sve_streaming_attrs.inc" 685ed35a92cSVlad Serebrennikov #undef GET_SVE_STREAMING_ATTRS 686ed35a92cSVlad Serebrennikov } 6871644a31aSSander de Smalen if (BuiltinType && 6881644a31aSSander de Smalen checkArmStreamingBuiltin(SemaRef, TheCall, FD, *BuiltinType, BuiltinID)) 6891644a31aSSander de Smalen return true; 690ed35a92cSVlad Serebrennikov } 691ed35a92cSVlad Serebrennikov // Range check SVE intrinsics that take immediate values. 692ed35a92cSVlad Serebrennikov SmallVector<std::tuple<int, int, int>, 3> ImmChecks; 693ed35a92cSVlad Serebrennikov 694ed35a92cSVlad Serebrennikov switch (BuiltinID) { 695ed35a92cSVlad Serebrennikov default: 696ed35a92cSVlad Serebrennikov return false; 697ed35a92cSVlad Serebrennikov #define GET_SVE_IMMEDIATE_CHECK 698ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_sve_sema_rangechecks.inc" 699ed35a92cSVlad Serebrennikov #undef GET_SVE_IMMEDIATE_CHECK 700ed35a92cSVlad Serebrennikov } 701ed35a92cSVlad Serebrennikov 7021f70fcefSSpencerAbson return PerformSVEImmChecks(TheCall, ImmChecks); 703ed35a92cSVlad Serebrennikov } 704ed35a92cSVlad Serebrennikov 705ed35a92cSVlad Serebrennikov bool SemaARM::CheckNeonBuiltinFunctionCall(const TargetInfo &TI, 706ed35a92cSVlad Serebrennikov unsigned BuiltinID, 707ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 708ed35a92cSVlad Serebrennikov if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) { 709ed35a92cSVlad Serebrennikov 710ed35a92cSVlad Serebrennikov switch (BuiltinID) { 711ed35a92cSVlad Serebrennikov default: 712ed35a92cSVlad Serebrennikov break; 713ed35a92cSVlad Serebrennikov #define GET_NEON_BUILTINS 714ed35a92cSVlad Serebrennikov #define TARGET_BUILTIN(id, ...) case NEON::BI##id: 715ed35a92cSVlad Serebrennikov #define BUILTIN(id, ...) case NEON::BI##id: 716ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_neon.inc" 7171644a31aSSander de Smalen if (checkArmStreamingBuiltin(SemaRef, TheCall, FD, ArmNonStreaming, 7181644a31aSSander de Smalen BuiltinID)) 7191644a31aSSander de Smalen return true; 720ed35a92cSVlad Serebrennikov break; 721ed35a92cSVlad Serebrennikov #undef TARGET_BUILTIN 722ed35a92cSVlad Serebrennikov #undef BUILTIN 723ed35a92cSVlad Serebrennikov #undef GET_NEON_BUILTINS 724ed35a92cSVlad Serebrennikov } 725ed35a92cSVlad Serebrennikov } 726ed35a92cSVlad Serebrennikov 727ed35a92cSVlad Serebrennikov llvm::APSInt Result; 728ed35a92cSVlad Serebrennikov uint64_t mask = 0; 7291f70fcefSSpencerAbson int TV = -1; 730ed35a92cSVlad Serebrennikov int PtrArgNum = -1; 731ed35a92cSVlad Serebrennikov bool HasConstPtr = false; 732ed35a92cSVlad Serebrennikov switch (BuiltinID) { 733ed35a92cSVlad Serebrennikov #define GET_NEON_OVERLOAD_CHECK 734ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_fp16.inc" 735ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_neon.inc" 736ed35a92cSVlad Serebrennikov #undef GET_NEON_OVERLOAD_CHECK 737ed35a92cSVlad Serebrennikov } 738ed35a92cSVlad Serebrennikov 739ed35a92cSVlad Serebrennikov // For NEON intrinsics which are overloaded on vector element type, validate 740ed35a92cSVlad Serebrennikov // the immediate which specifies which variant to emit. 741ed35a92cSVlad Serebrennikov unsigned ImmArg = TheCall->getNumArgs() - 1; 742ed35a92cSVlad Serebrennikov if (mask) { 743ed35a92cSVlad Serebrennikov if (SemaRef.BuiltinConstantArg(TheCall, ImmArg, Result)) 744ed35a92cSVlad Serebrennikov return true; 745ed35a92cSVlad Serebrennikov 746ed35a92cSVlad Serebrennikov TV = Result.getLimitedValue(64); 747ed35a92cSVlad Serebrennikov if ((TV > 63) || (mask & (1ULL << TV)) == 0) 748ed35a92cSVlad Serebrennikov return Diag(TheCall->getBeginLoc(), diag::err_invalid_neon_type_code) 749ed35a92cSVlad Serebrennikov << TheCall->getArg(ImmArg)->getSourceRange(); 750ed35a92cSVlad Serebrennikov } 751ed35a92cSVlad Serebrennikov 752ed35a92cSVlad Serebrennikov if (PtrArgNum >= 0) { 753ed35a92cSVlad Serebrennikov // Check that pointer arguments have the specified type. 754ed35a92cSVlad Serebrennikov Expr *Arg = TheCall->getArg(PtrArgNum); 755ed35a92cSVlad Serebrennikov if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) 756ed35a92cSVlad Serebrennikov Arg = ICE->getSubExpr(); 757ed35a92cSVlad Serebrennikov ExprResult RHS = SemaRef.DefaultFunctionArrayLvalueConversion(Arg); 758ed35a92cSVlad Serebrennikov QualType RHSTy = RHS.get()->getType(); 759ed35a92cSVlad Serebrennikov 760ed35a92cSVlad Serebrennikov llvm::Triple::ArchType Arch = TI.getTriple().getArch(); 761ed35a92cSVlad Serebrennikov bool IsPolyUnsigned = Arch == llvm::Triple::aarch64 || 762ed35a92cSVlad Serebrennikov Arch == llvm::Triple::aarch64_32 || 763ed35a92cSVlad Serebrennikov Arch == llvm::Triple::aarch64_be; 764ed35a92cSVlad Serebrennikov bool IsInt64Long = TI.getInt64Type() == TargetInfo::SignedLong; 765ed35a92cSVlad Serebrennikov QualType EltTy = getNeonEltType(NeonTypeFlags(TV), getASTContext(), 766ed35a92cSVlad Serebrennikov IsPolyUnsigned, IsInt64Long); 767ed35a92cSVlad Serebrennikov if (HasConstPtr) 768ed35a92cSVlad Serebrennikov EltTy = EltTy.withConst(); 769ed35a92cSVlad Serebrennikov QualType LHSTy = getASTContext().getPointerType(EltTy); 770ed35a92cSVlad Serebrennikov Sema::AssignConvertType ConvTy; 771ed35a92cSVlad Serebrennikov ConvTy = SemaRef.CheckSingleAssignmentConstraints(LHSTy, RHS); 772ed35a92cSVlad Serebrennikov if (RHS.isInvalid()) 773ed35a92cSVlad Serebrennikov return true; 774ed35a92cSVlad Serebrennikov if (SemaRef.DiagnoseAssignmentResult(ConvTy, Arg->getBeginLoc(), LHSTy, 775ff04c5b2SDan Liew RHSTy, RHS.get(), 776ff04c5b2SDan Liew AssignmentAction::Assigning)) 777ed35a92cSVlad Serebrennikov return true; 778ed35a92cSVlad Serebrennikov } 779ed35a92cSVlad Serebrennikov 780ed35a92cSVlad Serebrennikov // For NEON intrinsics which take an immediate value as part of the 781ed35a92cSVlad Serebrennikov // instruction, range check them here. 7821f70fcefSSpencerAbson SmallVector<std::tuple<int, int, int, int>, 2> ImmChecks; 783ed35a92cSVlad Serebrennikov switch (BuiltinID) { 784ed35a92cSVlad Serebrennikov default: 785ed35a92cSVlad Serebrennikov return false; 786ed35a92cSVlad Serebrennikov #define GET_NEON_IMMEDIATE_CHECK 787ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_fp16.inc" 788ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_neon.inc" 789ed35a92cSVlad Serebrennikov #undef GET_NEON_IMMEDIATE_CHECK 790ed35a92cSVlad Serebrennikov } 791ed35a92cSVlad Serebrennikov 7921f70fcefSSpencerAbson return PerformNeonImmChecks(TheCall, ImmChecks, TV); 793ed35a92cSVlad Serebrennikov } 794ed35a92cSVlad Serebrennikov 795ed35a92cSVlad Serebrennikov bool SemaARM::CheckMVEBuiltinFunctionCall(unsigned BuiltinID, 796ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 797ed35a92cSVlad Serebrennikov switch (BuiltinID) { 798ed35a92cSVlad Serebrennikov default: 799ed35a92cSVlad Serebrennikov return false; 800ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_mve_builtin_sema.inc" 801ed35a92cSVlad Serebrennikov } 802ed35a92cSVlad Serebrennikov } 803ed35a92cSVlad Serebrennikov 804ed35a92cSVlad Serebrennikov bool SemaARM::CheckCDEBuiltinFunctionCall(const TargetInfo &TI, 805ed35a92cSVlad Serebrennikov unsigned BuiltinID, 806ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 807ed35a92cSVlad Serebrennikov bool Err = false; 808ed35a92cSVlad Serebrennikov switch (BuiltinID) { 809ed35a92cSVlad Serebrennikov default: 810ed35a92cSVlad Serebrennikov return false; 811ed35a92cSVlad Serebrennikov #include "clang/Basic/arm_cde_builtin_sema.inc" 812ed35a92cSVlad Serebrennikov } 813ed35a92cSVlad Serebrennikov 814ed35a92cSVlad Serebrennikov if (Err) 815ed35a92cSVlad Serebrennikov return true; 816ed35a92cSVlad Serebrennikov 817ed35a92cSVlad Serebrennikov return CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), /*WantCDE*/ true); 818ed35a92cSVlad Serebrennikov } 819ed35a92cSVlad Serebrennikov 820ed35a92cSVlad Serebrennikov bool SemaARM::CheckARMCoprocessorImmediate(const TargetInfo &TI, 821ed35a92cSVlad Serebrennikov const Expr *CoprocArg, 822ed35a92cSVlad Serebrennikov bool WantCDE) { 823ed35a92cSVlad Serebrennikov ASTContext &Context = getASTContext(); 824ed35a92cSVlad Serebrennikov if (SemaRef.isConstantEvaluatedContext()) 825ed35a92cSVlad Serebrennikov return false; 826ed35a92cSVlad Serebrennikov 827ed35a92cSVlad Serebrennikov // We can't check the value of a dependent argument. 828ed35a92cSVlad Serebrennikov if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent()) 829ed35a92cSVlad Serebrennikov return false; 830ed35a92cSVlad Serebrennikov 831ed35a92cSVlad Serebrennikov llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context); 832ed35a92cSVlad Serebrennikov int64_t CoprocNo = CoprocNoAP.getExtValue(); 833ed35a92cSVlad Serebrennikov assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative"); 834ed35a92cSVlad Serebrennikov 835ed35a92cSVlad Serebrennikov uint32_t CDECoprocMask = TI.getARMCDECoprocMask(); 836ed35a92cSVlad Serebrennikov bool IsCDECoproc = CoprocNo <= 7 && (CDECoprocMask & (1 << CoprocNo)); 837ed35a92cSVlad Serebrennikov 838ed35a92cSVlad Serebrennikov if (IsCDECoproc != WantCDE) 839ed35a92cSVlad Serebrennikov return Diag(CoprocArg->getBeginLoc(), diag::err_arm_invalid_coproc) 840ed35a92cSVlad Serebrennikov << (int)CoprocNo << (int)WantCDE << CoprocArg->getSourceRange(); 841ed35a92cSVlad Serebrennikov 842ed35a92cSVlad Serebrennikov return false; 843ed35a92cSVlad Serebrennikov } 844ed35a92cSVlad Serebrennikov 845ed35a92cSVlad Serebrennikov bool SemaARM::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, 846ed35a92cSVlad Serebrennikov CallExpr *TheCall, 847ed35a92cSVlad Serebrennikov unsigned MaxWidth) { 848ed35a92cSVlad Serebrennikov assert((BuiltinID == ARM::BI__builtin_arm_ldrex || 849ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_ldaex || 850ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_strex || 851ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_stlex || 852ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_ldrex || 853ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_ldaex || 854ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_strex || 855ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_stlex) && 856ed35a92cSVlad Serebrennikov "unexpected ARM builtin"); 857ed35a92cSVlad Serebrennikov bool IsLdrex = BuiltinID == ARM::BI__builtin_arm_ldrex || 858ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_ldaex || 859ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_ldrex || 860ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_ldaex; 861ed35a92cSVlad Serebrennikov 862ed35a92cSVlad Serebrennikov ASTContext &Context = getASTContext(); 863ed35a92cSVlad Serebrennikov DeclRefExpr *DRE = 864ed35a92cSVlad Serebrennikov cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); 865ed35a92cSVlad Serebrennikov 866ed35a92cSVlad Serebrennikov // Ensure that we have the proper number of arguments. 867ed35a92cSVlad Serebrennikov if (SemaRef.checkArgCount(TheCall, IsLdrex ? 1 : 2)) 868ed35a92cSVlad Serebrennikov return true; 869ed35a92cSVlad Serebrennikov 870ed35a92cSVlad Serebrennikov // Inspect the pointer argument of the atomic builtin. This should always be 871ed35a92cSVlad Serebrennikov // a pointer type, whose element is an integral scalar or pointer type. 872ed35a92cSVlad Serebrennikov // Because it is a pointer type, we don't have to worry about any implicit 873ed35a92cSVlad Serebrennikov // casts here. 874ed35a92cSVlad Serebrennikov Expr *PointerArg = TheCall->getArg(IsLdrex ? 0 : 1); 875ed35a92cSVlad Serebrennikov ExprResult PointerArgRes = 876ed35a92cSVlad Serebrennikov SemaRef.DefaultFunctionArrayLvalueConversion(PointerArg); 877ed35a92cSVlad Serebrennikov if (PointerArgRes.isInvalid()) 878ed35a92cSVlad Serebrennikov return true; 879ed35a92cSVlad Serebrennikov PointerArg = PointerArgRes.get(); 880ed35a92cSVlad Serebrennikov 881ed35a92cSVlad Serebrennikov const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>(); 882ed35a92cSVlad Serebrennikov if (!pointerType) { 883ed35a92cSVlad Serebrennikov Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer) 884ed35a92cSVlad Serebrennikov << PointerArg->getType() << 0 << PointerArg->getSourceRange(); 885ed35a92cSVlad Serebrennikov return true; 886ed35a92cSVlad Serebrennikov } 887ed35a92cSVlad Serebrennikov 888ed35a92cSVlad Serebrennikov // ldrex takes a "const volatile T*" and strex takes a "volatile T*". Our next 889ed35a92cSVlad Serebrennikov // task is to insert the appropriate casts into the AST. First work out just 890ed35a92cSVlad Serebrennikov // what the appropriate type is. 891ed35a92cSVlad Serebrennikov QualType ValType = pointerType->getPointeeType(); 892ed35a92cSVlad Serebrennikov QualType AddrType = ValType.getUnqualifiedType().withVolatile(); 893ed35a92cSVlad Serebrennikov if (IsLdrex) 894ed35a92cSVlad Serebrennikov AddrType.addConst(); 895ed35a92cSVlad Serebrennikov 896ed35a92cSVlad Serebrennikov // Issue a warning if the cast is dodgy. 897ed35a92cSVlad Serebrennikov CastKind CastNeeded = CK_NoOp; 898b9d678d2SJoseph Huber if (!AddrType.isAtLeastAsQualifiedAs(ValType, getASTContext())) { 899ed35a92cSVlad Serebrennikov CastNeeded = CK_BitCast; 900ed35a92cSVlad Serebrennikov Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers) 901ed35a92cSVlad Serebrennikov << PointerArg->getType() << Context.getPointerType(AddrType) 902ff04c5b2SDan Liew << AssignmentAction::Passing << PointerArg->getSourceRange(); 903ed35a92cSVlad Serebrennikov } 904ed35a92cSVlad Serebrennikov 905ed35a92cSVlad Serebrennikov // Finally, do the cast and replace the argument with the corrected version. 906ed35a92cSVlad Serebrennikov AddrType = Context.getPointerType(AddrType); 907ed35a92cSVlad Serebrennikov PointerArgRes = SemaRef.ImpCastExprToType(PointerArg, AddrType, CastNeeded); 908ed35a92cSVlad Serebrennikov if (PointerArgRes.isInvalid()) 909ed35a92cSVlad Serebrennikov return true; 910ed35a92cSVlad Serebrennikov PointerArg = PointerArgRes.get(); 911ed35a92cSVlad Serebrennikov 912ed35a92cSVlad Serebrennikov TheCall->setArg(IsLdrex ? 0 : 1, PointerArg); 913ed35a92cSVlad Serebrennikov 914ed35a92cSVlad Serebrennikov // In general, we allow ints, floats and pointers to be loaded and stored. 915ed35a92cSVlad Serebrennikov if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && 916ed35a92cSVlad Serebrennikov !ValType->isBlockPointerType() && !ValType->isFloatingType()) { 917ed35a92cSVlad Serebrennikov Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr) 918ed35a92cSVlad Serebrennikov << PointerArg->getType() << 0 << PointerArg->getSourceRange(); 919ed35a92cSVlad Serebrennikov return true; 920ed35a92cSVlad Serebrennikov } 921ed35a92cSVlad Serebrennikov 922ed35a92cSVlad Serebrennikov // But ARM doesn't have instructions to deal with 128-bit versions. 923ed35a92cSVlad Serebrennikov if (Context.getTypeSize(ValType) > MaxWidth) { 924ed35a92cSVlad Serebrennikov assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate"); 925ed35a92cSVlad Serebrennikov Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size) 926ed35a92cSVlad Serebrennikov << PointerArg->getType() << PointerArg->getSourceRange(); 927ed35a92cSVlad Serebrennikov return true; 928ed35a92cSVlad Serebrennikov } 929ed35a92cSVlad Serebrennikov 930ed35a92cSVlad Serebrennikov switch (ValType.getObjCLifetime()) { 931ed35a92cSVlad Serebrennikov case Qualifiers::OCL_None: 932ed35a92cSVlad Serebrennikov case Qualifiers::OCL_ExplicitNone: 933ed35a92cSVlad Serebrennikov // okay 934ed35a92cSVlad Serebrennikov break; 935ed35a92cSVlad Serebrennikov 936ed35a92cSVlad Serebrennikov case Qualifiers::OCL_Weak: 937ed35a92cSVlad Serebrennikov case Qualifiers::OCL_Strong: 938ed35a92cSVlad Serebrennikov case Qualifiers::OCL_Autoreleasing: 939ed35a92cSVlad Serebrennikov Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership) 940ed35a92cSVlad Serebrennikov << ValType << PointerArg->getSourceRange(); 941ed35a92cSVlad Serebrennikov return true; 942ed35a92cSVlad Serebrennikov } 943ed35a92cSVlad Serebrennikov 944ed35a92cSVlad Serebrennikov if (IsLdrex) { 945ed35a92cSVlad Serebrennikov TheCall->setType(ValType); 946ed35a92cSVlad Serebrennikov return false; 947ed35a92cSVlad Serebrennikov } 948ed35a92cSVlad Serebrennikov 949ed35a92cSVlad Serebrennikov // Initialize the argument to be stored. 950ed35a92cSVlad Serebrennikov ExprResult ValArg = TheCall->getArg(0); 951ed35a92cSVlad Serebrennikov InitializedEntity Entity = InitializedEntity::InitializeParameter( 952ed35a92cSVlad Serebrennikov Context, ValType, /*consume*/ false); 953ed35a92cSVlad Serebrennikov ValArg = SemaRef.PerformCopyInitialization(Entity, SourceLocation(), ValArg); 954ed35a92cSVlad Serebrennikov if (ValArg.isInvalid()) 955ed35a92cSVlad Serebrennikov return true; 956ed35a92cSVlad Serebrennikov TheCall->setArg(0, ValArg.get()); 957ed35a92cSVlad Serebrennikov 958ed35a92cSVlad Serebrennikov // __builtin_arm_strex always returns an int. It's marked as such in the .def, 959ed35a92cSVlad Serebrennikov // but the custom checker bypasses all default analysis. 960ed35a92cSVlad Serebrennikov TheCall->setType(Context.IntTy); 961ed35a92cSVlad Serebrennikov return false; 962ed35a92cSVlad Serebrennikov } 963ed35a92cSVlad Serebrennikov 964ed35a92cSVlad Serebrennikov bool SemaARM::CheckARMBuiltinFunctionCall(const TargetInfo &TI, 965ed35a92cSVlad Serebrennikov unsigned BuiltinID, 966ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 967ed35a92cSVlad Serebrennikov if (BuiltinID == ARM::BI__builtin_arm_ldrex || 968ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_ldaex || 969ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_strex || 970ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_stlex) { 971ed35a92cSVlad Serebrennikov return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64); 972ed35a92cSVlad Serebrennikov } 973ed35a92cSVlad Serebrennikov 974ed35a92cSVlad Serebrennikov if (BuiltinID == ARM::BI__builtin_arm_prefetch) { 975ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) || 976ed35a92cSVlad Serebrennikov SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 1); 977ed35a92cSVlad Serebrennikov } 978ed35a92cSVlad Serebrennikov 979ed35a92cSVlad Serebrennikov if (BuiltinID == ARM::BI__builtin_arm_rsr64 || 980ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_wsr64) 981ed35a92cSVlad Serebrennikov return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 3, false); 982ed35a92cSVlad Serebrennikov 983ed35a92cSVlad Serebrennikov if (BuiltinID == ARM::BI__builtin_arm_rsr || 984ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_rsrp || 985ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_wsr || 986ed35a92cSVlad Serebrennikov BuiltinID == ARM::BI__builtin_arm_wsrp) 987ed35a92cSVlad Serebrennikov return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true); 988ed35a92cSVlad Serebrennikov 989ed35a92cSVlad Serebrennikov if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall)) 990ed35a92cSVlad Serebrennikov return true; 991ed35a92cSVlad Serebrennikov if (CheckMVEBuiltinFunctionCall(BuiltinID, TheCall)) 992ed35a92cSVlad Serebrennikov return true; 993ed35a92cSVlad Serebrennikov if (CheckCDEBuiltinFunctionCall(TI, BuiltinID, TheCall)) 994ed35a92cSVlad Serebrennikov return true; 995ed35a92cSVlad Serebrennikov 996ed35a92cSVlad Serebrennikov // For intrinsics which take an immediate value as part of the instruction, 997ed35a92cSVlad Serebrennikov // range check them here. 998ed35a92cSVlad Serebrennikov // FIXME: VFP Intrinsics should error if VFP not present. 999ed35a92cSVlad Serebrennikov switch (BuiltinID) { 1000ed35a92cSVlad Serebrennikov default: 1001ed35a92cSVlad Serebrennikov return false; 1002ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_ssat: 1003ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 32); 1004ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_usat: 1005ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31); 1006ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_ssat16: 1007ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 1, 16); 1008ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_usat16: 1009ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 15); 1010ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_vcvtr_f: 1011ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_vcvtr_d: 1012ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1); 1013ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_dmb: 1014ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_dsb: 1015ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_isb: 1016ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_dbg: 1017ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15); 1018ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_cdp: 1019ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_cdp2: 1020ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_mcr: 1021ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_mcr2: 1022ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_mrc: 1023ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_mrc2: 1024ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_mcrr: 1025ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_mcrr2: 1026ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_mrrc: 1027ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_mrrc2: 1028ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_ldc: 1029ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_ldcl: 1030ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_ldc2: 1031ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_ldc2l: 1032ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_stc: 1033ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_stcl: 1034ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_stc2: 1035ed35a92cSVlad Serebrennikov case ARM::BI__builtin_arm_stc2l: 1036ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 15) || 1037ed35a92cSVlad Serebrennikov CheckARMCoprocessorImmediate(TI, TheCall->getArg(0), 1038ed35a92cSVlad Serebrennikov /*WantCDE*/ false); 1039ed35a92cSVlad Serebrennikov } 1040ed35a92cSVlad Serebrennikov } 1041ed35a92cSVlad Serebrennikov 1042ed35a92cSVlad Serebrennikov bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, 1043ed35a92cSVlad Serebrennikov unsigned BuiltinID, 1044ed35a92cSVlad Serebrennikov CallExpr *TheCall) { 1045ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_ldrex || 1046ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_ldaex || 1047ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_strex || 1048ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_stlex) { 1049ed35a92cSVlad Serebrennikov return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128); 1050ed35a92cSVlad Serebrennikov } 1051ed35a92cSVlad Serebrennikov 1052ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_prefetch) { 1053ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 1) || 1054ed35a92cSVlad Serebrennikov SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3) || 1055ed35a92cSVlad Serebrennikov SemaRef.BuiltinConstantArgRange(TheCall, 3, 0, 1) || 1056ed35a92cSVlad Serebrennikov SemaRef.BuiltinConstantArgRange(TheCall, 4, 0, 1); 1057ed35a92cSVlad Serebrennikov } 1058ed35a92cSVlad Serebrennikov 1059ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_rsr64 || 1060ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsr64 || 1061ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_rsr128 || 1062ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsr128) 1063ed35a92cSVlad Serebrennikov return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true); 1064ed35a92cSVlad Serebrennikov 1065ed35a92cSVlad Serebrennikov // Memory Tagging Extensions (MTE) Intrinsics 1066ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_irg || 1067ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_addg || 1068ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_gmi || 1069ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_ldg || 1070ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_stg || 1071ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_subp) { 1072ed35a92cSVlad Serebrennikov return BuiltinARMMemoryTaggingCall(BuiltinID, TheCall); 1073ed35a92cSVlad Serebrennikov } 1074ed35a92cSVlad Serebrennikov 1075ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__builtin_arm_rsr || 1076ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_rsrp || 1077ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsr || 1078ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI__builtin_arm_wsrp) 1079ed35a92cSVlad Serebrennikov return BuiltinARMSpecialReg(BuiltinID, TheCall, 0, 5, true); 1080ed35a92cSVlad Serebrennikov 1081ed35a92cSVlad Serebrennikov // Only check the valid encoding range. Any constant in this range would be 1082ed35a92cSVlad Serebrennikov // converted to a register of the form S1_2_C3_C4_5. Let the hardware throw 1083ed35a92cSVlad Serebrennikov // an exception for incorrect registers. This matches MSVC behavior. 1084ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI_ReadStatusReg || 1085ed35a92cSVlad Serebrennikov BuiltinID == AArch64::BI_WriteStatusReg) 1086ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0x7fff); 1087ed35a92cSVlad Serebrennikov 1088ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__getReg) 1089ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 31); 1090ed35a92cSVlad Serebrennikov 1091ed35a92cSVlad Serebrennikov if (BuiltinID == AArch64::BI__break) 1092ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff); 1093ed35a92cSVlad Serebrennikov 1094ae7ab043SAmy Huang if (BuiltinID == AArch64::BI__hlt) 1095ae7ab043SAmy Huang return SemaRef.BuiltinConstantArgRange(TheCall, 0, 0, 0xffff); 1096ae7ab043SAmy Huang 1097ed35a92cSVlad Serebrennikov if (CheckNeonBuiltinFunctionCall(TI, BuiltinID, TheCall)) 1098ed35a92cSVlad Serebrennikov return true; 1099ed35a92cSVlad Serebrennikov 1100ed35a92cSVlad Serebrennikov if (CheckSVEBuiltinFunctionCall(BuiltinID, TheCall)) 1101ed35a92cSVlad Serebrennikov return true; 1102ed35a92cSVlad Serebrennikov 1103ed35a92cSVlad Serebrennikov if (CheckSMEBuiltinFunctionCall(BuiltinID, TheCall)) 1104ed35a92cSVlad Serebrennikov return true; 1105ed35a92cSVlad Serebrennikov 1106ed35a92cSVlad Serebrennikov // For intrinsics which take an immediate value as part of the instruction, 1107ed35a92cSVlad Serebrennikov // range check them here. 1108ed35a92cSVlad Serebrennikov unsigned i = 0, l = 0, u = 0; 1109ed35a92cSVlad Serebrennikov switch (BuiltinID) { 1110ed35a92cSVlad Serebrennikov default: return false; 1111ed35a92cSVlad Serebrennikov case AArch64::BI__builtin_arm_dmb: 1112ed35a92cSVlad Serebrennikov case AArch64::BI__builtin_arm_dsb: 1113ed35a92cSVlad Serebrennikov case AArch64::BI__builtin_arm_isb: l = 0; u = 15; break; 1114ed35a92cSVlad Serebrennikov case AArch64::BI__builtin_arm_tcancel: l = 0; u = 65535; break; 1115ed35a92cSVlad Serebrennikov } 1116ed35a92cSVlad Serebrennikov 1117ed35a92cSVlad Serebrennikov return SemaRef.BuiltinConstantArgRange(TheCall, i, l, u + l); 1118ed35a92cSVlad Serebrennikov } 1119ed35a92cSVlad Serebrennikov 11206b755b0cSVlad Serebrennikov namespace { 11216b755b0cSVlad Serebrennikov struct IntrinToName { 11226b755b0cSVlad Serebrennikov uint32_t Id; 11236b755b0cSVlad Serebrennikov int32_t FullName; 11246b755b0cSVlad Serebrennikov int32_t ShortName; 11256b755b0cSVlad Serebrennikov }; 11266b755b0cSVlad Serebrennikov } // unnamed namespace 11276b755b0cSVlad Serebrennikov 11286b755b0cSVlad Serebrennikov static bool BuiltinAliasValid(unsigned BuiltinID, StringRef AliasName, 11296b755b0cSVlad Serebrennikov ArrayRef<IntrinToName> Map, 11306b755b0cSVlad Serebrennikov const char *IntrinNames) { 11316b755b0cSVlad Serebrennikov AliasName.consume_front("__arm_"); 11326b755b0cSVlad Serebrennikov const IntrinToName *It = 11336b755b0cSVlad Serebrennikov llvm::lower_bound(Map, BuiltinID, [](const IntrinToName &L, unsigned Id) { 11346b755b0cSVlad Serebrennikov return L.Id < Id; 11356b755b0cSVlad Serebrennikov }); 11366b755b0cSVlad Serebrennikov if (It == Map.end() || It->Id != BuiltinID) 11376b755b0cSVlad Serebrennikov return false; 11386b755b0cSVlad Serebrennikov StringRef FullName(&IntrinNames[It->FullName]); 11396b755b0cSVlad Serebrennikov if (AliasName == FullName) 11406b755b0cSVlad Serebrennikov return true; 11416b755b0cSVlad Serebrennikov if (It->ShortName == -1) 11426b755b0cSVlad Serebrennikov return false; 11436b755b0cSVlad Serebrennikov StringRef ShortName(&IntrinNames[It->ShortName]); 11446b755b0cSVlad Serebrennikov return AliasName == ShortName; 11456b755b0cSVlad Serebrennikov } 11466b755b0cSVlad Serebrennikov 11476b755b0cSVlad Serebrennikov bool SemaARM::MveAliasValid(unsigned BuiltinID, StringRef AliasName) { 11486b755b0cSVlad Serebrennikov #include "clang/Basic/arm_mve_builtin_aliases.inc" 11496b755b0cSVlad Serebrennikov // The included file defines: 11506b755b0cSVlad Serebrennikov // - ArrayRef<IntrinToName> Map 11516b755b0cSVlad Serebrennikov // - const char IntrinNames[] 11526b755b0cSVlad Serebrennikov return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames); 11536b755b0cSVlad Serebrennikov } 11546b755b0cSVlad Serebrennikov 11556b755b0cSVlad Serebrennikov bool SemaARM::CdeAliasValid(unsigned BuiltinID, StringRef AliasName) { 11566b755b0cSVlad Serebrennikov #include "clang/Basic/arm_cde_builtin_aliases.inc" 11576b755b0cSVlad Serebrennikov return BuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames); 11586b755b0cSVlad Serebrennikov } 11596b755b0cSVlad Serebrennikov 11606b755b0cSVlad Serebrennikov bool SemaARM::SveAliasValid(unsigned BuiltinID, StringRef AliasName) { 11616b755b0cSVlad Serebrennikov if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID)) 11626b755b0cSVlad Serebrennikov BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID); 11636b755b0cSVlad Serebrennikov return BuiltinID >= AArch64::FirstSVEBuiltin && 11646b755b0cSVlad Serebrennikov BuiltinID <= AArch64::LastSVEBuiltin; 11656b755b0cSVlad Serebrennikov } 11666b755b0cSVlad Serebrennikov 11676b755b0cSVlad Serebrennikov bool SemaARM::SmeAliasValid(unsigned BuiltinID, StringRef AliasName) { 11686b755b0cSVlad Serebrennikov if (getASTContext().BuiltinInfo.isAuxBuiltinID(BuiltinID)) 11696b755b0cSVlad Serebrennikov BuiltinID = getASTContext().BuiltinInfo.getAuxBuiltinID(BuiltinID); 11706b755b0cSVlad Serebrennikov return BuiltinID >= AArch64::FirstSMEBuiltin && 11716b755b0cSVlad Serebrennikov BuiltinID <= AArch64::LastSMEBuiltin; 11726b755b0cSVlad Serebrennikov } 11736b755b0cSVlad Serebrennikov 11746b755b0cSVlad Serebrennikov void SemaARM::handleBuiltinAliasAttr(Decl *D, const ParsedAttr &AL) { 11756b755b0cSVlad Serebrennikov ASTContext &Context = getASTContext(); 11766b755b0cSVlad Serebrennikov if (!AL.isArgIdent(0)) { 11776b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 11786b755b0cSVlad Serebrennikov << AL << 1 << AANT_ArgumentIdentifier; 11796b755b0cSVlad Serebrennikov return; 11806b755b0cSVlad Serebrennikov } 11816b755b0cSVlad Serebrennikov 11826b755b0cSVlad Serebrennikov IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident; 11836b755b0cSVlad Serebrennikov unsigned BuiltinID = Ident->getBuiltinID(); 11846b755b0cSVlad Serebrennikov StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName(); 11856b755b0cSVlad Serebrennikov 11866b755b0cSVlad Serebrennikov bool IsAArch64 = Context.getTargetInfo().getTriple().isAArch64(); 11876b755b0cSVlad Serebrennikov if ((IsAArch64 && !SveAliasValid(BuiltinID, AliasName) && 11886b755b0cSVlad Serebrennikov !SmeAliasValid(BuiltinID, AliasName)) || 11896b755b0cSVlad Serebrennikov (!IsAArch64 && !MveAliasValid(BuiltinID, AliasName) && 11906b755b0cSVlad Serebrennikov !CdeAliasValid(BuiltinID, AliasName))) { 11916b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias); 11926b755b0cSVlad Serebrennikov return; 11936b755b0cSVlad Serebrennikov } 11946b755b0cSVlad Serebrennikov 11956b755b0cSVlad Serebrennikov D->addAttr(::new (Context) ArmBuiltinAliasAttr(Context, AL, Ident)); 11966b755b0cSVlad Serebrennikov } 11976b755b0cSVlad Serebrennikov 11986b755b0cSVlad Serebrennikov static bool checkNewAttrMutualExclusion( 11996b755b0cSVlad Serebrennikov Sema &S, const ParsedAttr &AL, const FunctionProtoType *FPT, 12006b755b0cSVlad Serebrennikov FunctionType::ArmStateValue CurrentState, StringRef StateName) { 12016b755b0cSVlad Serebrennikov auto CheckForIncompatibleAttr = 12026b755b0cSVlad Serebrennikov [&](FunctionType::ArmStateValue IncompatibleState, 12036b755b0cSVlad Serebrennikov StringRef IncompatibleStateName) { 12046b755b0cSVlad Serebrennikov if (CurrentState == IncompatibleState) { 12056b755b0cSVlad Serebrennikov S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) 12066b755b0cSVlad Serebrennikov << (std::string("'__arm_new(\"") + StateName.str() + "\")'") 12076b755b0cSVlad Serebrennikov << (std::string("'") + IncompatibleStateName.str() + "(\"" + 12086b755b0cSVlad Serebrennikov StateName.str() + "\")'") 12096b755b0cSVlad Serebrennikov << true; 12106b755b0cSVlad Serebrennikov AL.setInvalid(); 12116b755b0cSVlad Serebrennikov } 12126b755b0cSVlad Serebrennikov }; 12136b755b0cSVlad Serebrennikov 12146b755b0cSVlad Serebrennikov CheckForIncompatibleAttr(FunctionType::ARM_In, "__arm_in"); 12156b755b0cSVlad Serebrennikov CheckForIncompatibleAttr(FunctionType::ARM_Out, "__arm_out"); 12166b755b0cSVlad Serebrennikov CheckForIncompatibleAttr(FunctionType::ARM_InOut, "__arm_inout"); 12176b755b0cSVlad Serebrennikov CheckForIncompatibleAttr(FunctionType::ARM_Preserves, "__arm_preserves"); 12186b755b0cSVlad Serebrennikov return AL.isInvalid(); 12196b755b0cSVlad Serebrennikov } 12206b755b0cSVlad Serebrennikov 12216b755b0cSVlad Serebrennikov void SemaARM::handleNewAttr(Decl *D, const ParsedAttr &AL) { 12226b755b0cSVlad Serebrennikov if (!AL.getNumArgs()) { 12236b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_missing_arm_state) << AL; 12246b755b0cSVlad Serebrennikov AL.setInvalid(); 12256b755b0cSVlad Serebrennikov return; 12266b755b0cSVlad Serebrennikov } 12276b755b0cSVlad Serebrennikov 12286b755b0cSVlad Serebrennikov std::vector<StringRef> NewState; 12296b755b0cSVlad Serebrennikov if (const auto *ExistingAttr = D->getAttr<ArmNewAttr>()) { 12306b755b0cSVlad Serebrennikov for (StringRef S : ExistingAttr->newArgs()) 12316b755b0cSVlad Serebrennikov NewState.push_back(S); 12326b755b0cSVlad Serebrennikov } 12336b755b0cSVlad Serebrennikov 12346b755b0cSVlad Serebrennikov bool HasZA = false; 12356b755b0cSVlad Serebrennikov bool HasZT0 = false; 12366b755b0cSVlad Serebrennikov for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { 12376b755b0cSVlad Serebrennikov StringRef StateName; 12386b755b0cSVlad Serebrennikov SourceLocation LiteralLoc; 12396b755b0cSVlad Serebrennikov if (!SemaRef.checkStringLiteralArgumentAttr(AL, I, StateName, &LiteralLoc)) 12406b755b0cSVlad Serebrennikov return; 12416b755b0cSVlad Serebrennikov 12426b755b0cSVlad Serebrennikov if (StateName == "za") 12436b755b0cSVlad Serebrennikov HasZA = true; 12446b755b0cSVlad Serebrennikov else if (StateName == "zt0") 12456b755b0cSVlad Serebrennikov HasZT0 = true; 12466b755b0cSVlad Serebrennikov else { 12476b755b0cSVlad Serebrennikov Diag(LiteralLoc, diag::err_unknown_arm_state) << StateName; 12486b755b0cSVlad Serebrennikov AL.setInvalid(); 12496b755b0cSVlad Serebrennikov return; 12506b755b0cSVlad Serebrennikov } 12516b755b0cSVlad Serebrennikov 12526b755b0cSVlad Serebrennikov if (!llvm::is_contained(NewState, StateName)) // Avoid adding duplicates. 12536b755b0cSVlad Serebrennikov NewState.push_back(StateName); 12546b755b0cSVlad Serebrennikov } 12556b755b0cSVlad Serebrennikov 12566b755b0cSVlad Serebrennikov if (auto *FPT = dyn_cast<FunctionProtoType>(D->getFunctionType())) { 12576b755b0cSVlad Serebrennikov FunctionType::ArmStateValue ZAState = 12586b755b0cSVlad Serebrennikov FunctionType::getArmZAState(FPT->getAArch64SMEAttributes()); 12596b755b0cSVlad Serebrennikov if (HasZA && ZAState != FunctionType::ARM_None && 12606b755b0cSVlad Serebrennikov checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZAState, "za")) 12616b755b0cSVlad Serebrennikov return; 12626b755b0cSVlad Serebrennikov FunctionType::ArmStateValue ZT0State = 12636b755b0cSVlad Serebrennikov FunctionType::getArmZT0State(FPT->getAArch64SMEAttributes()); 12646b755b0cSVlad Serebrennikov if (HasZT0 && ZT0State != FunctionType::ARM_None && 12656b755b0cSVlad Serebrennikov checkNewAttrMutualExclusion(SemaRef, AL, FPT, ZT0State, "zt0")) 12666b755b0cSVlad Serebrennikov return; 12676b755b0cSVlad Serebrennikov } 12686b755b0cSVlad Serebrennikov 12696b755b0cSVlad Serebrennikov D->dropAttr<ArmNewAttr>(); 12706b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) ArmNewAttr( 12716b755b0cSVlad Serebrennikov getASTContext(), AL, NewState.data(), NewState.size())); 12726b755b0cSVlad Serebrennikov } 12736b755b0cSVlad Serebrennikov 12746b755b0cSVlad Serebrennikov void SemaARM::handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL) { 12756b755b0cSVlad Serebrennikov if (getLangOpts().CPlusPlus && !D->getDeclContext()->isExternCContext()) { 12766b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL; 12776b755b0cSVlad Serebrennikov return; 12786b755b0cSVlad Serebrennikov } 12796b755b0cSVlad Serebrennikov 12806b755b0cSVlad Serebrennikov const auto *FD = cast<FunctionDecl>(D); 12816b755b0cSVlad Serebrennikov if (!FD->isExternallyVisible()) { 12826b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static); 12836b755b0cSVlad Serebrennikov return; 12846b755b0cSVlad Serebrennikov } 12856b755b0cSVlad Serebrennikov 12866b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) CmseNSEntryAttr(getASTContext(), AL)); 12876b755b0cSVlad Serebrennikov } 12886b755b0cSVlad Serebrennikov 12896b755b0cSVlad Serebrennikov void SemaARM::handleInterruptAttr(Decl *D, const ParsedAttr &AL) { 12906b755b0cSVlad Serebrennikov // Check the attribute arguments. 12916b755b0cSVlad Serebrennikov if (AL.getNumArgs() > 1) { 12926b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1; 12936b755b0cSVlad Serebrennikov return; 12946b755b0cSVlad Serebrennikov } 12956b755b0cSVlad Serebrennikov 12966b755b0cSVlad Serebrennikov StringRef Str; 12976b755b0cSVlad Serebrennikov SourceLocation ArgLoc; 12986b755b0cSVlad Serebrennikov 12996b755b0cSVlad Serebrennikov if (AL.getNumArgs() == 0) 13006b755b0cSVlad Serebrennikov Str = ""; 13016b755b0cSVlad Serebrennikov else if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) 13026b755b0cSVlad Serebrennikov return; 13036b755b0cSVlad Serebrennikov 13046b755b0cSVlad Serebrennikov ARMInterruptAttr::InterruptType Kind; 13056b755b0cSVlad Serebrennikov if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) { 13066b755b0cSVlad Serebrennikov Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) 13076b755b0cSVlad Serebrennikov << AL << Str << ArgLoc; 13086b755b0cSVlad Serebrennikov return; 13096b755b0cSVlad Serebrennikov } 13106b755b0cSVlad Serebrennikov 1311588a6d7dSChris Copeland const TargetInfo &TI = getASTContext().getTargetInfo(); 1312588a6d7dSChris Copeland if (TI.hasFeature("vfp")) 1313588a6d7dSChris Copeland Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber); 1314588a6d7dSChris Copeland 13156b755b0cSVlad Serebrennikov D->addAttr(::new (getASTContext()) 13166b755b0cSVlad Serebrennikov ARMInterruptAttr(getASTContext(), AL, Kind)); 13176b755b0cSVlad Serebrennikov } 13186b755b0cSVlad Serebrennikov 13194e32271eSKerry McLaughlin // Check if the function definition uses any AArch64 SME features without 13204e32271eSKerry McLaughlin // having the '+sme' feature enabled and warn user if sme locally streaming 13214e32271eSKerry McLaughlin // function returns or uses arguments with VL-based types. 13224e32271eSKerry McLaughlin void SemaARM::CheckSMEFunctionDefAttributes(const FunctionDecl *FD) { 13234e32271eSKerry McLaughlin const auto *Attr = FD->getAttr<ArmNewAttr>(); 13244e32271eSKerry McLaughlin bool UsesSM = FD->hasAttr<ArmLocallyStreamingAttr>(); 13254e32271eSKerry McLaughlin bool UsesZA = Attr && Attr->isNewZA(); 13264e32271eSKerry McLaughlin bool UsesZT0 = Attr && Attr->isNewZT0(); 13274e32271eSKerry McLaughlin 1328b4ce29abSSander de Smalen if (UsesZA || UsesZT0) { 1329b4ce29abSSander de Smalen if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) { 1330b4ce29abSSander de Smalen FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); 1331b4ce29abSSander de Smalen if (EPI.AArch64SMEAttributes & FunctionType::SME_AgnosticZAStateMask) 1332b4ce29abSSander de Smalen Diag(FD->getLocation(), diag::err_sme_unsupported_agnostic_new); 1333b4ce29abSSander de Smalen } 1334b4ce29abSSander de Smalen } 1335b4ce29abSSander de Smalen 13364e32271eSKerry McLaughlin if (FD->hasAttr<ArmLocallyStreamingAttr>()) { 13374e32271eSKerry McLaughlin if (FD->getReturnType()->isSizelessVectorType()) 13384e32271eSKerry McLaughlin Diag(FD->getLocation(), 13394e32271eSKerry McLaughlin diag::warn_sme_locally_streaming_has_vl_args_returns) 13404e32271eSKerry McLaughlin << /*IsArg=*/false; 13414e32271eSKerry McLaughlin if (llvm::any_of(FD->parameters(), [](ParmVarDecl *P) { 13424e32271eSKerry McLaughlin return P->getOriginalType()->isSizelessVectorType(); 13434e32271eSKerry McLaughlin })) 13444e32271eSKerry McLaughlin Diag(FD->getLocation(), 13454e32271eSKerry McLaughlin diag::warn_sme_locally_streaming_has_vl_args_returns) 13464e32271eSKerry McLaughlin << /*IsArg=*/true; 13474e32271eSKerry McLaughlin } 13484e32271eSKerry McLaughlin if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) { 13494e32271eSKerry McLaughlin FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); 13504e32271eSKerry McLaughlin UsesSM |= EPI.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask; 13514e32271eSKerry McLaughlin UsesZA |= FunctionType::getArmZAState(EPI.AArch64SMEAttributes) != 13524e32271eSKerry McLaughlin FunctionType::ARM_None; 13534e32271eSKerry McLaughlin UsesZT0 |= FunctionType::getArmZT0State(EPI.AArch64SMEAttributes) != 13544e32271eSKerry McLaughlin FunctionType::ARM_None; 13554e32271eSKerry McLaughlin } 13564e32271eSKerry McLaughlin 13574e32271eSKerry McLaughlin ASTContext &Context = getASTContext(); 13584e32271eSKerry McLaughlin if (UsesSM || UsesZA) { 13594e32271eSKerry McLaughlin llvm::StringMap<bool> FeatureMap; 13604e32271eSKerry McLaughlin Context.getFunctionFeatureMap(FeatureMap, FD); 13614e32271eSKerry McLaughlin if (!FeatureMap.contains("sme")) { 13624e32271eSKerry McLaughlin if (UsesSM) 13634e32271eSKerry McLaughlin Diag(FD->getLocation(), 13644e32271eSKerry McLaughlin diag::err_sme_definition_using_sm_in_non_sme_target); 13654e32271eSKerry McLaughlin else 13664e32271eSKerry McLaughlin Diag(FD->getLocation(), 13674e32271eSKerry McLaughlin diag::err_sme_definition_using_za_in_non_sme_target); 13684e32271eSKerry McLaughlin } 13694e32271eSKerry McLaughlin } 13704e32271eSKerry McLaughlin if (UsesZT0) { 13714e32271eSKerry McLaughlin llvm::StringMap<bool> FeatureMap; 13724e32271eSKerry McLaughlin Context.getFunctionFeatureMap(FeatureMap, FD); 13734e32271eSKerry McLaughlin if (!FeatureMap.contains("sme2")) { 13744e32271eSKerry McLaughlin Diag(FD->getLocation(), 13754e32271eSKerry McLaughlin diag::err_sme_definition_using_zt0_in_non_sme2_target); 13764e32271eSKerry McLaughlin } 13774e32271eSKerry McLaughlin } 13784e32271eSKerry McLaughlin } 13794e32271eSKerry McLaughlin 1380ed35a92cSVlad Serebrennikov } // namespace clang 1381