brintos

brintos / llvm-project-archived public Read only

0
0
Text · 165.3 KiB · ecab394 Raw
4554 lines · cpp
1//===- SemaHLSL.cpp - Semantic Analysis for HLSL constructs ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// This implements Semantic Analysis for HLSL constructs.9//===----------------------------------------------------------------------===//10 11#include "clang/Sema/SemaHLSL.h"12#include "clang/AST/ASTConsumer.h"13#include "clang/AST/ASTContext.h"14#include "clang/AST/Attr.h"15#include "clang/AST/Attrs.inc"16#include "clang/AST/Decl.h"17#include "clang/AST/DeclBase.h"18#include "clang/AST/DeclCXX.h"19#include "clang/AST/DeclarationName.h"20#include "clang/AST/DynamicRecursiveASTVisitor.h"21#include "clang/AST/Expr.h"22#include "clang/AST/HLSLResource.h"23#include "clang/AST/Type.h"24#include "clang/AST/TypeBase.h"25#include "clang/AST/TypeLoc.h"26#include "clang/Basic/Builtins.h"27#include "clang/Basic/DiagnosticSema.h"28#include "clang/Basic/IdentifierTable.h"29#include "clang/Basic/LLVM.h"30#include "clang/Basic/SourceLocation.h"31#include "clang/Basic/Specifiers.h"32#include "clang/Basic/TargetInfo.h"33#include "clang/Sema/Initialization.h"34#include "clang/Sema/Lookup.h"35#include "clang/Sema/ParsedAttr.h"36#include "clang/Sema/Sema.h"37#include "clang/Sema/Template.h"38#include "llvm/ADT/ArrayRef.h"39#include "llvm/ADT/STLExtras.h"40#include "llvm/ADT/SmallVector.h"41#include "llvm/ADT/StringExtras.h"42#include "llvm/ADT/StringRef.h"43#include "llvm/ADT/Twine.h"44#include "llvm/Frontend/HLSL/HLSLBinding.h"45#include "llvm/Frontend/HLSL/RootSignatureValidations.h"46#include "llvm/Support/Casting.h"47#include "llvm/Support/DXILABI.h"48#include "llvm/Support/ErrorHandling.h"49#include "llvm/Support/FormatVariadic.h"50#include "llvm/TargetParser/Triple.h"51#include <cmath>52#include <cstddef>53#include <iterator>54#include <utility>55 56using namespace clang;57using namespace clang::hlsl;58using RegisterType = HLSLResourceBindingAttr::RegisterType;59 60static CXXRecordDecl *createHostLayoutStruct(Sema &S,61                                             CXXRecordDecl *StructDecl);62 63static RegisterType getRegisterType(ResourceClass RC) {64  switch (RC) {65  case ResourceClass::SRV:66    return RegisterType::SRV;67  case ResourceClass::UAV:68    return RegisterType::UAV;69  case ResourceClass::CBuffer:70    return RegisterType::CBuffer;71  case ResourceClass::Sampler:72    return RegisterType::Sampler;73  }74  llvm_unreachable("unexpected ResourceClass value");75}76 77static RegisterType getRegisterType(const HLSLAttributedResourceType *ResTy) {78  return getRegisterType(ResTy->getAttrs().ResourceClass);79}80 81// Converts the first letter of string Slot to RegisterType.82// Returns false if the letter does not correspond to a valid register type.83static bool convertToRegisterType(StringRef Slot, RegisterType *RT) {84  assert(RT != nullptr);85  switch (Slot[0]) {86  case 't':87  case 'T':88    *RT = RegisterType::SRV;89    return true;90  case 'u':91  case 'U':92    *RT = RegisterType::UAV;93    return true;94  case 'b':95  case 'B':96    *RT = RegisterType::CBuffer;97    return true;98  case 's':99  case 'S':100    *RT = RegisterType::Sampler;101    return true;102  case 'c':103  case 'C':104    *RT = RegisterType::C;105    return true;106  case 'i':107  case 'I':108    *RT = RegisterType::I;109    return true;110  default:111    return false;112  }113}114 115static ResourceClass getResourceClass(RegisterType RT) {116  switch (RT) {117  case RegisterType::SRV:118    return ResourceClass::SRV;119  case RegisterType::UAV:120    return ResourceClass::UAV;121  case RegisterType::CBuffer:122    return ResourceClass::CBuffer;123  case RegisterType::Sampler:124    return ResourceClass::Sampler;125  case RegisterType::C:126  case RegisterType::I:127    // Deliberately falling through to the unreachable below.128    break;129  }130  llvm_unreachable("unexpected RegisterType value");131}132 133static Builtin::ID getSpecConstBuiltinId(const Type *Type) {134  const auto *BT = dyn_cast<BuiltinType>(Type);135  if (!BT) {136    if (!Type->isEnumeralType())137      return Builtin::NotBuiltin;138    return Builtin::BI__builtin_get_spirv_spec_constant_int;139  }140 141  switch (BT->getKind()) {142  case BuiltinType::Bool:143    return Builtin::BI__builtin_get_spirv_spec_constant_bool;144  case BuiltinType::Short:145    return Builtin::BI__builtin_get_spirv_spec_constant_short;146  case BuiltinType::Int:147    return Builtin::BI__builtin_get_spirv_spec_constant_int;148  case BuiltinType::LongLong:149    return Builtin::BI__builtin_get_spirv_spec_constant_longlong;150  case BuiltinType::UShort:151    return Builtin::BI__builtin_get_spirv_spec_constant_ushort;152  case BuiltinType::UInt:153    return Builtin::BI__builtin_get_spirv_spec_constant_uint;154  case BuiltinType::ULongLong:155    return Builtin::BI__builtin_get_spirv_spec_constant_ulonglong;156  case BuiltinType::Half:157    return Builtin::BI__builtin_get_spirv_spec_constant_half;158  case BuiltinType::Float:159    return Builtin::BI__builtin_get_spirv_spec_constant_float;160  case BuiltinType::Double:161    return Builtin::BI__builtin_get_spirv_spec_constant_double;162  default:163    return Builtin::NotBuiltin;164  }165}166 167DeclBindingInfo *ResourceBindings::addDeclBindingInfo(const VarDecl *VD,168                                                      ResourceClass ResClass) {169  assert(getDeclBindingInfo(VD, ResClass) == nullptr &&170         "DeclBindingInfo already added");171  assert(!hasBindingInfoForDecl(VD) || BindingsList.back().Decl == VD);172  // VarDecl may have multiple entries for different resource classes.173  // DeclToBindingListIndex stores the index of the first binding we saw174  // for this decl. If there are any additional ones then that index175  // shouldn't be updated.176  DeclToBindingListIndex.try_emplace(VD, BindingsList.size());177  return &BindingsList.emplace_back(VD, ResClass);178}179 180DeclBindingInfo *ResourceBindings::getDeclBindingInfo(const VarDecl *VD,181                                                      ResourceClass ResClass) {182  auto Entry = DeclToBindingListIndex.find(VD);183  if (Entry != DeclToBindingListIndex.end()) {184    for (unsigned Index = Entry->getSecond();185         Index < BindingsList.size() && BindingsList[Index].Decl == VD;186         ++Index) {187      if (BindingsList[Index].ResClass == ResClass)188        return &BindingsList[Index];189    }190  }191  return nullptr;192}193 194bool ResourceBindings::hasBindingInfoForDecl(const VarDecl *VD) const {195  return DeclToBindingListIndex.contains(VD);196}197 198SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S) {}199 200Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,201                                 SourceLocation KwLoc, IdentifierInfo *Ident,202                                 SourceLocation IdentLoc,203                                 SourceLocation LBrace) {204  // For anonymous namespace, take the location of the left brace.205  DeclContext *LexicalParent = SemaRef.getCurLexicalContext();206  HLSLBufferDecl *Result = HLSLBufferDecl::Create(207      getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);208 209  // if CBuffer is false, then it's a TBuffer210  auto RC = CBuffer ? llvm::hlsl::ResourceClass::CBuffer211                    : llvm::hlsl::ResourceClass::SRV;212  Result->addAttr(HLSLResourceClassAttr::CreateImplicit(getASTContext(), RC));213 214  SemaRef.PushOnScopeChains(Result, BufferScope);215  SemaRef.PushDeclContext(BufferScope, Result);216 217  return Result;218}219 220static unsigned calculateLegacyCbufferFieldAlign(const ASTContext &Context,221                                                 QualType T) {222  // Arrays and Structs are always aligned to new buffer rows223  if (T->isArrayType() || T->isStructureType())224    return 16;225 226  // Vectors are aligned to the type they contain227  if (const VectorType *VT = T->getAs<VectorType>())228    return calculateLegacyCbufferFieldAlign(Context, VT->getElementType());229 230  assert(Context.getTypeSize(T) <= 64 &&231         "Scalar bit widths larger than 64 not supported");232 233  // Scalar types are aligned to their byte width234  return Context.getTypeSize(T) / 8;235}236 237// Calculate the size of a legacy cbuffer type in bytes based on238// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules239static unsigned calculateLegacyCbufferSize(const ASTContext &Context,240                                           QualType T) {241  constexpr unsigned CBufferAlign = 16;242  if (const auto *RD = T->getAsRecordDecl()) {243    unsigned Size = 0;244    for (const FieldDecl *Field : RD->fields()) {245      QualType Ty = Field->getType();246      unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty);247      unsigned FieldAlign = calculateLegacyCbufferFieldAlign(Context, Ty);248 249      // If the field crosses the row boundary after alignment it drops to the250      // next row251      unsigned AlignSize = llvm::alignTo(Size, FieldAlign);252      if ((AlignSize % CBufferAlign) + FieldSize > CBufferAlign) {253        FieldAlign = CBufferAlign;254      }255 256      Size = llvm::alignTo(Size, FieldAlign);257      Size += FieldSize;258    }259    return Size;260  }261 262  if (const ConstantArrayType *AT = Context.getAsConstantArrayType(T)) {263    unsigned ElementCount = AT->getSize().getZExtValue();264    if (ElementCount == 0)265      return 0;266 267    unsigned ElementSize =268        calculateLegacyCbufferSize(Context, AT->getElementType());269    unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);270    return AlignedElementSize * (ElementCount - 1) + ElementSize;271  }272 273  if (const VectorType *VT = T->getAs<VectorType>()) {274    unsigned ElementCount = VT->getNumElements();275    unsigned ElementSize =276        calculateLegacyCbufferSize(Context, VT->getElementType());277    return ElementSize * ElementCount;278  }279 280  return Context.getTypeSize(T) / 8;281}282 283// Validate packoffset:284// - if packoffset it used it must be set on all declarations inside the buffer285// - packoffset ranges must not overlap286static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl) {287  llvm::SmallVector<std::pair<VarDecl *, HLSLPackOffsetAttr *>> PackOffsetVec;288 289  // Make sure the packoffset annotations are either on all declarations290  // or on none.291  bool HasPackOffset = false;292  bool HasNonPackOffset = false;293  for (auto *Field : BufDecl->buffer_decls()) {294    VarDecl *Var = dyn_cast<VarDecl>(Field);295    if (!Var)296      continue;297    if (Field->hasAttr<HLSLPackOffsetAttr>()) {298      PackOffsetVec.emplace_back(Var, Field->getAttr<HLSLPackOffsetAttr>());299      HasPackOffset = true;300    } else {301      HasNonPackOffset = true;302    }303  }304 305  if (!HasPackOffset)306    return;307 308  if (HasNonPackOffset)309    S.Diag(BufDecl->getLocation(), diag::warn_hlsl_packoffset_mix);310 311  // Make sure there is no overlap in packoffset - sort PackOffsetVec by offset312  // and compare adjacent values.313  bool IsValid = true;314  ASTContext &Context = S.getASTContext();315  std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),316            [](const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,317               const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {318              return LHS.second->getOffsetInBytes() <319                     RHS.second->getOffsetInBytes();320            });321  for (unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {322    VarDecl *Var = PackOffsetVec[i].first;323    HLSLPackOffsetAttr *Attr = PackOffsetVec[i].second;324    unsigned Size = calculateLegacyCbufferSize(Context, Var->getType());325    unsigned Begin = Attr->getOffsetInBytes();326    unsigned End = Begin + Size;327    unsigned NextBegin = PackOffsetVec[i + 1].second->getOffsetInBytes();328    if (End > NextBegin) {329      VarDecl *NextVar = PackOffsetVec[i + 1].first;330      S.Diag(NextVar->getLocation(), diag::err_hlsl_packoffset_overlap)331          << NextVar << Var;332      IsValid = false;333    }334  }335  BufDecl->setHasValidPackoffset(IsValid);336}337 338// Returns true if the array has a zero size = if any of the dimensions is 0339static bool isZeroSizedArray(const ConstantArrayType *CAT) {340  while (CAT && !CAT->isZeroSize())341    CAT = dyn_cast<ConstantArrayType>(342        CAT->getElementType()->getUnqualifiedDesugaredType());343  return CAT != nullptr;344}345 346static bool isResourceRecordTypeOrArrayOf(VarDecl *VD) {347  const Type *Ty = VD->getType().getTypePtr();348  return Ty->isHLSLResourceRecord() || Ty->isHLSLResourceRecordArray();349}350 351static const HLSLAttributedResourceType *352getResourceArrayHandleType(VarDecl *VD) {353  assert(VD->getType()->isHLSLResourceRecordArray() &&354         "expected array of resource records");355  const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();356  while (const ArrayType *AT = dyn_cast<ArrayType>(Ty))357    Ty = AT->getArrayElementTypeNoTypeQual()->getUnqualifiedDesugaredType();358  return HLSLAttributedResourceType::findHandleTypeOnResource(Ty);359}360 361// Returns true if the type is a leaf element type that is not valid to be362// included in HLSL Buffer, such as a resource class, empty struct, zero-sized363// array, or a builtin intangible type. Returns false it is a valid leaf element364// type or if it is a record type that needs to be inspected further.365static bool isInvalidConstantBufferLeafElementType(const Type *Ty) {366  Ty = Ty->getUnqualifiedDesugaredType();367  if (Ty->isHLSLResourceRecord() || Ty->isHLSLResourceRecordArray())368    return true;369  if (const auto *RD = Ty->getAsCXXRecordDecl())370    return RD->isEmpty();371  if (Ty->isConstantArrayType() &&372      isZeroSizedArray(cast<ConstantArrayType>(Ty)))373    return true;374  if (Ty->isHLSLBuiltinIntangibleType() || Ty->isHLSLAttributedResourceType())375    return true;376  return false;377}378 379// Returns true if the struct contains at least one element that prevents it380// from being included inside HLSL Buffer as is, such as an intangible type,381// empty struct, or zero-sized array. If it does, a new implicit layout struct382// needs to be created for HLSL Buffer use that will exclude these unwanted383// declarations (see createHostLayoutStruct function).384static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD) {385  if (RD->isHLSLIntangible() || RD->isEmpty())386    return true;387  // check fields388  for (const FieldDecl *Field : RD->fields()) {389    QualType Ty = Field->getType();390    if (isInvalidConstantBufferLeafElementType(Ty.getTypePtr()))391      return true;392    if (const auto *RD = Ty->getAsCXXRecordDecl();393        RD && requiresImplicitBufferLayoutStructure(RD))394      return true;395  }396  // check bases397  for (const CXXBaseSpecifier &Base : RD->bases())398    if (requiresImplicitBufferLayoutStructure(399            Base.getType()->castAsCXXRecordDecl()))400      return true;401  return false;402}403 404static CXXRecordDecl *findRecordDeclInContext(IdentifierInfo *II,405                                              DeclContext *DC) {406  CXXRecordDecl *RD = nullptr;407  for (NamedDecl *Decl :408       DC->getNonTransparentContext()->lookup(DeclarationName(II))) {409    if (CXXRecordDecl *FoundRD = dyn_cast<CXXRecordDecl>(Decl)) {410      assert(RD == nullptr &&411             "there should be at most 1 record by a given name in a scope");412      RD = FoundRD;413    }414  }415  return RD;416}417 418// Creates a name for buffer layout struct using the provide name base.419// If the name must be unique (not previously defined), a suffix is added420// until a unique name is found.421static IdentifierInfo *getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl,422                                               bool MustBeUnique) {423  ASTContext &AST = S.getASTContext();424 425  IdentifierInfo *NameBaseII = BaseDecl->getIdentifier();426  llvm::SmallString<64> Name("__cblayout_");427  if (NameBaseII) {428    Name.append(NameBaseII->getName());429  } else {430    // anonymous struct431    Name.append("anon");432    MustBeUnique = true;433  }434 435  size_t NameLength = Name.size();436  IdentifierInfo *II = &AST.Idents.get(Name, tok::TokenKind::identifier);437  if (!MustBeUnique)438    return II;439 440  unsigned suffix = 0;441  while (true) {442    if (suffix != 0) {443      Name.append("_");444      Name.append(llvm::Twine(suffix).str());445      II = &AST.Idents.get(Name, tok::TokenKind::identifier);446    }447    if (!findRecordDeclInContext(II, BaseDecl->getDeclContext()))448      return II;449    // declaration with that name already exists - increment suffix and try450    // again until unique name is found451    suffix++;452    Name.truncate(NameLength);453  };454}455 456// Creates a field declaration of given name and type for HLSL buffer layout457// struct. Returns nullptr if the type cannot be use in HLSL Buffer layout.458static FieldDecl *createFieldForHostLayoutStruct(Sema &S, const Type *Ty,459                                                 IdentifierInfo *II,460                                                 CXXRecordDecl *LayoutStruct) {461  if (isInvalidConstantBufferLeafElementType(Ty))462    return nullptr;463 464  if (auto *RD = Ty->getAsCXXRecordDecl()) {465    if (requiresImplicitBufferLayoutStructure(RD)) {466      RD = createHostLayoutStruct(S, RD);467      if (!RD)468        return nullptr;469      Ty = S.Context.getCanonicalTagType(RD)->getTypePtr();470    }471  }472 473  QualType QT = QualType(Ty, 0);474  ASTContext &AST = S.getASTContext();475  TypeSourceInfo *TSI = AST.getTrivialTypeSourceInfo(QT, SourceLocation());476  auto *Field = FieldDecl::Create(AST, LayoutStruct, SourceLocation(),477                                  SourceLocation(), II, QT, TSI, nullptr, false,478                                  InClassInitStyle::ICIS_NoInit);479  Field->setAccess(AccessSpecifier::AS_public);480  return Field;481}482 483// Creates host layout struct for a struct included in HLSL Buffer.484// The layout struct will include only fields that are allowed in HLSL buffer.485// These fields will be filtered out:486// - resource classes487// - empty structs488// - zero-sized arrays489// Returns nullptr if the resulting layout struct would be empty.490static CXXRecordDecl *createHostLayoutStruct(Sema &S,491                                             CXXRecordDecl *StructDecl) {492  assert(requiresImplicitBufferLayoutStructure(StructDecl) &&493         "struct is already HLSL buffer compatible");494 495  ASTContext &AST = S.getASTContext();496  DeclContext *DC = StructDecl->getDeclContext();497  IdentifierInfo *II = getHostLayoutStructName(S, StructDecl, false);498 499  // reuse existing if the layout struct if it already exists500  if (CXXRecordDecl *RD = findRecordDeclInContext(II, DC))501    return RD;502 503  CXXRecordDecl *LS =504      CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, DC, SourceLocation(),505                            SourceLocation(), II);506  LS->setImplicit(true);507  LS->addAttr(PackedAttr::CreateImplicit(AST));508  LS->startDefinition();509 510  // copy base struct, create HLSL Buffer compatible version if needed511  if (unsigned NumBases = StructDecl->getNumBases()) {512    assert(NumBases == 1 && "HLSL supports only one base type");513    (void)NumBases;514    CXXBaseSpecifier Base = *StructDecl->bases_begin();515    CXXRecordDecl *BaseDecl = Base.getType()->castAsCXXRecordDecl();516    if (requiresImplicitBufferLayoutStructure(BaseDecl)) {517      BaseDecl = createHostLayoutStruct(S, BaseDecl);518      if (BaseDecl) {519        TypeSourceInfo *TSI =520            AST.getTrivialTypeSourceInfo(AST.getCanonicalTagType(BaseDecl));521        Base = CXXBaseSpecifier(SourceRange(), false, StructDecl->isClass(),522                                AS_none, TSI, SourceLocation());523      }524    }525    if (BaseDecl) {526      const CXXBaseSpecifier *BasesArray[1] = {&Base};527      LS->setBases(BasesArray, 1);528    }529  }530 531  // filter struct fields532  for (const FieldDecl *FD : StructDecl->fields()) {533    const Type *Ty = FD->getType()->getUnqualifiedDesugaredType();534    if (FieldDecl *NewFD =535            createFieldForHostLayoutStruct(S, Ty, FD->getIdentifier(), LS))536      LS->addDecl(NewFD);537  }538  LS->completeDefinition();539 540  if (LS->field_empty() && LS->getNumBases() == 0)541    return nullptr;542 543  DC->addDecl(LS);544  return LS;545}546 547// Creates host layout struct for HLSL Buffer. The struct will include only548// fields of types that are allowed in HLSL buffer and it will filter out:549// - static or groupshared variable declarations550// - resource classes551// - empty structs552// - zero-sized arrays553// - non-variable declarations554// The layout struct will be added to the HLSLBufferDecl declarations.555void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {556  ASTContext &AST = S.getASTContext();557  IdentifierInfo *II = getHostLayoutStructName(S, BufDecl, true);558 559  CXXRecordDecl *LS =560      CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, BufDecl,561                            SourceLocation(), SourceLocation(), II);562  LS->addAttr(PackedAttr::CreateImplicit(AST));563  LS->setImplicit(true);564  LS->startDefinition();565 566  for (Decl *D : BufDecl->buffer_decls()) {567    VarDecl *VD = dyn_cast<VarDecl>(D);568    if (!VD || VD->getStorageClass() == SC_Static ||569        VD->getType().getAddressSpace() == LangAS::hlsl_groupshared)570      continue;571    const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();572    if (FieldDecl *FD =573            createFieldForHostLayoutStruct(S, Ty, VD->getIdentifier(), LS)) {574      // add the field decl to the layout struct575      LS->addDecl(FD);576      // update address space of the original decl to hlsl_constant577      QualType NewTy =578          AST.getAddrSpaceQualType(VD->getType(), LangAS::hlsl_constant);579      VD->setType(NewTy);580    }581  }582  LS->completeDefinition();583  BufDecl->addLayoutStruct(LS);584}585 586static void addImplicitBindingAttrToDecl(Sema &S, Decl *D, RegisterType RT,587                                         uint32_t ImplicitBindingOrderID) {588  auto *Attr =589      HLSLResourceBindingAttr::CreateImplicit(S.getASTContext(), "", "0", {});590  Attr->setBinding(RT, std::nullopt, 0);591  Attr->setImplicitBindingOrderID(ImplicitBindingOrderID);592  D->addAttr(Attr);593}594 595// Handle end of cbuffer/tbuffer declaration596void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) {597  auto *BufDecl = cast<HLSLBufferDecl>(Dcl);598  BufDecl->setRBraceLoc(RBrace);599 600  validatePackoffset(SemaRef, BufDecl);601 602  createHostLayoutStructForBuffer(SemaRef, BufDecl);603 604  // Handle implicit binding if needed.605  ResourceBindingAttrs ResourceAttrs(Dcl);606  if (!ResourceAttrs.isExplicit()) {607    SemaRef.Diag(Dcl->getLocation(), diag::warn_hlsl_implicit_binding);608    // Use HLSLResourceBindingAttr to transfer implicit binding order_ID609    // to codegen. If it does not exist, create an implicit attribute.610    uint32_t OrderID = getNextImplicitBindingOrderID();611    if (ResourceAttrs.hasBinding())612      ResourceAttrs.setImplicitOrderID(OrderID);613    else614      addImplicitBindingAttrToDecl(SemaRef, BufDecl,615                                   BufDecl->isCBuffer() ? RegisterType::CBuffer616                                                        : RegisterType::SRV,617                                   OrderID);618  }619 620  SemaRef.PopDeclContext();621}622 623HLSLNumThreadsAttr *SemaHLSL::mergeNumThreadsAttr(Decl *D,624                                                  const AttributeCommonInfo &AL,625                                                  int X, int Y, int Z) {626  if (HLSLNumThreadsAttr *NT = D->getAttr<HLSLNumThreadsAttr>()) {627    if (NT->getX() != X || NT->getY() != Y || NT->getZ() != Z) {628      Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;629      Diag(AL.getLoc(), diag::note_conflicting_attribute);630    }631    return nullptr;632  }633  return ::new (getASTContext())634      HLSLNumThreadsAttr(getASTContext(), AL, X, Y, Z);635}636 637HLSLWaveSizeAttr *SemaHLSL::mergeWaveSizeAttr(Decl *D,638                                              const AttributeCommonInfo &AL,639                                              int Min, int Max, int Preferred,640                                              int SpelledArgsCount) {641  if (HLSLWaveSizeAttr *WS = D->getAttr<HLSLWaveSizeAttr>()) {642    if (WS->getMin() != Min || WS->getMax() != Max ||643        WS->getPreferred() != Preferred ||644        WS->getSpelledArgsCount() != SpelledArgsCount) {645      Diag(WS->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;646      Diag(AL.getLoc(), diag::note_conflicting_attribute);647    }648    return nullptr;649  }650  HLSLWaveSizeAttr *Result = ::new (getASTContext())651      HLSLWaveSizeAttr(getASTContext(), AL, Min, Max, Preferred);652  Result->setSpelledArgsCount(SpelledArgsCount);653  return Result;654}655 656HLSLVkConstantIdAttr *657SemaHLSL::mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL,658                                int Id) {659 660  auto &TargetInfo = getASTContext().getTargetInfo();661  if (TargetInfo.getTriple().getArch() != llvm::Triple::spirv) {662    Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;663    return nullptr;664  }665 666  auto *VD = cast<VarDecl>(D);667 668  if (getSpecConstBuiltinId(VD->getType()->getUnqualifiedDesugaredType()) ==669      Builtin::NotBuiltin) {670    Diag(VD->getLocation(), diag::err_specialization_const);671    return nullptr;672  }673 674  if (!VD->getType().isConstQualified()) {675    Diag(VD->getLocation(), diag::err_specialization_const);676    return nullptr;677  }678 679  if (HLSLVkConstantIdAttr *CI = D->getAttr<HLSLVkConstantIdAttr>()) {680    if (CI->getId() != Id) {681      Diag(CI->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;682      Diag(AL.getLoc(), diag::note_conflicting_attribute);683    }684    return nullptr;685  }686 687  HLSLVkConstantIdAttr *Result =688      ::new (getASTContext()) HLSLVkConstantIdAttr(getASTContext(), AL, Id);689  return Result;690}691 692HLSLShaderAttr *693SemaHLSL::mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL,694                          llvm::Triple::EnvironmentType ShaderType) {695  if (HLSLShaderAttr *NT = D->getAttr<HLSLShaderAttr>()) {696    if (NT->getType() != ShaderType) {697      Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;698      Diag(AL.getLoc(), diag::note_conflicting_attribute);699    }700    return nullptr;701  }702  return HLSLShaderAttr::Create(getASTContext(), ShaderType, AL);703}704 705HLSLParamModifierAttr *706SemaHLSL::mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL,707                                 HLSLParamModifierAttr::Spelling Spelling) {708  // We can only merge an `in` attribute with an `out` attribute. All other709  // combinations of duplicated attributes are ill-formed.710  if (HLSLParamModifierAttr *PA = D->getAttr<HLSLParamModifierAttr>()) {711    if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||712        (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {713      D->dropAttr<HLSLParamModifierAttr>();714      SourceRange AdjustedRange = {PA->getLocation(), AL.getRange().getEnd()};715      return HLSLParamModifierAttr::Create(716          getASTContext(), /*MergedSpelling=*/true, AdjustedRange,717          HLSLParamModifierAttr::Keyword_inout);718    }719    Diag(AL.getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;720    Diag(PA->getLocation(), diag::note_conflicting_attribute);721    return nullptr;722  }723  return HLSLParamModifierAttr::Create(getASTContext(), AL);724}725 726void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) {727  auto &TargetInfo = getASTContext().getTargetInfo();728 729  if (FD->getName() != TargetInfo.getTargetOpts().HLSLEntry)730    return;731 732  // If we have specified a root signature to override the entry function then733  // attach it now734  HLSLRootSignatureDecl *SignatureDecl =735      lookupRootSignatureOverrideDecl(FD->getDeclContext());736  if (SignatureDecl) {737    FD->dropAttr<RootSignatureAttr>();738    // We could look up the SourceRange of the macro here as well739    AttributeCommonInfo AL(RootSigOverrideIdent, AttributeScopeInfo(),740                           SourceRange(), ParsedAttr::Form::Microsoft());741    FD->addAttr(::new (getASTContext()) RootSignatureAttr(742        getASTContext(), AL, RootSigOverrideIdent, SignatureDecl));743  }744 745  llvm::Triple::EnvironmentType Env = TargetInfo.getTriple().getEnvironment();746  if (HLSLShaderAttr::isValidShaderType(Env) && Env != llvm::Triple::Library) {747    if (const auto *Shader = FD->getAttr<HLSLShaderAttr>()) {748      // The entry point is already annotated - check that it matches the749      // triple.750      if (Shader->getType() != Env) {751        Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)752            << Shader;753        FD->setInvalidDecl();754      }755    } else {756      // Implicitly add the shader attribute if the entry function isn't757      // explicitly annotated.758      FD->addAttr(HLSLShaderAttr::CreateImplicit(getASTContext(), Env,759                                                 FD->getBeginLoc()));760    }761  } else {762    switch (Env) {763    case llvm::Triple::UnknownEnvironment:764    case llvm::Triple::Library:765      break;766    case llvm::Triple::RootSignature:767      llvm_unreachable("rootsig environment has no functions");768    default:769      llvm_unreachable("Unhandled environment in triple");770    }771  }772}773 774bool SemaHLSL::determineActiveSemanticOnScalar(FunctionDecl *FD,775                                               DeclaratorDecl *OutputDecl,776                                               DeclaratorDecl *D,777                                               SemanticInfo &ActiveSemantic,778                                               llvm::StringSet<> &UsedSemantics,779                                               bool IsInput) {780  if (ActiveSemantic.Semantic == nullptr) {781    ActiveSemantic.Semantic = D->getAttr<HLSLParsedSemanticAttr>();782    if (ActiveSemantic.Semantic)783      ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();784  }785 786  if (!ActiveSemantic.Semantic) {787    Diag(D->getLocation(), diag::err_hlsl_missing_semantic_annotation);788    return false;789  }790 791  auto *A = ::new (getASTContext())792      HLSLAppliedSemanticAttr(getASTContext(), *ActiveSemantic.Semantic,793                              ActiveSemantic.Semantic->getAttrName()->getName(),794                              ActiveSemantic.Index.value_or(0));795  if (!A)796    return false;797 798  checkSemanticAnnotation(FD, D, A, IsInput);799  OutputDecl->addAttr(A);800 801  unsigned Location = ActiveSemantic.Index.value_or(0);802 803  const ConstantArrayType *AT = dyn_cast<ConstantArrayType>(D->getType());804  unsigned ElementCount = AT ? AT->getZExtSize() : 1;805  ActiveSemantic.Index = Location + ElementCount;806 807  Twine BaseName = Twine(ActiveSemantic.Semantic->getAttrName()->getName());808  for (unsigned I = 0; I < ElementCount; ++I) {809    Twine VariableName = BaseName.concat(Twine(Location + I));810 811    auto [_, Inserted] = UsedSemantics.insert(VariableName.str());812    if (!Inserted) {813      Diag(D->getLocation(), diag::err_hlsl_semantic_index_overlap)814          << VariableName.str();815      return false;816    }817  }818 819  return true;820}821 822bool SemaHLSL::determineActiveSemantic(FunctionDecl *FD,823                                       DeclaratorDecl *OutputDecl,824                                       DeclaratorDecl *D,825                                       SemanticInfo &ActiveSemantic,826                                       llvm::StringSet<> &UsedSemantics,827                                       bool IsInput) {828  if (ActiveSemantic.Semantic == nullptr) {829    ActiveSemantic.Semantic = D->getAttr<HLSLParsedSemanticAttr>();830    if (ActiveSemantic.Semantic)831      ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();832  }833 834  const Type *T = D == FD ? &*FD->getReturnType() : &*D->getType();835  T = T->getUnqualifiedDesugaredType();836 837  const RecordType *RT = dyn_cast<RecordType>(T);838  if (!RT)839    return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,840                                           UsedSemantics, IsInput);841 842  const RecordDecl *RD = RT->getDecl();843  for (FieldDecl *Field : RD->fields()) {844    SemanticInfo Info = ActiveSemantic;845    if (!determineActiveSemantic(FD, OutputDecl, Field, Info, UsedSemantics,846                                 IsInput)) {847      Diag(Field->getLocation(), diag::note_hlsl_semantic_used_here) << Field;848      return false;849    }850    if (ActiveSemantic.Semantic)851      ActiveSemantic = Info;852  }853 854  return true;855}856 857void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {858  const auto *ShaderAttr = FD->getAttr<HLSLShaderAttr>();859  assert(ShaderAttr && "Entry point has no shader attribute");860  llvm::Triple::EnvironmentType ST = ShaderAttr->getType();861  auto &TargetInfo = getASTContext().getTargetInfo();862  VersionTuple Ver = TargetInfo.getTriple().getOSVersion();863  switch (ST) {864  case llvm::Triple::Pixel:865  case llvm::Triple::Vertex:866  case llvm::Triple::Geometry:867  case llvm::Triple::Hull:868  case llvm::Triple::Domain:869  case llvm::Triple::RayGeneration:870  case llvm::Triple::Intersection:871  case llvm::Triple::AnyHit:872  case llvm::Triple::ClosestHit:873  case llvm::Triple::Miss:874  case llvm::Triple::Callable:875    if (const auto *NT = FD->getAttr<HLSLNumThreadsAttr>()) {876      DiagnoseAttrStageMismatch(NT, ST,877                                {llvm::Triple::Compute,878                                 llvm::Triple::Amplification,879                                 llvm::Triple::Mesh});880      FD->setInvalidDecl();881    }882    if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {883      DiagnoseAttrStageMismatch(WS, ST,884                                {llvm::Triple::Compute,885                                 llvm::Triple::Amplification,886                                 llvm::Triple::Mesh});887      FD->setInvalidDecl();888    }889    break;890 891  case llvm::Triple::Compute:892  case llvm::Triple::Amplification:893  case llvm::Triple::Mesh:894    if (!FD->hasAttr<HLSLNumThreadsAttr>()) {895      Diag(FD->getLocation(), diag::err_hlsl_missing_numthreads)896          << llvm::Triple::getEnvironmentTypeName(ST);897      FD->setInvalidDecl();898    }899    if (const auto *WS = FD->getAttr<HLSLWaveSizeAttr>()) {900      if (Ver < VersionTuple(6, 6)) {901        Diag(WS->getLocation(), diag::err_hlsl_attribute_in_wrong_shader_model)902            << WS << "6.6";903        FD->setInvalidDecl();904      } else if (WS->getSpelledArgsCount() > 1 && Ver < VersionTuple(6, 8)) {905        Diag(906            WS->getLocation(),907            diag::err_hlsl_attribute_number_arguments_insufficient_shader_model)908            << WS << WS->getSpelledArgsCount() << "6.8";909        FD->setInvalidDecl();910      }911    }912    break;913  case llvm::Triple::RootSignature:914    llvm_unreachable("rootsig environment has no function entry point");915  default:916    llvm_unreachable("Unhandled environment in triple");917  }918 919  llvm::StringSet<> ActiveInputSemantics;920  for (ParmVarDecl *Param : FD->parameters()) {921    SemanticInfo ActiveSemantic;922    ActiveSemantic.Semantic = Param->getAttr<HLSLParsedSemanticAttr>();923    if (ActiveSemantic.Semantic)924      ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();925 926    // FIXME: Verify output semantics in parameters.927    if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic,928                                 ActiveInputSemantics, /* IsInput= */ true)) {929      Diag(Param->getLocation(), diag::note_previous_decl) << Param;930      FD->setInvalidDecl();931    }932  }933 934  SemanticInfo ActiveSemantic;935  llvm::StringSet<> ActiveOutputSemantics;936  ActiveSemantic.Semantic = FD->getAttr<HLSLParsedSemanticAttr>();937  if (ActiveSemantic.Semantic)938    ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();939  if (!FD->getReturnType()->isVoidType())940    determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics,941                            /* IsInput= */ false);942}943 944void SemaHLSL::checkSemanticAnnotation(945    FunctionDecl *EntryPoint, const Decl *Param,946    const HLSLAppliedSemanticAttr *SemanticAttr, bool IsInput) {947  auto *ShaderAttr = EntryPoint->getAttr<HLSLShaderAttr>();948  assert(ShaderAttr && "Entry point has no shader attribute");949  llvm::Triple::EnvironmentType ST = ShaderAttr->getType();950 951  auto SemanticName = SemanticAttr->getSemanticName().upper();952  if (SemanticName == "SV_DISPATCHTHREADID" ||953      SemanticName == "SV_GROUPINDEX" || SemanticName == "SV_GROUPTHREADID" ||954      SemanticName == "SV_GROUPID") {955 956    if (ST != llvm::Triple::Compute)957      DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Compute});958 959    if (SemanticAttr->getSemanticIndex() != 0) {960      std::string PrettyName =961          "'" + SemanticAttr->getSemanticName().str() + "'";962      Diag(SemanticAttr->getLoc(),963           diag::err_hlsl_semantic_indexing_not_supported)964          << PrettyName;965    }966    return;967  }968 969  if (SemanticName == "SV_POSITION") {970    // SV_Position can be an input or output in vertex shaders,971    // but only an input in pixel shaders.972    if (ST == llvm::Triple::Vertex || (ST == llvm::Triple::Pixel && IsInput))973      return;974    DiagnoseAttrStageMismatch(SemanticAttr, ST,975                              {llvm::Triple::Pixel, llvm::Triple::Vertex});976    return;977  }978 979  // FIXME: catch-all for non-implemented system semantics reaching this980  // location.981  if (SemanticAttr->getAttrName()->getName().starts_with_insensitive("SV_"))982    llvm_unreachable("Unknown SemanticAttr");983}984 985void SemaHLSL::DiagnoseAttrStageMismatch(986    const Attr *A, llvm::Triple::EnvironmentType Stage,987    std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages) {988  SmallVector<StringRef, 8> StageStrings;989  llvm::transform(AllowedStages, std::back_inserter(StageStrings),990                  [](llvm::Triple::EnvironmentType ST) {991                    return StringRef(992                        HLSLShaderAttr::ConvertEnvironmentTypeToStr(ST));993                  });994  Diag(A->getLoc(), diag::err_hlsl_attr_unsupported_in_stage)995      << A->getAttrName() << llvm::Triple::getEnvironmentTypeName(Stage)996      << (AllowedStages.size() != 1) << join(StageStrings, ", ");997}998 999template <CastKind Kind>1000static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {1001  if (const auto *VTy = Ty->getAs<VectorType>())1002    Ty = VTy->getElementType();1003  Ty = S.getASTContext().getExtVectorType(Ty, Sz);1004  E = S.ImpCastExprToType(E.get(), Ty, Kind);1005}1006 1007template <CastKind Kind>1008static QualType castElement(Sema &S, ExprResult &E, QualType Ty) {1009  E = S.ImpCastExprToType(E.get(), Ty, Kind);1010  return Ty;1011}1012 1013static QualType handleFloatVectorBinOpConversion(1014    Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,1015    QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {1016  bool LHSFloat = LElTy->isRealFloatingType();1017  bool RHSFloat = RElTy->isRealFloatingType();1018 1019  if (LHSFloat && RHSFloat) {1020    if (IsCompAssign ||1021        SemaRef.getASTContext().getFloatingTypeOrder(LElTy, RElTy) > 0)1022      return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);1023 1024    return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);1025  }1026 1027  if (LHSFloat)1028    return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);1029 1030  assert(RHSFloat);1031  if (IsCompAssign)1032    return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);1033 1034  return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);1035}1036 1037static QualType handleIntegerVectorBinOpConversion(1038    Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,1039    QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {1040 1041  int IntOrder = SemaRef.Context.getIntegerTypeOrder(LElTy, RElTy);1042  bool LHSSigned = LElTy->hasSignedIntegerRepresentation();1043  bool RHSSigned = RElTy->hasSignedIntegerRepresentation();1044  auto &Ctx = SemaRef.getASTContext();1045 1046  // If both types have the same signedness, use the higher ranked type.1047  if (LHSSigned == RHSSigned) {1048    if (IsCompAssign || IntOrder >= 0)1049      return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);1050 1051    return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);1052  }1053 1054  // If the unsigned type has greater than or equal rank of the signed type, use1055  // the unsigned type.1056  if (IntOrder != (LHSSigned ? 1 : -1)) {1057    if (IsCompAssign || RHSSigned)1058      return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);1059    return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);1060  }1061 1062  // At this point the signed type has higher rank than the unsigned type, which1063  // means it will be the same size or bigger. If the signed type is bigger, it1064  // can represent all the values of the unsigned type, so select it.1065  if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {1066    if (IsCompAssign || LHSSigned)1067      return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);1068    return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);1069  }1070 1071  // This is a bit of an odd duck case in HLSL. It shouldn't happen, but can due1072  // to C/C++ leaking through. The place this happens today is long vs long1073  // long. When arguments are vector<unsigned long, N> and vector<long long, N>,1074  // the long long has higher rank than long even though they are the same size.1075 1076  // If this is a compound assignment cast the right hand side to the left hand1077  // side's type.1078  if (IsCompAssign)1079    return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);1080 1081  // If this isn't a compound assignment we convert to unsigned long long.1082  QualType ElTy = Ctx.getCorrespondingUnsignedType(LHSSigned ? LElTy : RElTy);1083  QualType NewTy = Ctx.getExtVectorType(1084      ElTy, RHSType->castAs<VectorType>()->getNumElements());1085  (void)castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);1086 1087  return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);1088}1089 1090static CastKind getScalarCastKind(ASTContext &Ctx, QualType DestTy,1091                                  QualType SrcTy) {1092  if (DestTy->isRealFloatingType() && SrcTy->isRealFloatingType())1093    return CK_FloatingCast;1094  if (DestTy->isIntegralType(Ctx) && SrcTy->isIntegralType(Ctx))1095    return CK_IntegralCast;1096  if (DestTy->isRealFloatingType())1097    return CK_IntegralToFloating;1098  assert(SrcTy->isRealFloatingType() && DestTy->isIntegralType(Ctx));1099  return CK_FloatingToIntegral;1100}1101 1102QualType SemaHLSL::handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS,1103                                               QualType LHSType,1104                                               QualType RHSType,1105                                               bool IsCompAssign) {1106  const auto *LVecTy = LHSType->getAs<VectorType>();1107  const auto *RVecTy = RHSType->getAs<VectorType>();1108  auto &Ctx = getASTContext();1109 1110  // If the LHS is not a vector and this is a compound assignment, we truncate1111  // the argument to a scalar then convert it to the LHS's type.1112  if (!LVecTy && IsCompAssign) {1113    QualType RElTy = RHSType->castAs<VectorType>()->getElementType();1114    RHS = SemaRef.ImpCastExprToType(RHS.get(), RElTy, CK_HLSLVectorTruncation);1115    RHSType = RHS.get()->getType();1116    if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))1117      return LHSType;1118    RHS = SemaRef.ImpCastExprToType(RHS.get(), LHSType,1119                                    getScalarCastKind(Ctx, LHSType, RHSType));1120    return LHSType;1121  }1122 1123  unsigned EndSz = std::numeric_limits<unsigned>::max();1124  unsigned LSz = 0;1125  if (LVecTy)1126    LSz = EndSz = LVecTy->getNumElements();1127  if (RVecTy)1128    EndSz = std::min(RVecTy->getNumElements(), EndSz);1129  assert(EndSz != std::numeric_limits<unsigned>::max() &&1130         "one of the above should have had a value");1131 1132  // In a compound assignment, the left operand does not change type, the right1133  // operand is converted to the type of the left operand.1134  if (IsCompAssign && LSz != EndSz) {1135    Diag(LHS.get()->getBeginLoc(),1136         diag::err_hlsl_vector_compound_assignment_truncation)1137        << LHSType << RHSType;1138    return QualType();1139  }1140 1141  if (RVecTy && RVecTy->getNumElements() > EndSz)1142    castVector<CK_HLSLVectorTruncation>(SemaRef, RHS, RHSType, EndSz);1143  if (!IsCompAssign && LVecTy && LVecTy->getNumElements() > EndSz)1144    castVector<CK_HLSLVectorTruncation>(SemaRef, LHS, LHSType, EndSz);1145 1146  if (!RVecTy)1147    castVector<CK_VectorSplat>(SemaRef, RHS, RHSType, EndSz);1148  if (!IsCompAssign && !LVecTy)1149    castVector<CK_VectorSplat>(SemaRef, LHS, LHSType, EndSz);1150 1151  // If we're at the same type after resizing we can stop here.1152  if (Ctx.hasSameUnqualifiedType(LHSType, RHSType))1153    return Ctx.getCommonSugaredType(LHSType, RHSType);1154 1155  QualType LElTy = LHSType->castAs<VectorType>()->getElementType();1156  QualType RElTy = RHSType->castAs<VectorType>()->getElementType();1157 1158  // Handle conversion for floating point vectors.1159  if (LElTy->isRealFloatingType() || RElTy->isRealFloatingType())1160    return handleFloatVectorBinOpConversion(SemaRef, LHS, RHS, LHSType, RHSType,1161                                            LElTy, RElTy, IsCompAssign);1162 1163  assert(LElTy->isIntegralType(Ctx) && RElTy->isIntegralType(Ctx) &&1164         "HLSL Vectors can only contain integer or floating point types");1165  return handleIntegerVectorBinOpConversion(SemaRef, LHS, RHS, LHSType, RHSType,1166                                            LElTy, RElTy, IsCompAssign);1167}1168 1169void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS,1170                                        BinaryOperatorKind Opc) {1171  assert((Opc == BO_LOr || Opc == BO_LAnd) &&1172         "Called with non-logical operator");1173  llvm::SmallVector<char, 256> Buff;1174  llvm::raw_svector_ostream OS(Buff);1175  PrintingPolicy PP(SemaRef.getLangOpts());1176  StringRef NewFnName = Opc == BO_LOr ? "or" : "and";1177  OS << NewFnName << "(";1178  LHS->printPretty(OS, nullptr, PP);1179  OS << ", ";1180  RHS->printPretty(OS, nullptr, PP);1181  OS << ")";1182  SourceRange FullRange = SourceRange(LHS->getBeginLoc(), RHS->getEndLoc());1183  SemaRef.Diag(LHS->getBeginLoc(), diag::note_function_suggestion)1184      << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());1185}1186 1187std::pair<IdentifierInfo *, bool>1188SemaHLSL::ActOnStartRootSignatureDecl(StringRef Signature) {1189  llvm::hash_code Hash = llvm::hash_value(Signature);1190  std::string IdStr = "__hlsl_rootsig_decl_" + std::to_string(Hash);1191  IdentifierInfo *DeclIdent = &(getASTContext().Idents.get(IdStr));1192 1193  // Check if we have already found a decl of the same name.1194  LookupResult R(SemaRef, DeclIdent, SourceLocation(),1195                 Sema::LookupOrdinaryName);1196  bool Found = SemaRef.LookupQualifiedName(R, SemaRef.CurContext);1197  return {DeclIdent, Found};1198}1199 1200void SemaHLSL::ActOnFinishRootSignatureDecl(1201    SourceLocation Loc, IdentifierInfo *DeclIdent,1202    ArrayRef<hlsl::RootSignatureElement> RootElements) {1203 1204  if (handleRootSignatureElements(RootElements))1205    return;1206 1207  SmallVector<llvm::hlsl::rootsig::RootElement> Elements;1208  for (auto &RootSigElement : RootElements)1209    Elements.push_back(RootSigElement.getElement());1210 1211  auto *SignatureDecl = HLSLRootSignatureDecl::Create(1212      SemaRef.getASTContext(), /*DeclContext=*/SemaRef.CurContext, Loc,1213      DeclIdent, SemaRef.getLangOpts().HLSLRootSigVer, Elements);1214 1215  SignatureDecl->setImplicit();1216  SemaRef.PushOnScopeChains(SignatureDecl, SemaRef.getCurScope());1217}1218 1219HLSLRootSignatureDecl *1220SemaHLSL::lookupRootSignatureOverrideDecl(DeclContext *DC) const {1221  if (RootSigOverrideIdent) {1222    LookupResult R(SemaRef, RootSigOverrideIdent, SourceLocation(),1223                   Sema::LookupOrdinaryName);1224    if (SemaRef.LookupQualifiedName(R, DC))1225      return dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl());1226  }1227 1228  return nullptr;1229}1230 1231namespace {1232 1233struct PerVisibilityBindingChecker {1234  SemaHLSL *S;1235  // We need one builder per `llvm::dxbc::ShaderVisibility` value.1236  std::array<llvm::hlsl::BindingInfoBuilder, 8> Builders;1237 1238  struct ElemInfo {1239    const hlsl::RootSignatureElement *Elem;1240    llvm::dxbc::ShaderVisibility Vis;1241    bool Diagnosed;1242  };1243  llvm::SmallVector<ElemInfo> ElemInfoMap;1244 1245  PerVisibilityBindingChecker(SemaHLSL *S) : S(S) {}1246 1247  void trackBinding(llvm::dxbc::ShaderVisibility Visibility,1248                    llvm::dxil::ResourceClass RC, uint32_t Space,1249                    uint32_t LowerBound, uint32_t UpperBound,1250                    const hlsl::RootSignatureElement *Elem) {1251    uint32_t BuilderIndex = llvm::to_underlying(Visibility);1252    assert(BuilderIndex < Builders.size() &&1253           "Not enough builders for visibility type");1254    Builders[BuilderIndex].trackBinding(RC, Space, LowerBound, UpperBound,1255                                        static_cast<const void *>(Elem));1256 1257    static_assert(llvm::to_underlying(llvm::dxbc::ShaderVisibility::All) == 0,1258                  "'All' visibility must come first");1259    if (Visibility == llvm::dxbc::ShaderVisibility::All)1260      for (size_t I = 1, E = Builders.size(); I < E; ++I)1261        Builders[I].trackBinding(RC, Space, LowerBound, UpperBound,1262                                 static_cast<const void *>(Elem));1263 1264    ElemInfoMap.push_back({Elem, Visibility, false});1265  }1266 1267  ElemInfo &getInfo(const hlsl::RootSignatureElement *Elem) {1268    auto It = llvm::lower_bound(1269        ElemInfoMap, Elem,1270        [](const auto &LHS, const auto &RHS) { return LHS.Elem < RHS; });1271    assert(It->Elem == Elem && "Element not in map");1272    return *It;1273  }1274 1275  bool checkOverlap() {1276    llvm::sort(ElemInfoMap, [](const auto &LHS, const auto &RHS) {1277      return LHS.Elem < RHS.Elem;1278    });1279 1280    bool HadOverlap = false;1281 1282    using llvm::hlsl::BindingInfoBuilder;1283    auto ReportOverlap = [this,1284                          &HadOverlap](const BindingInfoBuilder &Builder,1285                                       const llvm::hlsl::Binding &Reported) {1286      HadOverlap = true;1287 1288      const auto *Elem =1289          static_cast<const hlsl::RootSignatureElement *>(Reported.Cookie);1290      const llvm::hlsl::Binding &Previous = Builder.findOverlapping(Reported);1291      const auto *PrevElem =1292          static_cast<const hlsl::RootSignatureElement *>(Previous.Cookie);1293 1294      ElemInfo &Info = getInfo(Elem);1295      // We will have already diagnosed this binding if there's overlap in the1296      // "All" visibility as well as any particular visibility.1297      if (Info.Diagnosed)1298        return;1299      Info.Diagnosed = true;1300 1301      ElemInfo &PrevInfo = getInfo(PrevElem);1302      llvm::dxbc::ShaderVisibility CommonVis =1303          Info.Vis == llvm::dxbc::ShaderVisibility::All ? PrevInfo.Vis1304                                                        : Info.Vis;1305 1306      this->S->Diag(Elem->getLocation(), diag::err_hlsl_resource_range_overlap)1307          << llvm::to_underlying(Reported.RC) << Reported.LowerBound1308          << Reported.isUnbounded() << Reported.UpperBound1309          << llvm::to_underlying(Previous.RC) << Previous.LowerBound1310          << Previous.isUnbounded() << Previous.UpperBound << Reported.Space1311          << CommonVis;1312 1313      this->S->Diag(PrevElem->getLocation(),1314                    diag::note_hlsl_resource_range_here);1315    };1316 1317    for (BindingInfoBuilder &Builder : Builders)1318      Builder.calculateBindingInfo(ReportOverlap);1319 1320    return HadOverlap;1321  }1322};1323 1324static CXXMethodDecl *lookupMethod(Sema &S, CXXRecordDecl *RecordDecl,1325                                   StringRef Name, SourceLocation Loc) {1326  DeclarationName DeclName(&S.getASTContext().Idents.get(Name));1327  LookupResult Result(S, DeclName, Loc, Sema::LookupMemberName);1328  if (!S.LookupQualifiedName(Result, static_cast<DeclContext *>(RecordDecl)))1329    return nullptr;1330  return cast<CXXMethodDecl>(Result.getFoundDecl());1331}1332 1333} // end anonymous namespace1334 1335static bool hasCounterHandle(const CXXRecordDecl *RD) {1336  if (RD->field_empty())1337    return false;1338  auto It = std::next(RD->field_begin());1339  if (It == RD->field_end())1340    return false;1341  const FieldDecl *SecondField = *It;1342  if (const auto *ResTy =1343          SecondField->getType()->getAs<HLSLAttributedResourceType>()) {1344    return ResTy->getAttrs().IsCounter;1345  }1346  return false;1347}1348 1349bool SemaHLSL::handleRootSignatureElements(1350    ArrayRef<hlsl::RootSignatureElement> Elements) {1351  // Define some common error handling functions1352  bool HadError = false;1353  auto ReportError = [this, &HadError](SourceLocation Loc, uint32_t LowerBound,1354                                       uint32_t UpperBound) {1355    HadError = true;1356    this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)1357        << LowerBound << UpperBound;1358  };1359 1360  auto ReportFloatError = [this, &HadError](SourceLocation Loc,1361                                            float LowerBound,1362                                            float UpperBound) {1363    HadError = true;1364    this->Diag(Loc, diag::err_hlsl_invalid_rootsig_value)1365        << llvm::formatv("{0:f}", LowerBound).sstr<6>()1366        << llvm::formatv("{0:f}", UpperBound).sstr<6>();1367  };1368 1369  auto VerifyRegister = [ReportError](SourceLocation Loc, uint32_t Register) {1370    if (!llvm::hlsl::rootsig::verifyRegisterValue(Register))1371      ReportError(Loc, 0, 0xfffffffe);1372  };1373 1374  auto VerifySpace = [ReportError](SourceLocation Loc, uint32_t Space) {1375    if (!llvm::hlsl::rootsig::verifyRegisterSpace(Space))1376      ReportError(Loc, 0, 0xffffffef);1377  };1378 1379  const uint32_t Version =1380      llvm::to_underlying(SemaRef.getLangOpts().HLSLRootSigVer);1381  const uint32_t VersionEnum = Version - 1;1382  auto ReportFlagError = [this, &HadError, VersionEnum](SourceLocation Loc) {1383    HadError = true;1384    this->Diag(Loc, diag::err_hlsl_invalid_rootsig_flag)1385        << /*version minor*/ VersionEnum;1386  };1387 1388  // Iterate through the elements and do basic validations1389  for (const hlsl::RootSignatureElement &RootSigElem : Elements) {1390    SourceLocation Loc = RootSigElem.getLocation();1391    const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();1392    if (const auto *Descriptor =1393            std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {1394      VerifyRegister(Loc, Descriptor->Reg.Number);1395      VerifySpace(Loc, Descriptor->Space);1396 1397      if (!llvm::hlsl::rootsig::verifyRootDescriptorFlag(Version,1398                                                         Descriptor->Flags))1399        ReportFlagError(Loc);1400    } else if (const auto *Constants =1401                   std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {1402      VerifyRegister(Loc, Constants->Reg.Number);1403      VerifySpace(Loc, Constants->Space);1404    } else if (const auto *Sampler =1405                   std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {1406      VerifyRegister(Loc, Sampler->Reg.Number);1407      VerifySpace(Loc, Sampler->Space);1408 1409      assert(!std::isnan(Sampler->MaxLOD) && !std::isnan(Sampler->MinLOD) &&1410             "By construction, parseFloatParam can't produce a NaN from a "1411             "float_literal token");1412 1413      if (!llvm::hlsl::rootsig::verifyMaxAnisotropy(Sampler->MaxAnisotropy))1414        ReportError(Loc, 0, 16);1415      if (!llvm::hlsl::rootsig::verifyMipLODBias(Sampler->MipLODBias))1416        ReportFloatError(Loc, -16.f, 15.99f);1417    } else if (const auto *Clause =1418                   std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(1419                       &Elem)) {1420      VerifyRegister(Loc, Clause->Reg.Number);1421      VerifySpace(Loc, Clause->Space);1422 1423      if (!llvm::hlsl::rootsig::verifyNumDescriptors(Clause->NumDescriptors)) {1424        // NumDescriptor could techincally be ~0u but that is reserved for1425        // unbounded, so the diagnostic will not report that as a valid int1426        // value1427        ReportError(Loc, 1, 0xfffffffe);1428      }1429 1430      if (!llvm::hlsl::rootsig::verifyDescriptorRangeFlag(Version, Clause->Type,1431                                                          Clause->Flags))1432        ReportFlagError(Loc);1433    }1434  }1435 1436  PerVisibilityBindingChecker BindingChecker(this);1437  SmallVector<std::pair<const llvm::hlsl::rootsig::DescriptorTableClause *,1438                        const hlsl::RootSignatureElement *>>1439      UnboundClauses;1440 1441  for (const hlsl::RootSignatureElement &RootSigElem : Elements) {1442    const llvm::hlsl::rootsig::RootElement &Elem = RootSigElem.getElement();1443    if (const auto *Descriptor =1444            std::get_if<llvm::hlsl::rootsig::RootDescriptor>(&Elem)) {1445      uint32_t LowerBound(Descriptor->Reg.Number);1446      uint32_t UpperBound(LowerBound); // inclusive range1447 1448      BindingChecker.trackBinding(1449          Descriptor->Visibility,1450          static_cast<llvm::dxil::ResourceClass>(Descriptor->Type),1451          Descriptor->Space, LowerBound, UpperBound, &RootSigElem);1452    } else if (const auto *Constants =1453                   std::get_if<llvm::hlsl::rootsig::RootConstants>(&Elem)) {1454      uint32_t LowerBound(Constants->Reg.Number);1455      uint32_t UpperBound(LowerBound); // inclusive range1456 1457      BindingChecker.trackBinding(1458          Constants->Visibility, llvm::dxil::ResourceClass::CBuffer,1459          Constants->Space, LowerBound, UpperBound, &RootSigElem);1460    } else if (const auto *Sampler =1461                   std::get_if<llvm::hlsl::rootsig::StaticSampler>(&Elem)) {1462      uint32_t LowerBound(Sampler->Reg.Number);1463      uint32_t UpperBound(LowerBound); // inclusive range1464 1465      BindingChecker.trackBinding(1466          Sampler->Visibility, llvm::dxil::ResourceClass::Sampler,1467          Sampler->Space, LowerBound, UpperBound, &RootSigElem);1468    } else if (const auto *Clause =1469                   std::get_if<llvm::hlsl::rootsig::DescriptorTableClause>(1470                       &Elem)) {1471      // We'll process these once we see the table element.1472      UnboundClauses.emplace_back(Clause, &RootSigElem);1473    } else if (const auto *Table =1474                   std::get_if<llvm::hlsl::rootsig::DescriptorTable>(&Elem)) {1475      assert(UnboundClauses.size() == Table->NumClauses &&1476             "Number of unbound elements must match the number of clauses");1477      bool HasAnySampler = false;1478      bool HasAnyNonSampler = false;1479      uint64_t Offset = 0;1480      bool IsPrevUnbound = false;1481      for (const auto &[Clause, ClauseElem] : UnboundClauses) {1482        SourceLocation Loc = ClauseElem->getLocation();1483        if (Clause->Type == llvm::dxil::ResourceClass::Sampler)1484          HasAnySampler = true;1485        else1486          HasAnyNonSampler = true;1487 1488        if (HasAnySampler && HasAnyNonSampler)1489          Diag(Loc, diag::err_hlsl_invalid_mixed_resources);1490 1491        // Relevant error will have already been reported above and needs to be1492        // fixed before we can conduct further analysis, so shortcut error1493        // return1494        if (Clause->NumDescriptors == 0)1495          return true;1496 1497        bool IsAppending =1498            Clause->Offset == llvm::hlsl::rootsig::DescriptorTableOffsetAppend;1499        if (!IsAppending)1500          Offset = Clause->Offset;1501 1502        uint64_t RangeBound = llvm::hlsl::rootsig::computeRangeBound(1503            Offset, Clause->NumDescriptors);1504 1505        if (IsPrevUnbound && IsAppending)1506          Diag(Loc, diag::err_hlsl_appending_onto_unbound);1507        else if (!llvm::hlsl::rootsig::verifyNoOverflowedOffset(RangeBound))1508          Diag(Loc, diag::err_hlsl_offset_overflow) << Offset << RangeBound;1509 1510        // Update offset to be 1 past this range's bound1511        Offset = RangeBound + 1;1512        IsPrevUnbound = Clause->NumDescriptors ==1513                        llvm::hlsl::rootsig::NumDescriptorsUnbounded;1514 1515        // Compute the register bounds and track resource binding1516        uint32_t LowerBound(Clause->Reg.Number);1517        uint32_t UpperBound = llvm::hlsl::rootsig::computeRangeBound(1518            LowerBound, Clause->NumDescriptors);1519 1520        BindingChecker.trackBinding(1521            Table->Visibility,1522            static_cast<llvm::dxil::ResourceClass>(Clause->Type), Clause->Space,1523            LowerBound, UpperBound, ClauseElem);1524      }1525      UnboundClauses.clear();1526    }1527  }1528 1529  return BindingChecker.checkOverlap();1530}1531 1532void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {1533  if (AL.getNumArgs() != 1) {1534    Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;1535    return;1536  }1537 1538  IdentifierInfo *Ident = AL.getArgAsIdent(0)->getIdentifierInfo();1539  if (auto *RS = D->getAttr<RootSignatureAttr>()) {1540    if (RS->getSignatureIdent() != Ident) {1541      Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << RS;1542      return;1543    }1544 1545    Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << RS;1546    return;1547  }1548 1549  LookupResult R(SemaRef, Ident, SourceLocation(), Sema::LookupOrdinaryName);1550  if (SemaRef.LookupQualifiedName(R, D->getDeclContext()))1551    if (auto *SignatureDecl =1552            dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {1553      D->addAttr(::new (getASTContext()) RootSignatureAttr(1554          getASTContext(), AL, Ident, SignatureDecl));1555    }1556}1557 1558void SemaHLSL::handleNumThreadsAttr(Decl *D, const ParsedAttr &AL) {1559  llvm::VersionTuple SMVersion =1560      getASTContext().getTargetInfo().getTriple().getOSVersion();1561  bool IsDXIL = getASTContext().getTargetInfo().getTriple().getArch() ==1562                llvm::Triple::dxil;1563 1564  uint32_t ZMax = 1024;1565  uint32_t ThreadMax = 1024;1566  if (IsDXIL && SMVersion.getMajor() <= 4) {1567    ZMax = 1;1568    ThreadMax = 768;1569  } else if (IsDXIL && SMVersion.getMajor() == 5) {1570    ZMax = 64;1571    ThreadMax = 1024;1572  }1573 1574  uint32_t X;1575  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), X))1576    return;1577  if (X > 1024) {1578    Diag(AL.getArgAsExpr(0)->getExprLoc(),1579         diag::err_hlsl_numthreads_argument_oor)1580        << 0 << 1024;1581    return;1582  }1583  uint32_t Y;1584  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Y))1585    return;1586  if (Y > 1024) {1587    Diag(AL.getArgAsExpr(1)->getExprLoc(),1588         diag::err_hlsl_numthreads_argument_oor)1589        << 1 << 1024;1590    return;1591  }1592  uint32_t Z;1593  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(2), Z))1594    return;1595  if (Z > ZMax) {1596    SemaRef.Diag(AL.getArgAsExpr(2)->getExprLoc(),1597                 diag::err_hlsl_numthreads_argument_oor)1598        << 2 << ZMax;1599    return;1600  }1601 1602  if (X * Y * Z > ThreadMax) {1603    Diag(AL.getLoc(), diag::err_hlsl_numthreads_invalid) << ThreadMax;1604    return;1605  }1606 1607  HLSLNumThreadsAttr *NewAttr = mergeNumThreadsAttr(D, AL, X, Y, Z);1608  if (NewAttr)1609    D->addAttr(NewAttr);1610}1611 1612static bool isValidWaveSizeValue(unsigned Value) {1613  return llvm::isPowerOf2_32(Value) && Value >= 4 && Value <= 128;1614}1615 1616void SemaHLSL::handleWaveSizeAttr(Decl *D, const ParsedAttr &AL) {1617  // validate that the wavesize argument is a power of 2 between 4 and 1281618  // inclusive1619  unsigned SpelledArgsCount = AL.getNumArgs();1620  if (SpelledArgsCount == 0 || SpelledArgsCount > 3)1621    return;1622 1623  uint32_t Min;1624  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Min))1625    return;1626 1627  uint32_t Max = 0;1628  if (SpelledArgsCount > 1 &&1629      !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Max))1630    return;1631 1632  uint32_t Preferred = 0;1633  if (SpelledArgsCount > 2 &&1634      !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(2), Preferred))1635    return;1636 1637  if (SpelledArgsCount > 2) {1638    if (!isValidWaveSizeValue(Preferred)) {1639      Diag(AL.getArgAsExpr(2)->getExprLoc(),1640           diag::err_attribute_power_of_two_in_range)1641          << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize1642          << Preferred;1643      return;1644    }1645    // Preferred not in range.1646    if (Preferred < Min || Preferred > Max) {1647      Diag(AL.getArgAsExpr(2)->getExprLoc(),1648           diag::err_attribute_power_of_two_in_range)1649          << AL << Min << Max << Preferred;1650      return;1651    }1652  } else if (SpelledArgsCount > 1) {1653    if (!isValidWaveSizeValue(Max)) {1654      Diag(AL.getArgAsExpr(1)->getExprLoc(),1655           diag::err_attribute_power_of_two_in_range)1656          << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Max;1657      return;1658    }1659    if (Max < Min) {1660      Diag(AL.getLoc(), diag::err_attribute_argument_invalid) << AL << 1;1661      return;1662    } else if (Max == Min) {1663      Diag(AL.getLoc(), diag::warn_attr_min_eq_max) << AL;1664    }1665  } else {1666    if (!isValidWaveSizeValue(Min)) {1667      Diag(AL.getArgAsExpr(0)->getExprLoc(),1668           diag::err_attribute_power_of_two_in_range)1669          << AL << llvm::dxil::MinWaveSize << llvm::dxil::MaxWaveSize << Min;1670      return;1671    }1672  }1673 1674  HLSLWaveSizeAttr *NewAttr =1675      mergeWaveSizeAttr(D, AL, Min, Max, Preferred, SpelledArgsCount);1676  if (NewAttr)1677    D->addAttr(NewAttr);1678}1679 1680void SemaHLSL::handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL) {1681  uint32_t ID;1682  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), ID))1683    return;1684  D->addAttr(::new (getASTContext())1685                 HLSLVkExtBuiltinInputAttr(getASTContext(), AL, ID));1686}1687 1688void SemaHLSL::handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL) {1689  uint32_t Id;1690  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Id))1691    return;1692  HLSLVkConstantIdAttr *NewAttr = mergeVkConstantIdAttr(D, AL, Id);1693  if (NewAttr)1694    D->addAttr(NewAttr);1695}1696 1697void SemaHLSL::handleVkBindingAttr(Decl *D, const ParsedAttr &AL) {1698  uint32_t Binding = 0;1699  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Binding))1700    return;1701  uint32_t Set = 0;1702  if (AL.getNumArgs() > 1 &&1703      !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Set))1704    return;1705 1706  D->addAttr(::new (getASTContext())1707                 HLSLVkBindingAttr(getASTContext(), AL, Binding, Set));1708}1709 1710bool SemaHLSL::diagnoseInputIDType(QualType T, const ParsedAttr &AL) {1711  const auto *VT = T->getAs<VectorType>();1712 1713  if (!T->hasUnsignedIntegerRepresentation() ||1714      (VT && VT->getNumElements() > 3)) {1715    Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)1716        << AL << "uint/uint2/uint3";1717    return false;1718  }1719 1720  return true;1721}1722 1723bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) {1724  const auto *VT = T->getAs<VectorType>();1725  if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) {1726    Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)1727        << AL << "float/float1/float2/float3/float4";1728    return false;1729  }1730 1731  return true;1732}1733 1734void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,1735                                          std::optional<unsigned> Index) {1736  std::string SemanticName = AL.getAttrName()->getName().upper();1737 1738  auto *VD = cast<ValueDecl>(D);1739  QualType ValueType = VD->getType();1740  if (auto *FD = dyn_cast<FunctionDecl>(D))1741    ValueType = FD->getReturnType();1742 1743  bool IsOutput = false;1744  if (HLSLParamModifierAttr *MA = D->getAttr<HLSLParamModifierAttr>()) {1745    if (MA->isOut()) {1746      IsOutput = true;1747      ValueType = cast<ReferenceType>(ValueType)->getPointeeType();1748    }1749  }1750 1751  if (SemanticName == "SV_DISPATCHTHREADID") {1752    diagnoseInputIDType(ValueType, AL);1753    if (IsOutput)1754      Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;1755    if (Index.has_value())1756      Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;1757    D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));1758    return;1759  }1760 1761  if (SemanticName == "SV_GROUPINDEX") {1762    if (IsOutput)1763      Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;1764    if (Index.has_value())1765      Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;1766    D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));1767    return;1768  }1769 1770  if (SemanticName == "SV_GROUPTHREADID") {1771    diagnoseInputIDType(ValueType, AL);1772    if (IsOutput)1773      Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;1774    if (Index.has_value())1775      Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;1776    D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));1777    return;1778  }1779 1780  if (SemanticName == "SV_GROUPID") {1781    diagnoseInputIDType(ValueType, AL);1782    if (IsOutput)1783      Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL;1784    if (Index.has_value())1785      Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL;1786    D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));1787    return;1788  }1789 1790  if (SemanticName == "SV_POSITION") {1791    const auto *VT = ValueType->getAs<VectorType>();1792    if (!ValueType->hasFloatingRepresentation() ||1793        (VT && VT->getNumElements() > 4))1794      Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type)1795          << AL << "float/float1/float2/float3/float4";1796    D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));1797    return;1798  }1799 1800  Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL;1801}1802 1803void SemaHLSL::handleSemanticAttr(Decl *D, const ParsedAttr &AL) {1804  uint32_t IndexValue, ExplicitIndex;1805  SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), IndexValue);1806  SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), ExplicitIndex);1807  assert(IndexValue > 0 ? ExplicitIndex : true);1808  std::optional<unsigned> Index =1809      ExplicitIndex ? std::optional<unsigned>(IndexValue) : std::nullopt;1810 1811  if (AL.getAttrName()->getName().starts_with_insensitive("SV_"))1812    diagnoseSystemSemanticAttr(D, AL, Index);1813  else1814    D->addAttr(createSemanticAttr<HLSLParsedSemanticAttr>(AL, Index));1815}1816 1817void SemaHLSL::handlePackOffsetAttr(Decl *D, const ParsedAttr &AL) {1818  if (!isa<VarDecl>(D) || !isa<HLSLBufferDecl>(D->getDeclContext())) {1819    Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_ast_node)1820        << AL << "shader constant in a constant buffer";1821    return;1822  }1823 1824  uint32_t SubComponent;1825  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), SubComponent))1826    return;1827  uint32_t Component;1828  if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Component))1829    return;1830 1831  QualType T = cast<VarDecl>(D)->getType().getCanonicalType();1832  // Check if T is an array or struct type.1833  // TODO: mark matrix type as aggregate type.1834  bool IsAggregateTy = (T->isArrayType() || T->isStructureType());1835 1836  // Check Component is valid for T.1837  if (Component) {1838    unsigned Size = getASTContext().getTypeSize(T);1839    if (IsAggregateTy || Size > 128) {1840      Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);1841      return;1842    } else {1843      // Make sure Component + sizeof(T) <= 4.1844      if ((Component * 32 + Size) > 128) {1845        Diag(AL.getLoc(), diag::err_hlsl_packoffset_cross_reg_boundary);1846        return;1847      }1848      QualType EltTy = T;1849      if (const auto *VT = T->getAs<VectorType>())1850        EltTy = VT->getElementType();1851      unsigned Align = getASTContext().getTypeAlign(EltTy);1852      if (Align > 32 && Component == 1) {1853        // NOTE: Component 3 will hit err_hlsl_packoffset_cross_reg_boundary.1854        // So we only need to check Component 1 here.1855        Diag(AL.getLoc(), diag::err_hlsl_packoffset_alignment_mismatch)1856            << Align << EltTy;1857        return;1858      }1859    }1860  }1861 1862  D->addAttr(::new (getASTContext()) HLSLPackOffsetAttr(1863      getASTContext(), AL, SubComponent, Component));1864}1865 1866void SemaHLSL::handleShaderAttr(Decl *D, const ParsedAttr &AL) {1867  StringRef Str;1868  SourceLocation ArgLoc;1869  if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))1870    return;1871 1872  llvm::Triple::EnvironmentType ShaderType;1873  if (!HLSLShaderAttr::ConvertStrToEnvironmentType(Str, ShaderType)) {1874    Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)1875        << AL << Str << ArgLoc;1876    return;1877  }1878 1879  // FIXME: check function match the shader stage.1880 1881  HLSLShaderAttr *NewAttr = mergeShaderAttr(D, AL, ShaderType);1882  if (NewAttr)1883    D->addAttr(NewAttr);1884}1885 1886bool clang::CreateHLSLAttributedResourceType(1887    Sema &S, QualType Wrapped, ArrayRef<const Attr *> AttrList,1888    QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo) {1889  assert(AttrList.size() && "expected list of resource attributes");1890 1891  QualType ContainedTy = QualType();1892  TypeSourceInfo *ContainedTyInfo = nullptr;1893  SourceLocation LocBegin = AttrList[0]->getRange().getBegin();1894  SourceLocation LocEnd = AttrList[0]->getRange().getEnd();1895 1896  HLSLAttributedResourceType::Attributes ResAttrs;1897 1898  bool HasResourceClass = false;1899  for (const Attr *A : AttrList) {1900    if (!A)1901      continue;1902    LocEnd = A->getRange().getEnd();1903    switch (A->getKind()) {1904    case attr::HLSLResourceClass: {1905      ResourceClass RC = cast<HLSLResourceClassAttr>(A)->getResourceClass();1906      if (HasResourceClass) {1907        S.Diag(A->getLocation(), ResAttrs.ResourceClass == RC1908                                     ? diag::warn_duplicate_attribute_exact1909                                     : diag::warn_duplicate_attribute)1910            << A;1911        return false;1912      }1913      ResAttrs.ResourceClass = RC;1914      HasResourceClass = true;1915      break;1916    }1917    case attr::HLSLROV:1918      if (ResAttrs.IsROV) {1919        S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;1920        return false;1921      }1922      ResAttrs.IsROV = true;1923      break;1924    case attr::HLSLRawBuffer:1925      if (ResAttrs.RawBuffer) {1926        S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;1927        return false;1928      }1929      ResAttrs.RawBuffer = true;1930      break;1931    case attr::HLSLIsCounter:1932      if (ResAttrs.IsCounter) {1933        S.Diag(A->getLocation(), diag::warn_duplicate_attribute_exact) << A;1934        return false;1935      }1936      ResAttrs.IsCounter = true;1937      break;1938    case attr::HLSLContainedType: {1939      const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);1940      QualType Ty = CTAttr->getType();1941      if (!ContainedTy.isNull()) {1942        S.Diag(A->getLocation(), ContainedTy == Ty1943                                     ? diag::warn_duplicate_attribute_exact1944                                     : diag::warn_duplicate_attribute)1945            << A;1946        return false;1947      }1948      ContainedTy = Ty;1949      ContainedTyInfo = CTAttr->getTypeLoc();1950      break;1951    }1952    default:1953      llvm_unreachable("unhandled resource attribute type");1954    }1955  }1956 1957  if (!HasResourceClass) {1958    S.Diag(AttrList.back()->getRange().getEnd(),1959           diag::err_hlsl_missing_resource_class);1960    return false;1961  }1962 1963  ResType = S.getASTContext().getHLSLAttributedResourceType(1964      Wrapped, ContainedTy, ResAttrs);1965 1966  if (LocInfo && ContainedTyInfo) {1967    LocInfo->Range = SourceRange(LocBegin, LocEnd);1968    LocInfo->ContainedTyInfo = ContainedTyInfo;1969  }1970  return true;1971}1972 1973// Validates and creates an HLSL attribute that is applied as type attribute on1974// HLSL resource. The attributes are collected in HLSLResourcesTypeAttrs and at1975// the end of the declaration they are applied to the declaration type by1976// wrapping it in HLSLAttributedResourceType.1977bool SemaHLSL::handleResourceTypeAttr(QualType T, const ParsedAttr &AL) {1978  // only allow resource type attributes on intangible types1979  if (!T->isHLSLResourceType()) {1980    Diag(AL.getLoc(), diag::err_hlsl_attribute_needs_intangible_type)1981        << AL << getASTContext().HLSLResourceTy;1982    return false;1983  }1984 1985  // validate number of arguments1986  if (!AL.checkExactlyNumArgs(SemaRef, AL.getMinArgs()))1987    return false;1988 1989  Attr *A = nullptr;1990 1991  AttributeCommonInfo ACI(1992      AL.getLoc(), AttributeScopeInfo(AL.getScopeName(), AL.getScopeLoc()),1993      AttributeCommonInfo::NoSemaHandlerAttribute,1994      {1995          AttributeCommonInfo::AS_CXX11, 0, false /*IsAlignas*/,1996          false /*IsRegularKeywordAttribute*/1997      });1998 1999  switch (AL.getKind()) {2000  case ParsedAttr::AT_HLSLResourceClass: {2001    if (!AL.isArgIdent(0)) {2002      Diag(AL.getLoc(), diag::err_attribute_argument_type)2003          << AL << AANT_ArgumentIdentifier;2004      return false;2005    }2006 2007    IdentifierLoc *Loc = AL.getArgAsIdent(0);2008    StringRef Identifier = Loc->getIdentifierInfo()->getName();2009    SourceLocation ArgLoc = Loc->getLoc();2010 2011    // Validate resource class value2012    ResourceClass RC;2013    if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {2014      Diag(ArgLoc, diag::warn_attribute_type_not_supported)2015          << "ResourceClass" << Identifier;2016      return false;2017    }2018    A = HLSLResourceClassAttr::Create(getASTContext(), RC, ACI);2019    break;2020  }2021 2022  case ParsedAttr::AT_HLSLROV:2023    A = HLSLROVAttr::Create(getASTContext(), ACI);2024    break;2025 2026  case ParsedAttr::AT_HLSLRawBuffer:2027    A = HLSLRawBufferAttr::Create(getASTContext(), ACI);2028    break;2029 2030  case ParsedAttr::AT_HLSLIsCounter:2031    A = HLSLIsCounterAttr::Create(getASTContext(), ACI);2032    break;2033 2034  case ParsedAttr::AT_HLSLContainedType: {2035    if (AL.getNumArgs() != 1 && !AL.hasParsedType()) {2036      Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;2037      return false;2038    }2039 2040    TypeSourceInfo *TSI = nullptr;2041    QualType QT = SemaRef.GetTypeFromParser(AL.getTypeArg(), &TSI);2042    assert(TSI && "no type source info for attribute argument");2043    if (SemaRef.RequireCompleteType(TSI->getTypeLoc().getBeginLoc(), QT,2044                                    diag::err_incomplete_type))2045      return false;2046    A = HLSLContainedTypeAttr::Create(getASTContext(), TSI, ACI);2047    break;2048  }2049 2050  default:2051    llvm_unreachable("unhandled HLSL attribute");2052  }2053 2054  HLSLResourcesTypeAttrs.emplace_back(A);2055  return true;2056}2057 2058// Combines all resource type attributes and creates HLSLAttributedResourceType.2059QualType SemaHLSL::ProcessResourceTypeAttributes(QualType CurrentType) {2060  if (!HLSLResourcesTypeAttrs.size())2061    return CurrentType;2062 2063  QualType QT = CurrentType;2064  HLSLAttributedResourceLocInfo LocInfo;2065  if (CreateHLSLAttributedResourceType(SemaRef, CurrentType,2066                                       HLSLResourcesTypeAttrs, QT, &LocInfo)) {2067    const HLSLAttributedResourceType *RT =2068        cast<HLSLAttributedResourceType>(QT.getTypePtr());2069 2070    // Temporarily store TypeLoc information for the new type.2071    // It will be transferred to HLSLAttributesResourceTypeLoc2072    // shortly after the type is created by TypeSpecLocFiller which2073    // will call the TakeLocForHLSLAttribute method below.2074    LocsForHLSLAttributedResources.insert(std::pair(RT, LocInfo));2075  }2076  HLSLResourcesTypeAttrs.clear();2077  return QT;2078}2079 2080// Returns source location for the HLSLAttributedResourceType2081HLSLAttributedResourceLocInfo2082SemaHLSL::TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT) {2083  HLSLAttributedResourceLocInfo LocInfo = {};2084  auto I = LocsForHLSLAttributedResources.find(RT);2085  if (I != LocsForHLSLAttributedResources.end()) {2086    LocInfo = I->second;2087    LocsForHLSLAttributedResources.erase(I);2088    return LocInfo;2089  }2090  LocInfo.Range = SourceRange();2091  return LocInfo;2092}2093 2094// Walks though the global variable declaration, collects all resource binding2095// requirements and adds them to Bindings2096void SemaHLSL::collectResourceBindingsOnUserRecordDecl(const VarDecl *VD,2097                                                       const RecordType *RT) {2098  const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();2099  for (FieldDecl *FD : RD->fields()) {2100    const Type *Ty = FD->getType()->getUnqualifiedDesugaredType();2101 2102    // Unwrap arrays2103    // FIXME: Calculate array size while unwrapping2104    assert(!Ty->isIncompleteArrayType() &&2105           "incomplete arrays inside user defined types are not supported");2106    while (Ty->isConstantArrayType()) {2107      const ConstantArrayType *CAT = cast<ConstantArrayType>(Ty);2108      Ty = CAT->getElementType()->getUnqualifiedDesugaredType();2109    }2110 2111    if (!Ty->isRecordType())2112      continue;2113 2114    if (const HLSLAttributedResourceType *AttrResType =2115            HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {2116      // Add a new DeclBindingInfo to Bindings if it does not already exist2117      ResourceClass RC = AttrResType->getAttrs().ResourceClass;2118      DeclBindingInfo *DBI = Bindings.getDeclBindingInfo(VD, RC);2119      if (!DBI)2120        Bindings.addDeclBindingInfo(VD, RC);2121    } else if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {2122      // Recursively scan embedded struct or class; it would be nice to do this2123      // without recursion, but tricky to correctly calculate the size of the2124      // binding, which is something we are probably going to need to do later2125      // on. Hopefully nesting of structs in structs too many levels is2126      // unlikely.2127      collectResourceBindingsOnUserRecordDecl(VD, RT);2128    }2129  }2130}2131 2132// Diagnose localized register binding errors for a single binding; does not2133// diagnose resource binding on user record types, that will be done later2134// in processResourceBindingOnDecl based on the information collected in2135// collectResourceBindingsOnVarDecl.2136// Returns false if the register binding is not valid.2137static bool DiagnoseLocalRegisterBinding(Sema &S, SourceLocation &ArgLoc,2138                                         Decl *D, RegisterType RegType,2139                                         bool SpecifiedSpace) {2140  int RegTypeNum = static_cast<int>(RegType);2141 2142  // check if the decl type is groupshared2143  if (D->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) {2144    S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;2145    return false;2146  }2147 2148  // Cbuffers and Tbuffers are HLSLBufferDecl types2149  if (HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D)) {2150    ResourceClass RC = CBufferOrTBuffer->isCBuffer() ? ResourceClass::CBuffer2151                                                     : ResourceClass::SRV;2152    if (RegType == getRegisterType(RC))2153      return true;2154 2155    S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)2156        << RegTypeNum;2157    return false;2158  }2159 2160  // Samplers, UAVs, and SRVs are VarDecl types2161  assert(isa<VarDecl>(D) && "D is expected to be VarDecl or HLSLBufferDecl");2162  VarDecl *VD = cast<VarDecl>(D);2163 2164  // Resource2165  if (const HLSLAttributedResourceType *AttrResType =2166          HLSLAttributedResourceType::findHandleTypeOnResource(2167              VD->getType().getTypePtr())) {2168    if (RegType == getRegisterType(AttrResType))2169      return true;2170 2171    S.Diag(D->getLocation(), diag::err_hlsl_binding_type_mismatch)2172        << RegTypeNum;2173    return false;2174  }2175 2176  const clang::Type *Ty = VD->getType().getTypePtr();2177  while (Ty->isArrayType())2178    Ty = Ty->getArrayElementTypeNoTypeQual();2179 2180  // Basic types2181  if (Ty->isArithmeticType() || Ty->isVectorType()) {2182    bool DeclaredInCOrTBuffer = isa<HLSLBufferDecl>(D->getDeclContext());2183    if (SpecifiedSpace && !DeclaredInCOrTBuffer)2184      S.Diag(ArgLoc, diag::err_hlsl_space_on_global_constant);2185 2186    if (!DeclaredInCOrTBuffer && (Ty->isIntegralType(S.getASTContext()) ||2187                                  Ty->isFloatingType() || Ty->isVectorType())) {2188      // Register annotation on default constant buffer declaration ($Globals)2189      if (RegType == RegisterType::CBuffer)2190        S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b);2191      else if (RegType != RegisterType::C)2192        S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;2193      else2194        return true;2195    } else {2196      if (RegType == RegisterType::C)2197        S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_packoffset);2198      else2199        S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;2200    }2201    return false;2202  }2203  if (Ty->isRecordType())2204    // RecordTypes will be diagnosed in processResourceBindingOnDecl2205    // that is called from ActOnVariableDeclarator2206    return true;2207 2208  // Anything else is an error2209  S.Diag(ArgLoc, diag::err_hlsl_binding_type_mismatch) << RegTypeNum;2210  return false;2211}2212 2213static bool ValidateMultipleRegisterAnnotations(Sema &S, Decl *TheDecl,2214                                                RegisterType regType) {2215  // make sure that there are no two register annotations2216  // applied to the decl with the same register type2217  bool RegisterTypesDetected[5] = {false};2218  RegisterTypesDetected[static_cast<int>(regType)] = true;2219 2220  for (auto it = TheDecl->attr_begin(); it != TheDecl->attr_end(); ++it) {2221    if (HLSLResourceBindingAttr *attr =2222            dyn_cast<HLSLResourceBindingAttr>(*it)) {2223 2224      RegisterType otherRegType = attr->getRegisterType();2225      if (RegisterTypesDetected[static_cast<int>(otherRegType)]) {2226        int otherRegTypeNum = static_cast<int>(otherRegType);2227        S.Diag(TheDecl->getLocation(),2228               diag::err_hlsl_duplicate_register_annotation)2229            << otherRegTypeNum;2230        return false;2231      }2232      RegisterTypesDetected[static_cast<int>(otherRegType)] = true;2233    }2234  }2235  return true;2236}2237 2238static bool DiagnoseHLSLRegisterAttribute(Sema &S, SourceLocation &ArgLoc,2239                                          Decl *D, RegisterType RegType,2240                                          bool SpecifiedSpace) {2241 2242  // exactly one of these two types should be set2243  assert(((isa<VarDecl>(D) && !isa<HLSLBufferDecl>(D)) ||2244          (!isa<VarDecl>(D) && isa<HLSLBufferDecl>(D))) &&2245         "expecting VarDecl or HLSLBufferDecl");2246 2247  // check if the declaration contains resource matching the register type2248  if (!DiagnoseLocalRegisterBinding(S, ArgLoc, D, RegType, SpecifiedSpace))2249    return false;2250 2251  // next, if multiple register annotations exist, check that none conflict.2252  return ValidateMultipleRegisterAnnotations(S, D, RegType);2253}2254 2255void SemaHLSL::handleResourceBindingAttr(Decl *TheDecl, const ParsedAttr &AL) {2256  if (VarDecl *VD = dyn_cast<VarDecl>(TheDecl)) {2257    QualType Ty = VD->getType();2258    if (const auto *IAT = dyn_cast<IncompleteArrayType>(Ty))2259      Ty = IAT->getElementType();2260    if (SemaRef.RequireCompleteType(TheDecl->getBeginLoc(), Ty,2261                                    diag::err_incomplete_type))2262      return;2263  }2264 2265  StringRef Slot = "";2266  StringRef Space = "";2267  SourceLocation SlotLoc, SpaceLoc;2268 2269  if (!AL.isArgIdent(0)) {2270    Diag(AL.getLoc(), diag::err_attribute_argument_type)2271        << AL << AANT_ArgumentIdentifier;2272    return;2273  }2274  IdentifierLoc *Loc = AL.getArgAsIdent(0);2275 2276  if (AL.getNumArgs() == 2) {2277    Slot = Loc->getIdentifierInfo()->getName();2278    SlotLoc = Loc->getLoc();2279    if (!AL.isArgIdent(1)) {2280      Diag(AL.getLoc(), diag::err_attribute_argument_type)2281          << AL << AANT_ArgumentIdentifier;2282      return;2283    }2284    Loc = AL.getArgAsIdent(1);2285    Space = Loc->getIdentifierInfo()->getName();2286    SpaceLoc = Loc->getLoc();2287  } else {2288    StringRef Str = Loc->getIdentifierInfo()->getName();2289    if (Str.starts_with("space")) {2290      Space = Str;2291      SpaceLoc = Loc->getLoc();2292    } else {2293      Slot = Str;2294      SlotLoc = Loc->getLoc();2295      Space = "space0";2296    }2297  }2298 2299  RegisterType RegType = RegisterType::SRV;2300  std::optional<unsigned> SlotNum;2301  unsigned SpaceNum = 0;2302 2303  // Validate slot2304  if (!Slot.empty()) {2305    if (!convertToRegisterType(Slot, &RegType)) {2306      Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);2307      return;2308    }2309    if (RegType == RegisterType::I) {2310      Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);2311      return;2312    }2313    StringRef SlotNumStr = Slot.substr(1);2314    unsigned N;2315    if (SlotNumStr.getAsInteger(10, N)) {2316      Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);2317      return;2318    }2319    SlotNum = N;2320  }2321 2322  // Validate space2323  if (!Space.starts_with("space")) {2324    Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;2325    return;2326  }2327  StringRef SpaceNumStr = Space.substr(5);2328  if (SpaceNumStr.getAsInteger(10, SpaceNum)) {2329    Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;2330    return;2331  }2332 2333  // If we have slot, diagnose it is the right register type for the decl2334  if (SlotNum.has_value())2335    if (!DiagnoseHLSLRegisterAttribute(SemaRef, SlotLoc, TheDecl, RegType,2336                                       !SpaceLoc.isInvalid()))2337      return;2338 2339  HLSLResourceBindingAttr *NewAttr =2340      HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);2341  if (NewAttr) {2342    NewAttr->setBinding(RegType, SlotNum, SpaceNum);2343    TheDecl->addAttr(NewAttr);2344  }2345}2346 2347void SemaHLSL::handleParamModifierAttr(Decl *D, const ParsedAttr &AL) {2348  HLSLParamModifierAttr *NewAttr = mergeParamModifierAttr(2349      D, AL,2350      static_cast<HLSLParamModifierAttr::Spelling>(AL.getSemanticSpelling()));2351  if (NewAttr)2352    D->addAttr(NewAttr);2353}2354 2355namespace {2356 2357/// This class implements HLSL availability diagnostics for default2358/// and relaxed mode2359///2360/// The goal of this diagnostic is to emit an error or warning when an2361/// unavailable API is found in code that is reachable from the shader2362/// entry function or from an exported function (when compiling a shader2363/// library).2364///2365/// This is done by traversing the AST of all shader entry point functions2366/// and of all exported functions, and any functions that are referenced2367/// from this AST. In other words, any functions that are reachable from2368/// the entry points.2369class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor {2370  Sema &SemaRef;2371 2372  // Stack of functions to be scaned2373  llvm::SmallVector<const FunctionDecl *, 8> DeclsToScan;2374 2375  // Tracks which environments functions have been scanned in.2376  //2377  // Maps FunctionDecl to an unsigned number that represents the set of shader2378  // environments the function has been scanned for.2379  // The llvm::Triple::EnvironmentType enum values for shader stages guaranteed2380  // to be numbered from llvm::Triple::Pixel to llvm::Triple::Amplification2381  // (verified by static_asserts in Triple.cpp), we can use it to index2382  // individual bits in the set, as long as we shift the values to start with 02383  // by subtracting the value of llvm::Triple::Pixel first.2384  //2385  // The N'th bit in the set will be set if the function has been scanned2386  // in shader environment whose llvm::Triple::EnvironmentType integer value2387  // equals (llvm::Triple::Pixel + N).2388  //2389  // For example, if a function has been scanned in compute and pixel stage2390  // environment, the value will be 0x21 (100001 binary) because:2391  //2392  //   (int)(llvm::Triple::Pixel - llvm::Triple::Pixel) == 02393  //   (int)(llvm::Triple::Compute - llvm::Triple::Pixel) == 52394  //2395  // A FunctionDecl is mapped to 0 (or not included in the map) if it has not2396  // been scanned in any environment.2397  llvm::DenseMap<const FunctionDecl *, unsigned> ScannedDecls;2398 2399  // Do not access these directly, use the get/set methods below to make2400  // sure the values are in sync2401  llvm::Triple::EnvironmentType CurrentShaderEnvironment;2402  unsigned CurrentShaderStageBit;2403 2404  // True if scanning a function that was already scanned in a different2405  // shader stage context, and therefore we should not report issues that2406  // depend only on shader model version because they would be duplicate.2407  bool ReportOnlyShaderStageIssues;2408 2409  // Helper methods for dealing with current stage context / environment2410  void SetShaderStageContext(llvm::Triple::EnvironmentType ShaderType) {2411    static_assert(sizeof(unsigned) >= 4);2412    assert(HLSLShaderAttr::isValidShaderType(ShaderType));2413    assert((unsigned)(ShaderType - llvm::Triple::Pixel) < 31 &&2414           "ShaderType is too big for this bitmap"); // 31 is reserved for2415                                                     // "unknown"2416 2417    unsigned bitmapIndex = ShaderType - llvm::Triple::Pixel;2418    CurrentShaderEnvironment = ShaderType;2419    CurrentShaderStageBit = (1 << bitmapIndex);2420  }2421 2422  void SetUnknownShaderStageContext() {2423    CurrentShaderEnvironment = llvm::Triple::UnknownEnvironment;2424    CurrentShaderStageBit = (1 << 31);2425  }2426 2427  llvm::Triple::EnvironmentType GetCurrentShaderEnvironment() const {2428    return CurrentShaderEnvironment;2429  }2430 2431  bool InUnknownShaderStageContext() const {2432    return CurrentShaderEnvironment == llvm::Triple::UnknownEnvironment;2433  }2434 2435  // Helper methods for dealing with shader stage bitmap2436  void AddToScannedFunctions(const FunctionDecl *FD) {2437    unsigned &ScannedStages = ScannedDecls[FD];2438    ScannedStages |= CurrentShaderStageBit;2439  }2440 2441  unsigned GetScannedStages(const FunctionDecl *FD) { return ScannedDecls[FD]; }2442 2443  bool WasAlreadyScannedInCurrentStage(const FunctionDecl *FD) {2444    return WasAlreadyScannedInCurrentStage(GetScannedStages(FD));2445  }2446 2447  bool WasAlreadyScannedInCurrentStage(unsigned ScannerStages) {2448    return ScannerStages & CurrentShaderStageBit;2449  }2450 2451  static bool NeverBeenScanned(unsigned ScannedStages) {2452    return ScannedStages == 0;2453  }2454 2455  // Scanning methods2456  void HandleFunctionOrMethodRef(FunctionDecl *FD, Expr *RefExpr);2457  void CheckDeclAvailability(NamedDecl *D, const AvailabilityAttr *AA,2458                             SourceRange Range);2459  const AvailabilityAttr *FindAvailabilityAttr(const Decl *D);2460  bool HasMatchingEnvironmentOrNone(const AvailabilityAttr *AA);2461 2462public:2463  DiagnoseHLSLAvailability(Sema &SemaRef)2464      : SemaRef(SemaRef),2465        CurrentShaderEnvironment(llvm::Triple::UnknownEnvironment),2466        CurrentShaderStageBit(0), ReportOnlyShaderStageIssues(false) {}2467 2468  // AST traversal methods2469  void RunOnTranslationUnit(const TranslationUnitDecl *TU);2470  void RunOnFunction(const FunctionDecl *FD);2471 2472  bool VisitDeclRefExpr(DeclRefExpr *DRE) override {2473    FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(DRE->getDecl());2474    if (FD)2475      HandleFunctionOrMethodRef(FD, DRE);2476    return true;2477  }2478 2479  bool VisitMemberExpr(MemberExpr *ME) override {2480    FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(ME->getMemberDecl());2481    if (FD)2482      HandleFunctionOrMethodRef(FD, ME);2483    return true;2484  }2485};2486 2487void DiagnoseHLSLAvailability::HandleFunctionOrMethodRef(FunctionDecl *FD,2488                                                         Expr *RefExpr) {2489  assert((isa<DeclRefExpr>(RefExpr) || isa<MemberExpr>(RefExpr)) &&2490         "expected DeclRefExpr or MemberExpr");2491 2492  // has a definition -> add to stack to be scanned2493  const FunctionDecl *FDWithBody = nullptr;2494  if (FD->hasBody(FDWithBody)) {2495    if (!WasAlreadyScannedInCurrentStage(FDWithBody))2496      DeclsToScan.push_back(FDWithBody);2497    return;2498  }2499 2500  // no body -> diagnose availability2501  const AvailabilityAttr *AA = FindAvailabilityAttr(FD);2502  if (AA)2503    CheckDeclAvailability(2504        FD, AA, SourceRange(RefExpr->getBeginLoc(), RefExpr->getEndLoc()));2505}2506 2507void DiagnoseHLSLAvailability::RunOnTranslationUnit(2508    const TranslationUnitDecl *TU) {2509 2510  // Iterate over all shader entry functions and library exports, and for those2511  // that have a body (definiton), run diag scan on each, setting appropriate2512  // shader environment context based on whether it is a shader entry function2513  // or an exported function. Exported functions can be in namespaces and in2514  // export declarations so we need to scan those declaration contexts as well.2515  llvm::SmallVector<const DeclContext *, 8> DeclContextsToScan;2516  DeclContextsToScan.push_back(TU);2517 2518  while (!DeclContextsToScan.empty()) {2519    const DeclContext *DC = DeclContextsToScan.pop_back_val();2520    for (auto &D : DC->decls()) {2521      // do not scan implicit declaration generated by the implementation2522      if (D->isImplicit())2523        continue;2524 2525      // for namespace or export declaration add the context to the list to be2526      // scanned later2527      if (llvm::dyn_cast<NamespaceDecl>(D) || llvm::dyn_cast<ExportDecl>(D)) {2528        DeclContextsToScan.push_back(llvm::dyn_cast<DeclContext>(D));2529        continue;2530      }2531 2532      // skip over other decls or function decls without body2533      const FunctionDecl *FD = llvm::dyn_cast<FunctionDecl>(D);2534      if (!FD || !FD->isThisDeclarationADefinition())2535        continue;2536 2537      // shader entry point2538      if (HLSLShaderAttr *ShaderAttr = FD->getAttr<HLSLShaderAttr>()) {2539        SetShaderStageContext(ShaderAttr->getType());2540        RunOnFunction(FD);2541        continue;2542      }2543      // exported library function2544      // FIXME: replace this loop with external linkage check once issue #920712545      // is resolved2546      bool isExport = FD->isInExportDeclContext();2547      if (!isExport) {2548        for (const auto *Redecl : FD->redecls()) {2549          if (Redecl->isInExportDeclContext()) {2550            isExport = true;2551            break;2552          }2553        }2554      }2555      if (isExport) {2556        SetUnknownShaderStageContext();2557        RunOnFunction(FD);2558        continue;2559      }2560    }2561  }2562}2563 2564void DiagnoseHLSLAvailability::RunOnFunction(const FunctionDecl *FD) {2565  assert(DeclsToScan.empty() && "DeclsToScan should be empty");2566  DeclsToScan.push_back(FD);2567 2568  while (!DeclsToScan.empty()) {2569    // Take one decl from the stack and check it by traversing its AST.2570    // For any CallExpr found during the traversal add it's callee to the top of2571    // the stack to be processed next. Functions already processed are stored in2572    // ScannedDecls.2573    const FunctionDecl *FD = DeclsToScan.pop_back_val();2574 2575    // Decl was already scanned2576    const unsigned ScannedStages = GetScannedStages(FD);2577    if (WasAlreadyScannedInCurrentStage(ScannedStages))2578      continue;2579 2580    ReportOnlyShaderStageIssues = !NeverBeenScanned(ScannedStages);2581 2582    AddToScannedFunctions(FD);2583    TraverseStmt(FD->getBody());2584  }2585}2586 2587bool DiagnoseHLSLAvailability::HasMatchingEnvironmentOrNone(2588    const AvailabilityAttr *AA) {2589  IdentifierInfo *IIEnvironment = AA->getEnvironment();2590  if (!IIEnvironment)2591    return true;2592 2593  llvm::Triple::EnvironmentType CurrentEnv = GetCurrentShaderEnvironment();2594  if (CurrentEnv == llvm::Triple::UnknownEnvironment)2595    return false;2596 2597  llvm::Triple::EnvironmentType AttrEnv =2598      AvailabilityAttr::getEnvironmentType(IIEnvironment->getName());2599 2600  return CurrentEnv == AttrEnv;2601}2602 2603const AvailabilityAttr *2604DiagnoseHLSLAvailability::FindAvailabilityAttr(const Decl *D) {2605  AvailabilityAttr const *PartialMatch = nullptr;2606  // Check each AvailabilityAttr to find the one for this platform.2607  // For multiple attributes with the same platform try to find one for this2608  // environment.2609  for (const auto *A : D->attrs()) {2610    if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {2611      StringRef AttrPlatform = Avail->getPlatform()->getName();2612      StringRef TargetPlatform =2613          SemaRef.getASTContext().getTargetInfo().getPlatformName();2614 2615      // Match the platform name.2616      if (AttrPlatform == TargetPlatform) {2617        // Find the best matching attribute for this environment2618        if (HasMatchingEnvironmentOrNone(Avail))2619          return Avail;2620        PartialMatch = Avail;2621      }2622    }2623  }2624  return PartialMatch;2625}2626 2627// Check availability against target shader model version and current shader2628// stage and emit diagnostic2629void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,2630                                                     const AvailabilityAttr *AA,2631                                                     SourceRange Range) {2632 2633  IdentifierInfo *IIEnv = AA->getEnvironment();2634 2635  if (!IIEnv) {2636    // The availability attribute does not have environment -> it depends only2637    // on shader model version and not on specific the shader stage.2638 2639    // Skip emitting the diagnostics if the diagnostic mode is set to2640    // strict (-fhlsl-strict-availability) because all relevant diagnostics2641    // were already emitted in the DiagnoseUnguardedAvailability scan2642    // (SemaAvailability.cpp).2643    if (SemaRef.getLangOpts().HLSLStrictAvailability)2644      return;2645 2646    // Do not report shader-stage-independent issues if scanning a function2647    // that was already scanned in a different shader stage context (they would2648    // be duplicate)2649    if (ReportOnlyShaderStageIssues)2650      return;2651 2652  } else {2653    // The availability attribute has environment -> we need to know2654    // the current stage context to property diagnose it.2655    if (InUnknownShaderStageContext())2656      return;2657  }2658 2659  // Check introduced version and if environment matches2660  bool EnvironmentMatches = HasMatchingEnvironmentOrNone(AA);2661  VersionTuple Introduced = AA->getIntroduced();2662  VersionTuple TargetVersion =2663      SemaRef.Context.getTargetInfo().getPlatformMinVersion();2664 2665  if (TargetVersion >= Introduced && EnvironmentMatches)2666    return;2667 2668  // Emit diagnostic message2669  const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();2670  llvm::StringRef PlatformName(2671      AvailabilityAttr::getPrettyPlatformName(TI.getPlatformName()));2672 2673  llvm::StringRef CurrentEnvStr =2674      llvm::Triple::getEnvironmentTypeName(GetCurrentShaderEnvironment());2675 2676  llvm::StringRef AttrEnvStr =2677      AA->getEnvironment() ? AA->getEnvironment()->getName() : "";2678  bool UseEnvironment = !AttrEnvStr.empty();2679 2680  if (EnvironmentMatches) {2681    SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability)2682        << Range << D << PlatformName << Introduced.getAsString()2683        << UseEnvironment << CurrentEnvStr;2684  } else {2685    SemaRef.Diag(Range.getBegin(), diag::warn_hlsl_availability_unavailable)2686        << Range << D;2687  }2688 2689  SemaRef.Diag(D->getLocation(), diag::note_partial_availability_specified_here)2690      << D << PlatformName << Introduced.getAsString()2691      << SemaRef.Context.getTargetInfo().getPlatformMinVersion().getAsString()2692      << UseEnvironment << AttrEnvStr << CurrentEnvStr;2693}2694 2695} // namespace2696 2697void SemaHLSL::ActOnEndOfTranslationUnit(TranslationUnitDecl *TU) {2698  // process default CBuffer - create buffer layout struct and invoke codegenCGH2699  if (!DefaultCBufferDecls.empty()) {2700    HLSLBufferDecl *DefaultCBuffer = HLSLBufferDecl::CreateDefaultCBuffer(2701        SemaRef.getASTContext(), SemaRef.getCurLexicalContext(),2702        DefaultCBufferDecls);2703    addImplicitBindingAttrToDecl(SemaRef, DefaultCBuffer, RegisterType::CBuffer,2704                                 getNextImplicitBindingOrderID());2705    SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);2706    createHostLayoutStructForBuffer(SemaRef, DefaultCBuffer);2707 2708    // Set HasValidPackoffset if any of the decls has a register(c#) annotation;2709    for (const Decl *VD : DefaultCBufferDecls) {2710      const HLSLResourceBindingAttr *RBA =2711          VD->getAttr<HLSLResourceBindingAttr>();2712      if (RBA && RBA->hasRegisterSlot() &&2713          RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {2714        DefaultCBuffer->setHasValidPackoffset(true);2715        break;2716      }2717    }2718 2719    DeclGroupRef DG(DefaultCBuffer);2720    SemaRef.Consumer.HandleTopLevelDecl(DG);2721  }2722  diagnoseAvailabilityViolations(TU);2723}2724 2725void SemaHLSL::diagnoseAvailabilityViolations(TranslationUnitDecl *TU) {2726  // Skip running the diagnostics scan if the diagnostic mode is2727  // strict (-fhlsl-strict-availability) and the target shader stage is known2728  // because all relevant diagnostics were already emitted in the2729  // DiagnoseUnguardedAvailability scan (SemaAvailability.cpp).2730  const TargetInfo &TI = SemaRef.getASTContext().getTargetInfo();2731  if (SemaRef.getLangOpts().HLSLStrictAvailability &&2732      TI.getTriple().getEnvironment() != llvm::Triple::EnvironmentType::Library)2733    return;2734 2735  DiagnoseHLSLAvailability(SemaRef).RunOnTranslationUnit(TU);2736}2737 2738static bool CheckAllArgsHaveSameType(Sema *S, CallExpr *TheCall) {2739  assert(TheCall->getNumArgs() > 1);2740  QualType ArgTy0 = TheCall->getArg(0)->getType();2741 2742  for (unsigned I = 1, N = TheCall->getNumArgs(); I < N; ++I) {2743    if (!S->getASTContext().hasSameUnqualifiedType(2744            ArgTy0, TheCall->getArg(I)->getType())) {2745      S->Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector)2746          << TheCall->getDirectCallee() << /*useAllTerminology*/ true2747          << SourceRange(TheCall->getArg(0)->getBeginLoc(),2748                         TheCall->getArg(N - 1)->getEndLoc());2749      return true;2750    }2751  }2752  return false;2753}2754 2755static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType) {2756  QualType ArgType = Arg->getType();2757  if (!S->getASTContext().hasSameUnqualifiedType(ArgType, ExpectedType)) {2758    S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)2759        << ArgType << ExpectedType << 1 << 0 << 0;2760    return true;2761  }2762  return false;2763}2764 2765static bool CheckAllArgTypesAreCorrect(2766    Sema *S, CallExpr *TheCall,2767    llvm::function_ref<bool(Sema *S, SourceLocation Loc, int ArgOrdinal,2768                            clang::QualType PassedType)>2769        Check) {2770  for (unsigned I = 0; I < TheCall->getNumArgs(); ++I) {2771    Expr *Arg = TheCall->getArg(I);2772    if (Check(S, Arg->getBeginLoc(), I + 1, Arg->getType()))2773      return true;2774  }2775  return false;2776}2777 2778static bool CheckFloatOrHalfRepresentation(Sema *S, SourceLocation Loc,2779                                           int ArgOrdinal,2780                                           clang::QualType PassedType) {2781  clang::QualType BaseType =2782      PassedType->isVectorType()2783          ? PassedType->castAs<clang::VectorType>()->getElementType()2784          : PassedType;2785  if (!BaseType->isHalfType() && !BaseType->isFloat32Type())2786    return S->Diag(Loc, diag::err_builtin_invalid_arg_type)2787           << ArgOrdinal << /* scalar or vector of */ 5 << /* no int */ 02788           << /* half or float */ 2 << PassedType;2789  return false;2790}2791 2792static bool CheckModifiableLValue(Sema *S, CallExpr *TheCall,2793                                  unsigned ArgIndex) {2794  auto *Arg = TheCall->getArg(ArgIndex);2795  SourceLocation OrigLoc = Arg->getExprLoc();2796  if (Arg->IgnoreCasts()->isModifiableLvalue(S->Context, &OrigLoc) ==2797      Expr::MLV_Valid)2798    return false;2799  S->Diag(OrigLoc, diag::error_hlsl_inout_lvalue) << Arg << 0;2800  return true;2801}2802 2803static bool CheckNoDoubleVectors(Sema *S, SourceLocation Loc, int ArgOrdinal,2804                                 clang::QualType PassedType) {2805  const auto *VecTy = PassedType->getAs<VectorType>();2806  if (!VecTy)2807    return false;2808 2809  if (VecTy->getElementType()->isDoubleType())2810    return S->Diag(Loc, diag::err_builtin_invalid_arg_type)2811           << ArgOrdinal << /* scalar */ 1 << /* no int */ 0 << /* fp */ 12812           << PassedType;2813  return false;2814}2815 2816static bool CheckFloatingOrIntRepresentation(Sema *S, SourceLocation Loc,2817                                             int ArgOrdinal,2818                                             clang::QualType PassedType) {2819  if (!PassedType->hasIntegerRepresentation() &&2820      !PassedType->hasFloatingRepresentation())2821    return S->Diag(Loc, diag::err_builtin_invalid_arg_type)2822           << ArgOrdinal << /* scalar or vector of */ 5 << /* integer */ 12823           << /* fp */ 1 << PassedType;2824  return false;2825}2826 2827static bool CheckUnsignedIntVecRepresentation(Sema *S, SourceLocation Loc,2828                                              int ArgOrdinal,2829                                              clang::QualType PassedType) {2830  if (auto *VecTy = PassedType->getAs<VectorType>())2831    if (VecTy->getElementType()->isUnsignedIntegerType())2832      return false;2833 2834  return S->Diag(Loc, diag::err_builtin_invalid_arg_type)2835         << ArgOrdinal << /* vector of */ 4 << /* uint */ 3 << /* no fp */ 02836         << PassedType;2837}2838 2839// checks for unsigned ints of all sizes2840static bool CheckUnsignedIntRepresentation(Sema *S, SourceLocation Loc,2841                                           int ArgOrdinal,2842                                           clang::QualType PassedType) {2843  if (!PassedType->hasUnsignedIntegerRepresentation())2844    return S->Diag(Loc, diag::err_builtin_invalid_arg_type)2845           << ArgOrdinal << /* scalar or vector of */ 5 << /* unsigned int */ 32846           << /* no fp */ 0 << PassedType;2847  return false;2848}2849 2850static bool CheckExpectedBitWidth(Sema *S, CallExpr *TheCall,2851                                  unsigned ArgOrdinal, unsigned Width) {2852  QualType ArgTy = TheCall->getArg(0)->getType();2853  if (auto *VTy = ArgTy->getAs<VectorType>())2854    ArgTy = VTy->getElementType();2855  // ensure arg type has expected bit width2856  uint64_t ElementBitCount =2857      S->getASTContext().getTypeSizeInChars(ArgTy).getQuantity() * 8;2858  if (ElementBitCount != Width) {2859    S->Diag(TheCall->getArg(0)->getBeginLoc(),2860            diag::err_integer_incorrect_bit_count)2861        << Width << ElementBitCount;2862    return true;2863  }2864  return false;2865}2866 2867static void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall,2868                                       QualType ReturnType) {2869  auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>();2870  if (VecTyA)2871    ReturnType =2872        S->Context.getExtVectorType(ReturnType, VecTyA->getNumElements());2873 2874  TheCall->setType(ReturnType);2875}2876 2877static bool CheckScalarOrVector(Sema *S, CallExpr *TheCall, QualType Scalar,2878                                unsigned ArgIndex) {2879  assert(TheCall->getNumArgs() >= ArgIndex);2880  QualType ArgType = TheCall->getArg(ArgIndex)->getType();2881  auto *VTy = ArgType->getAs<VectorType>();2882  // not the scalar or vector<scalar>2883  if (!(S->Context.hasSameUnqualifiedType(ArgType, Scalar) ||2884        (VTy &&2885         S->Context.hasSameUnqualifiedType(VTy->getElementType(), Scalar)))) {2886    S->Diag(TheCall->getArg(0)->getBeginLoc(),2887            diag::err_typecheck_expect_scalar_or_vector)2888        << ArgType << Scalar;2889    return true;2890  }2891  return false;2892}2893 2894static bool CheckAnyScalarOrVector(Sema *S, CallExpr *TheCall,2895                                   unsigned ArgIndex) {2896  assert(TheCall->getNumArgs() >= ArgIndex);2897  QualType ArgType = TheCall->getArg(ArgIndex)->getType();2898  auto *VTy = ArgType->getAs<VectorType>();2899  // not the scalar or vector<scalar>2900  if (!(ArgType->isScalarType() ||2901        (VTy && VTy->getElementType()->isScalarType()))) {2902    S->Diag(TheCall->getArg(0)->getBeginLoc(),2903            diag::err_typecheck_expect_any_scalar_or_vector)2904        << ArgType << 1;2905    return true;2906  }2907  return false;2908}2909 2910static bool CheckWaveActive(Sema *S, CallExpr *TheCall) {2911  QualType BoolType = S->getASTContext().BoolTy;2912  assert(TheCall->getNumArgs() >= 1);2913  QualType ArgType = TheCall->getArg(0)->getType();2914  auto *VTy = ArgType->getAs<VectorType>();2915  // is the bool or vector<bool>2916  if (S->Context.hasSameUnqualifiedType(ArgType, BoolType) ||2917      (VTy &&2918       S->Context.hasSameUnqualifiedType(VTy->getElementType(), BoolType))) {2919    S->Diag(TheCall->getArg(0)->getBeginLoc(),2920            diag::err_typecheck_expect_any_scalar_or_vector)2921        << ArgType << 0;2922    return true;2923  }2924  return false;2925}2926 2927static bool CheckBoolSelect(Sema *S, CallExpr *TheCall) {2928  assert(TheCall->getNumArgs() == 3);2929  Expr *Arg1 = TheCall->getArg(1);2930  Expr *Arg2 = TheCall->getArg(2);2931  if (!S->Context.hasSameUnqualifiedType(Arg1->getType(), Arg2->getType())) {2932    S->Diag(TheCall->getBeginLoc(),2933            diag::err_typecheck_call_different_arg_types)2934        << Arg1->getType() << Arg2->getType() << Arg1->getSourceRange()2935        << Arg2->getSourceRange();2936    return true;2937  }2938 2939  TheCall->setType(Arg1->getType());2940  return false;2941}2942 2943static bool CheckVectorSelect(Sema *S, CallExpr *TheCall) {2944  assert(TheCall->getNumArgs() == 3);2945  Expr *Arg1 = TheCall->getArg(1);2946  QualType Arg1Ty = Arg1->getType();2947  Expr *Arg2 = TheCall->getArg(2);2948  QualType Arg2Ty = Arg2->getType();2949 2950  QualType Arg1ScalarTy = Arg1Ty;2951  if (auto VTy = Arg1ScalarTy->getAs<VectorType>())2952    Arg1ScalarTy = VTy->getElementType();2953 2954  QualType Arg2ScalarTy = Arg2Ty;2955  if (auto VTy = Arg2ScalarTy->getAs<VectorType>())2956    Arg2ScalarTy = VTy->getElementType();2957 2958  if (!S->Context.hasSameUnqualifiedType(Arg1ScalarTy, Arg2ScalarTy))2959    S->Diag(Arg1->getBeginLoc(), diag::err_hlsl_builtin_scalar_vector_mismatch)2960        << /* second and third */ 1 << TheCall->getCallee() << Arg1Ty << Arg2Ty;2961 2962  QualType Arg0Ty = TheCall->getArg(0)->getType();2963  unsigned Arg0Length = Arg0Ty->getAs<VectorType>()->getNumElements();2964  unsigned Arg1Length = Arg1Ty->isVectorType()2965                            ? Arg1Ty->getAs<VectorType>()->getNumElements()2966                            : 0;2967  unsigned Arg2Length = Arg2Ty->isVectorType()2968                            ? Arg2Ty->getAs<VectorType>()->getNumElements()2969                            : 0;2970  if (Arg1Length > 0 && Arg0Length != Arg1Length) {2971    S->Diag(TheCall->getBeginLoc(),2972            diag::err_typecheck_vector_lengths_not_equal)2973        << Arg0Ty << Arg1Ty << TheCall->getArg(0)->getSourceRange()2974        << Arg1->getSourceRange();2975    return true;2976  }2977 2978  if (Arg2Length > 0 && Arg0Length != Arg2Length) {2979    S->Diag(TheCall->getBeginLoc(),2980            diag::err_typecheck_vector_lengths_not_equal)2981        << Arg0Ty << Arg2Ty << TheCall->getArg(0)->getSourceRange()2982        << Arg2->getSourceRange();2983    return true;2984  }2985 2986  TheCall->setType(2987      S->getASTContext().getExtVectorType(Arg1ScalarTy, Arg0Length));2988  return false;2989}2990 2991static bool CheckResourceHandle(2992    Sema *S, CallExpr *TheCall, unsigned ArgIndex,2993    llvm::function_ref<bool(const HLSLAttributedResourceType *ResType)> Check =2994        nullptr) {2995  assert(TheCall->getNumArgs() >= ArgIndex);2996  QualType ArgType = TheCall->getArg(ArgIndex)->getType();2997  const HLSLAttributedResourceType *ResTy =2998      ArgType.getTypePtr()->getAs<HLSLAttributedResourceType>();2999  if (!ResTy) {3000    S->Diag(TheCall->getArg(ArgIndex)->getBeginLoc(),3001            diag::err_typecheck_expect_hlsl_resource)3002        << ArgType;3003    return true;3004  }3005  if (Check && Check(ResTy)) {3006    S->Diag(TheCall->getArg(ArgIndex)->getExprLoc(),3007            diag::err_invalid_hlsl_resource_type)3008        << ArgType;3009    return true;3010  }3011  return false;3012}3013 3014// Note: returning true in this case results in CheckBuiltinFunctionCall3015// returning an ExprError3016bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {3017  switch (BuiltinID) {3018  case Builtin::BI__builtin_hlsl_adduint64: {3019    if (SemaRef.checkArgCount(TheCall, 2))3020      return true;3021 3022    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3023                                   CheckUnsignedIntVecRepresentation))3024      return true;3025 3026    // ensure arg integers are 32-bits3027    if (CheckExpectedBitWidth(&SemaRef, TheCall, 0, 32))3028      return true;3029 3030    // ensure both args are vectors of total bit size of a multiple of 643031    auto *VTy = TheCall->getArg(0)->getType()->getAs<VectorType>();3032    int NumElementsArg = VTy->getNumElements();3033    if (NumElementsArg != 2 && NumElementsArg != 4) {3034      SemaRef.Diag(TheCall->getBeginLoc(), diag::err_vector_incorrect_bit_count)3035          << 1 /*a multiple of*/ << 64 << NumElementsArg * 32;3036      return true;3037    }3038 3039    // ensure first arg and second arg have the same type3040    if (CheckAllArgsHaveSameType(&SemaRef, TheCall))3041      return true;3042 3043    ExprResult A = TheCall->getArg(0);3044    QualType ArgTyA = A.get()->getType();3045    // return type is the same as the input type3046    TheCall->setType(ArgTyA);3047    break;3048  }3049  case Builtin::BI__builtin_hlsl_resource_getpointer: {3050    if (SemaRef.checkArgCount(TheCall, 2) ||3051        CheckResourceHandle(&SemaRef, TheCall, 0) ||3052        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),3053                            SemaRef.getASTContext().UnsignedIntTy))3054      return true;3055 3056    auto *ResourceTy =3057        TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();3058    QualType ContainedTy = ResourceTy->getContainedType();3059    auto ReturnType =3060        SemaRef.Context.getAddrSpaceQualType(ContainedTy, LangAS::hlsl_device);3061    ReturnType = SemaRef.Context.getPointerType(ReturnType);3062    TheCall->setType(ReturnType);3063    TheCall->setValueKind(VK_LValue);3064 3065    break;3066  }3067  case Builtin::BI__builtin_hlsl_resource_load_with_status: {3068    if (SemaRef.checkArgCount(TheCall, 3) ||3069        CheckResourceHandle(&SemaRef, TheCall, 0) ||3070        CheckArgTypeMatches(&SemaRef, TheCall->getArg(1),3071                            SemaRef.getASTContext().UnsignedIntTy) ||3072        CheckArgTypeMatches(&SemaRef, TheCall->getArg(2),3073                            SemaRef.getASTContext().UnsignedIntTy) ||3074        CheckModifiableLValue(&SemaRef, TheCall, 2))3075      return true;3076 3077    auto *ResourceTy =3078        TheCall->getArg(0)->getType()->castAs<HLSLAttributedResourceType>();3079    QualType ReturnType = ResourceTy->getContainedType();3080    TheCall->setType(ReturnType);3081 3082    break;3083  }3084 3085  case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {3086    assert(TheCall->getNumArgs() == 1 && "expected 1 arg");3087    // Update return type to be the attributed resource type from arg0.3088    QualType ResourceTy = TheCall->getArg(0)->getType();3089    TheCall->setType(ResourceTy);3090    break;3091  }3092  case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {3093    assert(TheCall->getNumArgs() == 6 && "expected 6 args");3094    // Update return type to be the attributed resource type from arg0.3095    QualType ResourceTy = TheCall->getArg(0)->getType();3096    TheCall->setType(ResourceTy);3097    break;3098  }3099  case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {3100    assert(TheCall->getNumArgs() == 6 && "expected 6 args");3101    // Update return type to be the attributed resource type from arg0.3102    QualType ResourceTy = TheCall->getArg(0)->getType();3103    TheCall->setType(ResourceTy);3104    break;3105  }3106  case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {3107    assert(TheCall->getNumArgs() == 3 && "expected 3 args");3108    ASTContext &AST = SemaRef.getASTContext();3109    QualType MainHandleTy = TheCall->getArg(0)->getType();3110    auto *MainResType = MainHandleTy->getAs<HLSLAttributedResourceType>();3111    auto MainAttrs = MainResType->getAttrs();3112    assert(!MainAttrs.IsCounter && "cannot create a counter from a counter");3113    MainAttrs.IsCounter = true;3114    QualType CounterHandleTy = AST.getHLSLAttributedResourceType(3115        MainResType->getWrappedType(), MainResType->getContainedType(),3116        MainAttrs);3117    // Update return type to be the attributed resource type from arg03118    // with added IsCounter flag.3119    TheCall->setType(CounterHandleTy);3120    break;3121  }3122  case Builtin::BI__builtin_hlsl_and:3123  case Builtin::BI__builtin_hlsl_or: {3124    if (SemaRef.checkArgCount(TheCall, 2))3125      return true;3126    if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))3127      return true;3128    if (CheckAllArgsHaveSameType(&SemaRef, TheCall))3129      return true;3130 3131    ExprResult A = TheCall->getArg(0);3132    QualType ArgTyA = A.get()->getType();3133    // return type is the same as the input type3134    TheCall->setType(ArgTyA);3135    break;3136  }3137  case Builtin::BI__builtin_hlsl_all:3138  case Builtin::BI__builtin_hlsl_any: {3139    if (SemaRef.checkArgCount(TheCall, 1))3140      return true;3141    if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))3142      return true;3143    break;3144  }3145  case Builtin::BI__builtin_hlsl_asdouble: {3146    if (SemaRef.checkArgCount(TheCall, 2))3147      return true;3148    if (CheckScalarOrVector(3149            &SemaRef, TheCall,3150            /*only check for uint*/ SemaRef.Context.UnsignedIntTy,3151            /* arg index */ 0))3152      return true;3153    if (CheckScalarOrVector(3154            &SemaRef, TheCall,3155            /*only check for uint*/ SemaRef.Context.UnsignedIntTy,3156            /* arg index */ 1))3157      return true;3158    if (CheckAllArgsHaveSameType(&SemaRef, TheCall))3159      return true;3160 3161    SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().DoubleTy);3162    break;3163  }3164  case Builtin::BI__builtin_hlsl_elementwise_clamp: {3165    if (SemaRef.BuiltinElementwiseTernaryMath(3166            TheCall, /*ArgTyRestr=*/3167            Sema::EltwiseBuiltinArgTyRestriction::None))3168      return true;3169    break;3170  }3171  case Builtin::BI__builtin_hlsl_dot: {3172    // arg count is checked by BuiltinVectorToScalarMath3173    if (SemaRef.BuiltinVectorToScalarMath(TheCall))3174      return true;3175    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall, CheckNoDoubleVectors))3176      return true;3177    break;3178  }3179  case Builtin::BI__builtin_hlsl_elementwise_firstbithigh:3180  case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {3181    if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))3182      return true;3183 3184    const Expr *Arg = TheCall->getArg(0);3185    QualType ArgTy = Arg->getType();3186    QualType EltTy = ArgTy;3187 3188    QualType ResTy = SemaRef.Context.UnsignedIntTy;3189 3190    if (auto *VecTy = EltTy->getAs<VectorType>()) {3191      EltTy = VecTy->getElementType();3192      ResTy = SemaRef.Context.getExtVectorType(ResTy, VecTy->getNumElements());3193    }3194 3195    if (!EltTy->isIntegerType()) {3196      Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)3197          << 1 << /* scalar or vector of */ 5 << /* integer ty */ 13198          << /* no fp */ 0 << ArgTy;3199      return true;3200    }3201 3202    TheCall->setType(ResTy);3203    break;3204  }3205  case Builtin::BI__builtin_hlsl_select: {3206    if (SemaRef.checkArgCount(TheCall, 3))3207      return true;3208    if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))3209      return true;3210    QualType ArgTy = TheCall->getArg(0)->getType();3211    if (ArgTy->isBooleanType() && CheckBoolSelect(&SemaRef, TheCall))3212      return true;3213    auto *VTy = ArgTy->getAs<VectorType>();3214    if (VTy && VTy->getElementType()->isBooleanType() &&3215        CheckVectorSelect(&SemaRef, TheCall))3216      return true;3217    break;3218  }3219  case Builtin::BI__builtin_hlsl_elementwise_saturate:3220  case Builtin::BI__builtin_hlsl_elementwise_rcp: {3221    if (SemaRef.checkArgCount(TheCall, 1))3222      return true;3223    if (!TheCall->getArg(0)3224             ->getType()3225             ->hasFloatingRepresentation()) // half or float or double3226      return SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),3227                          diag::err_builtin_invalid_arg_type)3228             << /* ordinal */ 1 << /* scalar or vector */ 5 << /* no int */ 03229             << /* fp */ 1 << TheCall->getArg(0)->getType();3230    if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))3231      return true;3232    break;3233  }3234  case Builtin::BI__builtin_hlsl_elementwise_degrees:3235  case Builtin::BI__builtin_hlsl_elementwise_radians:3236  case Builtin::BI__builtin_hlsl_elementwise_rsqrt:3237  case Builtin::BI__builtin_hlsl_elementwise_frac:3238  case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:3239  case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {3240    if (SemaRef.checkArgCount(TheCall, 1))3241      return true;3242    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3243                                   CheckFloatOrHalfRepresentation))3244      return true;3245    if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))3246      return true;3247    break;3248  }3249  case Builtin::BI__builtin_hlsl_elementwise_isinf:3250  case Builtin::BI__builtin_hlsl_elementwise_isnan: {3251    if (SemaRef.checkArgCount(TheCall, 1))3252      return true;3253    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3254                                   CheckFloatOrHalfRepresentation))3255      return true;3256    if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))3257      return true;3258    SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().BoolTy);3259    break;3260  }3261  case Builtin::BI__builtin_hlsl_lerp: {3262    if (SemaRef.checkArgCount(TheCall, 3))3263      return true;3264    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3265                                   CheckFloatOrHalfRepresentation))3266      return true;3267    if (CheckAllArgsHaveSameType(&SemaRef, TheCall))3268      return true;3269    if (SemaRef.BuiltinElementwiseTernaryMath(TheCall))3270      return true;3271    break;3272  }3273  case Builtin::BI__builtin_hlsl_mad: {3274    if (SemaRef.BuiltinElementwiseTernaryMath(3275            TheCall, /*ArgTyRestr=*/3276            Sema::EltwiseBuiltinArgTyRestriction::None))3277      return true;3278    break;3279  }3280  case Builtin::BI__builtin_hlsl_normalize: {3281    if (SemaRef.checkArgCount(TheCall, 1))3282      return true;3283    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3284                                   CheckFloatOrHalfRepresentation))3285      return true;3286    ExprResult A = TheCall->getArg(0);3287    QualType ArgTyA = A.get()->getType();3288    // return type is the same as the input type3289    TheCall->setType(ArgTyA);3290    break;3291  }3292  case Builtin::BI__builtin_hlsl_elementwise_sign: {3293    if (SemaRef.PrepareBuiltinElementwiseMathOneArgCall(TheCall))3294      return true;3295    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3296                                   CheckFloatingOrIntRepresentation))3297      return true;3298    SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().IntTy);3299    break;3300  }3301  case Builtin::BI__builtin_hlsl_step: {3302    if (SemaRef.checkArgCount(TheCall, 2))3303      return true;3304    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3305                                   CheckFloatOrHalfRepresentation))3306      return true;3307 3308    ExprResult A = TheCall->getArg(0);3309    QualType ArgTyA = A.get()->getType();3310    // return type is the same as the input type3311    TheCall->setType(ArgTyA);3312    break;3313  }3314  case Builtin::BI__builtin_hlsl_wave_active_max:3315  case Builtin::BI__builtin_hlsl_wave_active_min:3316  case Builtin::BI__builtin_hlsl_wave_active_sum: {3317    if (SemaRef.checkArgCount(TheCall, 1))3318      return true;3319 3320    // Ensure input expr type is a scalar/vector and the same as the return type3321    if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))3322      return true;3323    if (CheckWaveActive(&SemaRef, TheCall))3324      return true;3325    ExprResult Expr = TheCall->getArg(0);3326    QualType ArgTyExpr = Expr.get()->getType();3327    TheCall->setType(ArgTyExpr);3328    break;3329  }3330  // Note these are llvm builtins that we want to catch invalid intrinsic3331  // generation. Normal handling of these builtins will occur elsewhere.3332  case Builtin::BI__builtin_elementwise_bitreverse: {3333    // does not include a check for number of arguments3334    // because that is done previously3335    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3336                                   CheckUnsignedIntRepresentation))3337      return true;3338    break;3339  }3340  case Builtin::BI__builtin_hlsl_wave_read_lane_at: {3341    if (SemaRef.checkArgCount(TheCall, 2))3342      return true;3343 3344    // Ensure index parameter type can be interpreted as a uint3345    ExprResult Index = TheCall->getArg(1);3346    QualType ArgTyIndex = Index.get()->getType();3347    if (!ArgTyIndex->isIntegerType()) {3348      SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),3349                   diag::err_typecheck_convert_incompatible)3350          << ArgTyIndex << SemaRef.Context.UnsignedIntTy << 1 << 0 << 0;3351      return true;3352    }3353 3354    // Ensure input expr type is a scalar/vector and the same as the return type3355    if (CheckAnyScalarOrVector(&SemaRef, TheCall, 0))3356      return true;3357 3358    ExprResult Expr = TheCall->getArg(0);3359    QualType ArgTyExpr = Expr.get()->getType();3360    TheCall->setType(ArgTyExpr);3361    break;3362  }3363  case Builtin::BI__builtin_hlsl_wave_get_lane_index: {3364    if (SemaRef.checkArgCount(TheCall, 0))3365      return true;3366    break;3367  }3368  case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {3369    if (SemaRef.checkArgCount(TheCall, 3))3370      return true;3371 3372    if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.DoubleTy, 0) ||3373        CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.UnsignedIntTy,3374                            1) ||3375        CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.UnsignedIntTy,3376                            2))3377      return true;3378 3379    if (CheckModifiableLValue(&SemaRef, TheCall, 1) ||3380        CheckModifiableLValue(&SemaRef, TheCall, 2))3381      return true;3382    break;3383  }3384  case Builtin::BI__builtin_hlsl_elementwise_clip: {3385    if (SemaRef.checkArgCount(TheCall, 1))3386      return true;3387 3388    if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.FloatTy, 0))3389      return true;3390    break;3391  }3392  case Builtin::BI__builtin_elementwise_acos:3393  case Builtin::BI__builtin_elementwise_asin:3394  case Builtin::BI__builtin_elementwise_atan:3395  case Builtin::BI__builtin_elementwise_atan2:3396  case Builtin::BI__builtin_elementwise_ceil:3397  case Builtin::BI__builtin_elementwise_cos:3398  case Builtin::BI__builtin_elementwise_cosh:3399  case Builtin::BI__builtin_elementwise_exp:3400  case Builtin::BI__builtin_elementwise_exp2:3401  case Builtin::BI__builtin_elementwise_exp10:3402  case Builtin::BI__builtin_elementwise_floor:3403  case Builtin::BI__builtin_elementwise_fmod:3404  case Builtin::BI__builtin_elementwise_log:3405  case Builtin::BI__builtin_elementwise_log2:3406  case Builtin::BI__builtin_elementwise_log10:3407  case Builtin::BI__builtin_elementwise_pow:3408  case Builtin::BI__builtin_elementwise_roundeven:3409  case Builtin::BI__builtin_elementwise_sin:3410  case Builtin::BI__builtin_elementwise_sinh:3411  case Builtin::BI__builtin_elementwise_sqrt:3412  case Builtin::BI__builtin_elementwise_tan:3413  case Builtin::BI__builtin_elementwise_tanh:3414  case Builtin::BI__builtin_elementwise_trunc: {3415    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3416                                   CheckFloatOrHalfRepresentation))3417      return true;3418    break;3419  }3420  case Builtin::BI__builtin_hlsl_buffer_update_counter: {3421    assert(TheCall->getNumArgs() == 2 && "expected 2 args");3422    auto checkResTy = [](const HLSLAttributedResourceType *ResTy) -> bool {3423      return !(ResTy->getAttrs().ResourceClass == ResourceClass::UAV &&3424               ResTy->getAttrs().RawBuffer && ResTy->hasContainedType());3425    };3426    if (CheckResourceHandle(&SemaRef, TheCall, 0, checkResTy))3427      return true;3428    Expr *OffsetExpr = TheCall->getArg(1);3429    std::optional<llvm::APSInt> Offset =3430        OffsetExpr->getIntegerConstantExpr(SemaRef.getASTContext());3431    if (!Offset.has_value() || std::abs(Offset->getExtValue()) != 1) {3432      SemaRef.Diag(TheCall->getArg(1)->getBeginLoc(),3433                   diag::err_hlsl_expect_arg_const_int_one_or_neg_one)3434          << 1;3435      return true;3436    }3437    break;3438  }3439  case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {3440    if (SemaRef.checkArgCount(TheCall, 1))3441      return true;3442    if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,3443                                   CheckUnsignedIntRepresentation))3444      return true;3445    // ensure arg integers are 32 bits3446    if (CheckExpectedBitWidth(&SemaRef, TheCall, 0, 32))3447      return true;3448    // check it wasn't a bool type3449    QualType ArgTy = TheCall->getArg(0)->getType();3450    if (auto *VTy = ArgTy->getAs<VectorType>())3451      ArgTy = VTy->getElementType();3452    if (ArgTy->isBooleanType()) {3453      SemaRef.Diag(TheCall->getArg(0)->getBeginLoc(),3454                   diag::err_builtin_invalid_arg_type)3455          << 1 << /* scalar or vector of */ 5 << /* unsigned int */ 33456          << /* no fp */ 0 << TheCall->getArg(0)->getType();3457      return true;3458    }3459 3460    SetElementTypeAsReturnType(&SemaRef, TheCall, getASTContext().FloatTy);3461    break;3462  }3463  }3464  return false;3465}3466 3467static void BuildFlattenedTypeList(QualType BaseTy,3468                                   llvm::SmallVectorImpl<QualType> &List) {3469  llvm::SmallVector<QualType, 16> WorkList;3470  WorkList.push_back(BaseTy);3471  while (!WorkList.empty()) {3472    QualType T = WorkList.pop_back_val();3473    T = T.getCanonicalType().getUnqualifiedType();3474    if (const auto *AT = dyn_cast<ConstantArrayType>(T)) {3475      llvm::SmallVector<QualType, 16> ElementFields;3476      // Generally I've avoided recursion in this algorithm, but arrays of3477      // structs could be time-consuming to flatten and churn through on the3478      // work list. Hopefully nesting arrays of structs containing arrays3479      // of structs too many levels deep is unlikely.3480      BuildFlattenedTypeList(AT->getElementType(), ElementFields);3481      // Repeat the element's field list n times.3482      for (uint64_t Ct = 0; Ct < AT->getZExtSize(); ++Ct)3483        llvm::append_range(List, ElementFields);3484      continue;3485    }3486    // Vectors can only have element types that are builtin types, so this can3487    // add directly to the list instead of to the WorkList.3488    if (const auto *VT = dyn_cast<VectorType>(T)) {3489      List.insert(List.end(), VT->getNumElements(), VT->getElementType());3490      continue;3491    }3492    if (const auto *MT = dyn_cast<ConstantMatrixType>(T)) {3493      List.insert(List.end(), MT->getNumElementsFlattened(),3494                  MT->getElementType());3495      continue;3496    }3497    if (const auto *RD = T->getAsCXXRecordDecl()) {3498      if (RD->isStandardLayout())3499        RD = RD->getStandardLayoutBaseWithFields();3500 3501      // For types that we shouldn't decompose (unions and non-aggregates), just3502      // add the type itself to the list.3503      if (RD->isUnion() || !RD->isAggregate()) {3504        List.push_back(T);3505        continue;3506      }3507 3508      llvm::SmallVector<QualType, 16> FieldTypes;3509      for (const auto *FD : RD->fields())3510        if (!FD->isUnnamedBitField())3511          FieldTypes.push_back(FD->getType());3512      // Reverse the newly added sub-range.3513      std::reverse(FieldTypes.begin(), FieldTypes.end());3514      llvm::append_range(WorkList, FieldTypes);3515 3516      // If this wasn't a standard layout type we may also have some base3517      // classes to deal with.3518      if (!RD->isStandardLayout()) {3519        FieldTypes.clear();3520        for (const auto &Base : RD->bases())3521          FieldTypes.push_back(Base.getType());3522        std::reverse(FieldTypes.begin(), FieldTypes.end());3523        llvm::append_range(WorkList, FieldTypes);3524      }3525      continue;3526    }3527    List.push_back(T);3528  }3529}3530 3531bool SemaHLSL::IsTypedResourceElementCompatible(clang::QualType QT) {3532  // null and array types are not allowed.3533  if (QT.isNull() || QT->isArrayType())3534    return false;3535 3536  // UDT types are not allowed3537  if (QT->isRecordType())3538    return false;3539 3540  if (QT->isBooleanType() || QT->isEnumeralType())3541    return false;3542 3543  // the only other valid builtin types are scalars or vectors3544  if (QT->isArithmeticType()) {3545    if (SemaRef.Context.getTypeSize(QT) / 8 > 16)3546      return false;3547    return true;3548  }3549 3550  if (const VectorType *VT = QT->getAs<VectorType>()) {3551    int ArraySize = VT->getNumElements();3552 3553    if (ArraySize > 4)3554      return false;3555 3556    QualType ElTy = VT->getElementType();3557    if (ElTy->isBooleanType())3558      return false;3559 3560    if (SemaRef.Context.getTypeSize(QT) / 8 > 16)3561      return false;3562    return true;3563  }3564 3565  return false;3566}3567 3568bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const {3569  if (T1.isNull() || T2.isNull())3570    return false;3571 3572  T1 = T1.getCanonicalType().getUnqualifiedType();3573  T2 = T2.getCanonicalType().getUnqualifiedType();3574 3575  // If both types are the same canonical type, they're obviously compatible.3576  if (SemaRef.getASTContext().hasSameType(T1, T2))3577    return true;3578 3579  llvm::SmallVector<QualType, 16> T1Types;3580  BuildFlattenedTypeList(T1, T1Types);3581  llvm::SmallVector<QualType, 16> T2Types;3582  BuildFlattenedTypeList(T2, T2Types);3583 3584  // Check the flattened type list3585  return llvm::equal(T1Types, T2Types,3586                     [this](QualType LHS, QualType RHS) -> bool {3587                       return SemaRef.IsLayoutCompatible(LHS, RHS);3588                     });3589}3590 3591bool SemaHLSL::CheckCompatibleParameterABI(FunctionDecl *New,3592                                           FunctionDecl *Old) {3593  if (New->getNumParams() != Old->getNumParams())3594    return true;3595 3596  bool HadError = false;3597 3598  for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) {3599    ParmVarDecl *NewParam = New->getParamDecl(i);3600    ParmVarDecl *OldParam = Old->getParamDecl(i);3601 3602    // HLSL parameter declarations for inout and out must match between3603    // declarations. In HLSL inout and out are ambiguous at the call site,3604    // but have different calling behavior, so you cannot overload a3605    // method based on a difference between inout and out annotations.3606    const auto *NDAttr = NewParam->getAttr<HLSLParamModifierAttr>();3607    unsigned NSpellingIdx = (NDAttr ? NDAttr->getSpellingListIndex() : 0);3608    const auto *ODAttr = OldParam->getAttr<HLSLParamModifierAttr>();3609    unsigned OSpellingIdx = (ODAttr ? ODAttr->getSpellingListIndex() : 0);3610 3611    if (NSpellingIdx != OSpellingIdx) {3612      SemaRef.Diag(NewParam->getLocation(),3613                   diag::err_hlsl_param_qualifier_mismatch)3614          << NDAttr << NewParam;3615      SemaRef.Diag(OldParam->getLocation(), diag::note_previous_declaration_as)3616          << ODAttr;3617      HadError = true;3618    }3619  }3620  return HadError;3621}3622 3623// Generally follows PerformScalarCast, with cases reordered for3624// clarity of what types are supported3625bool SemaHLSL::CanPerformScalarCast(QualType SrcTy, QualType DestTy) {3626 3627  if (!SrcTy->isScalarType() || !DestTy->isScalarType())3628    return false;3629 3630  if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy))3631    return true;3632 3633  switch (SrcTy->getScalarTypeKind()) {3634  case Type::STK_Bool: // casting from bool is like casting from an integer3635  case Type::STK_Integral:3636    switch (DestTy->getScalarTypeKind()) {3637    case Type::STK_Bool:3638    case Type::STK_Integral:3639    case Type::STK_Floating:3640      return true;3641    case Type::STK_CPointer:3642    case Type::STK_ObjCObjectPointer:3643    case Type::STK_BlockPointer:3644    case Type::STK_MemberPointer:3645      llvm_unreachable("HLSL doesn't support pointers.");3646    case Type::STK_IntegralComplex:3647    case Type::STK_FloatingComplex:3648      llvm_unreachable("HLSL doesn't support complex types.");3649    case Type::STK_FixedPoint:3650      llvm_unreachable("HLSL doesn't support fixed point types.");3651    }3652    llvm_unreachable("Should have returned before this");3653 3654  case Type::STK_Floating:3655    switch (DestTy->getScalarTypeKind()) {3656    case Type::STK_Floating:3657    case Type::STK_Bool:3658    case Type::STK_Integral:3659      return true;3660    case Type::STK_FloatingComplex:3661    case Type::STK_IntegralComplex:3662      llvm_unreachable("HLSL doesn't support complex types.");3663    case Type::STK_FixedPoint:3664      llvm_unreachable("HLSL doesn't support fixed point types.");3665    case Type::STK_CPointer:3666    case Type::STK_ObjCObjectPointer:3667    case Type::STK_BlockPointer:3668    case Type::STK_MemberPointer:3669      llvm_unreachable("HLSL doesn't support pointers.");3670    }3671    llvm_unreachable("Should have returned before this");3672 3673  case Type::STK_MemberPointer:3674  case Type::STK_CPointer:3675  case Type::STK_BlockPointer:3676  case Type::STK_ObjCObjectPointer:3677    llvm_unreachable("HLSL doesn't support pointers.");3678 3679  case Type::STK_FixedPoint:3680    llvm_unreachable("HLSL doesn't support fixed point types.");3681 3682  case Type::STK_FloatingComplex:3683  case Type::STK_IntegralComplex:3684    llvm_unreachable("HLSL doesn't support complex types.");3685  }3686 3687  llvm_unreachable("Unhandled scalar cast");3688}3689 3690// Can perform an HLSL Aggregate splat cast if the Dest is an aggregate and the3691// Src is a scalar or a vector of length 13692// Or if Dest is a vector and Src is a vector of length 13693bool SemaHLSL::CanPerformAggregateSplatCast(Expr *Src, QualType DestTy) {3694 3695  QualType SrcTy = Src->getType();3696  // Not a valid HLSL Aggregate Splat cast if Dest is a scalar or if this is3697  // going to be a vector splat from a scalar.3698  if ((SrcTy->isScalarType() && DestTy->isVectorType()) ||3699      DestTy->isScalarType())3700    return false;3701 3702  const VectorType *SrcVecTy = SrcTy->getAs<VectorType>();3703 3704  // Src isn't a scalar or a vector of length 13705  if (!SrcTy->isScalarType() && !(SrcVecTy && SrcVecTy->getNumElements() == 1))3706    return false;3707 3708  if (SrcVecTy)3709    SrcTy = SrcVecTy->getElementType();3710 3711  llvm::SmallVector<QualType> DestTypes;3712  BuildFlattenedTypeList(DestTy, DestTypes);3713 3714  for (unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) {3715    if (DestTypes[I]->isUnionType())3716      return false;3717    if (!CanPerformScalarCast(SrcTy, DestTypes[I]))3718      return false;3719  }3720  return true;3721}3722 3723// Can we perform an HLSL Elementwise cast?3724// TODO: update this code when matrices are added; see issue #880603725bool SemaHLSL::CanPerformElementwiseCast(Expr *Src, QualType DestTy) {3726 3727  // Don't handle casts where LHS and RHS are any combination of scalar/vector3728  // There must be an aggregate somewhere3729  QualType SrcTy = Src->getType();3730  if (SrcTy->isScalarType()) // always a splat and this cast doesn't handle that3731    return false;3732 3733  if (SrcTy->isVectorType() &&3734      (DestTy->isScalarType() || DestTy->isVectorType()))3735    return false;3736 3737  llvm::SmallVector<QualType> DestTypes;3738  BuildFlattenedTypeList(DestTy, DestTypes);3739  llvm::SmallVector<QualType> SrcTypes;3740  BuildFlattenedTypeList(SrcTy, SrcTypes);3741 3742  // Usually the size of SrcTypes must be greater than or equal to the size of3743  // DestTypes.3744  if (SrcTypes.size() < DestTypes.size())3745    return false;3746 3747  unsigned SrcSize = SrcTypes.size();3748  unsigned DstSize = DestTypes.size();3749  unsigned I;3750  for (I = 0; I < DstSize && I < SrcSize; I++) {3751    if (SrcTypes[I]->isUnionType() || DestTypes[I]->isUnionType())3752      return false;3753    if (!CanPerformScalarCast(SrcTypes[I], DestTypes[I])) {3754      return false;3755    }3756  }3757 3758  // check the rest of the source type for unions.3759  for (; I < SrcSize; I++) {3760    if (SrcTypes[I]->isUnionType())3761      return false;3762  }3763  return true;3764}3765 3766ExprResult SemaHLSL::ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg) {3767  assert(Param->hasAttr<HLSLParamModifierAttr>() &&3768         "We should not get here without a parameter modifier expression");3769  const auto *Attr = Param->getAttr<HLSLParamModifierAttr>();3770  if (Attr->getABI() == ParameterABI::Ordinary)3771    return ExprResult(Arg);3772 3773  bool IsInOut = Attr->getABI() == ParameterABI::HLSLInOut;3774  if (!Arg->isLValue()) {3775    SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_lvalue)3776        << Arg << (IsInOut ? 1 : 0);3777    return ExprError();3778  }3779 3780  ASTContext &Ctx = SemaRef.getASTContext();3781 3782  QualType Ty = Param->getType().getNonLValueExprType(Ctx);3783 3784  // HLSL allows implicit conversions from scalars to vectors, but not the3785  // inverse, so we need to disallow `inout` with scalar->vector or3786  // scalar->matrix conversions.3787  if (Arg->getType()->isScalarType() != Ty->isScalarType()) {3788    SemaRef.Diag(Arg->getBeginLoc(), diag::error_hlsl_inout_scalar_extension)3789        << Arg << (IsInOut ? 1 : 0);3790    return ExprError();3791  }3792 3793  auto *ArgOpV = new (Ctx) OpaqueValueExpr(Param->getBeginLoc(), Arg->getType(),3794                                           VK_LValue, OK_Ordinary, Arg);3795 3796  // Parameters are initialized via copy initialization. This allows for3797  // overload resolution of argument constructors.3798  InitializedEntity Entity =3799      InitializedEntity::InitializeParameter(Ctx, Ty, false);3800  ExprResult Res =3801      SemaRef.PerformCopyInitialization(Entity, Param->getBeginLoc(), ArgOpV);3802  if (Res.isInvalid())3803    return ExprError();3804  Expr *Base = Res.get();3805  // After the cast, drop the reference type when creating the exprs.3806  Ty = Ty.getNonLValueExprType(Ctx);3807  auto *OpV = new (Ctx)3808      OpaqueValueExpr(Param->getBeginLoc(), Ty, VK_LValue, OK_Ordinary, Base);3809 3810  // Writebacks are performed with `=` binary operator, which allows for3811  // overload resolution on writeback result expressions.3812  Res = SemaRef.ActOnBinOp(SemaRef.getCurScope(), Param->getBeginLoc(),3813                           tok::equal, ArgOpV, OpV);3814 3815  if (Res.isInvalid())3816    return ExprError();3817  Expr *Writeback = Res.get();3818  auto *OutExpr =3819      HLSLOutArgExpr::Create(Ctx, Ty, ArgOpV, OpV, Writeback, IsInOut);3820 3821  return ExprResult(OutExpr);3822}3823 3824QualType SemaHLSL::getInoutParameterType(QualType Ty) {3825  // If HLSL gains support for references, all the cites that use this will need3826  // to be updated with semantic checking to produce errors for3827  // pointers/references.3828  assert(!Ty->isReferenceType() &&3829         "Pointer and reference types cannot be inout or out parameters");3830  Ty = SemaRef.getASTContext().getLValueReferenceType(Ty);3831  Ty.addRestrict();3832  return Ty;3833}3834 3835static bool IsDefaultBufferConstantDecl(VarDecl *VD) {3836  QualType QT = VD->getType();3837  return VD->getDeclContext()->isTranslationUnit() &&3838         QT.getAddressSpace() == LangAS::Default &&3839         VD->getStorageClass() != SC_Static &&3840         !VD->hasAttr<HLSLVkConstantIdAttr>() &&3841         !isInvalidConstantBufferLeafElementType(QT.getTypePtr());3842}3843 3844void SemaHLSL::deduceAddressSpace(VarDecl *Decl) {3845  // The variable already has an address space (groupshared for ex).3846  if (Decl->getType().hasAddressSpace())3847    return;3848 3849  if (Decl->getType()->isDependentType())3850    return;3851 3852  QualType Type = Decl->getType();3853 3854  if (Decl->hasAttr<HLSLVkExtBuiltinInputAttr>()) {3855    LangAS ImplAS = LangAS::hlsl_input;3856    Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);3857    Decl->setType(Type);3858    return;3859  }3860 3861  if (Type->isSamplerT() || Type->isVoidType())3862    return;3863 3864  // Resource handles.3865  if (Type->isHLSLResourceRecord() || Type->isHLSLResourceRecordArray())3866    return;3867 3868  // Only static globals belong to the Private address space.3869  // Non-static globals belongs to the cbuffer.3870  if (Decl->getStorageClass() != SC_Static && !Decl->isStaticDataMember())3871    return;3872 3873  LangAS ImplAS = LangAS::hlsl_private;3874  Type = SemaRef.getASTContext().getAddrSpaceQualType(Type, ImplAS);3875  Decl->setType(Type);3876}3877 3878void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {3879  if (VD->hasGlobalStorage()) {3880    // make sure the declaration has a complete type3881    if (SemaRef.RequireCompleteType(3882            VD->getLocation(),3883            SemaRef.getASTContext().getBaseElementType(VD->getType()),3884            diag::err_typecheck_decl_incomplete_type)) {3885      VD->setInvalidDecl();3886      deduceAddressSpace(VD);3887      return;3888    }3889 3890    // Global variables outside a cbuffer block that are not a resource, static,3891    // groupshared, or an empty array or struct belong to the default constant3892    // buffer $Globals (to be created at the end of the translation unit).3893    if (IsDefaultBufferConstantDecl(VD)) {3894      // update address space to hlsl_constant3895      QualType NewTy = getASTContext().getAddrSpaceQualType(3896          VD->getType(), LangAS::hlsl_constant);3897      VD->setType(NewTy);3898      DefaultCBufferDecls.push_back(VD);3899    }3900 3901    // find all resources bindings on decl3902    if (VD->getType()->isHLSLIntangibleType())3903      collectResourceBindingsOnVarDecl(VD);3904 3905    if (VD->hasAttr<HLSLVkConstantIdAttr>())3906      VD->setStorageClass(StorageClass::SC_Static);3907 3908    if (isResourceRecordTypeOrArrayOf(VD) &&3909        VD->getStorageClass() != SC_Static) {3910      // Add internal linkage attribute to non-static resource variables. The3911      // global externally visible storage is accessed through the handle, which3912      // is a member. The variable itself is not externally visible.3913      VD->addAttr(InternalLinkageAttr::CreateImplicit(getASTContext()));3914    }3915 3916    // process explicit bindings3917    processExplicitBindingsOnDecl(VD);3918 3919    if (VD->getType()->isHLSLResourceRecordArray()) {3920      // If the resource array does not have an explicit binding attribute,3921      // create an implicit one. It will be used to transfer implicit binding3922      // order_ID to codegen.3923      ResourceBindingAttrs Binding(VD);3924      if (!Binding.isExplicit()) {3925        uint32_t OrderID = getNextImplicitBindingOrderID();3926        if (Binding.hasBinding())3927          Binding.setImplicitOrderID(OrderID);3928        else {3929          addImplicitBindingAttrToDecl(3930              SemaRef, VD, getRegisterType(getResourceArrayHandleType(VD)),3931              OrderID);3932          // Re-create the binding object to pick up the new attribute.3933          Binding = ResourceBindingAttrs(VD);3934        }3935      }3936 3937      // Get to the base type of a potentially multi-dimensional array.3938      QualType Ty = getASTContext().getBaseElementType(VD->getType());3939 3940      const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();3941      if (hasCounterHandle(RD)) {3942        if (!Binding.hasCounterImplicitOrderID()) {3943          uint32_t OrderID = getNextImplicitBindingOrderID();3944          Binding.setCounterImplicitOrderID(OrderID);3945        }3946      }3947    }3948  }3949 3950  deduceAddressSpace(VD);3951}3952 3953bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {3954  assert(VD->getType()->isHLSLResourceRecord() &&3955         "expected resource record type");3956 3957  ASTContext &AST = SemaRef.getASTContext();3958  uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);3959  uint64_t IntTySize = AST.getTypeSize(AST.IntTy);3960 3961  // Gather resource binding attributes.3962  ResourceBindingAttrs Binding(VD);3963 3964  // Find correct initialization method and create its arguments.3965  QualType ResourceTy = VD->getType();3966  CXXRecordDecl *ResourceDecl = ResourceTy->getAsCXXRecordDecl();3967  CXXMethodDecl *CreateMethod = nullptr;3968  llvm::SmallVector<Expr *> Args;3969 3970  bool HasCounter = hasCounterHandle(ResourceDecl);3971  const char *CreateMethodName;3972  if (Binding.isExplicit())3973    CreateMethodName = HasCounter ? "__createFromBindingWithImplicitCounter"3974                                  : "__createFromBinding";3975  else3976    CreateMethodName = HasCounter3977                           ? "__createFromImplicitBindingWithImplicitCounter"3978                           : "__createFromImplicitBinding";3979 3980  CreateMethod =3981      lookupMethod(SemaRef, ResourceDecl, CreateMethodName, VD->getLocation());3982 3983  if (!CreateMethod)3984    // This can happen if someone creates a struct that looks like an HLSL3985    // resource record but does not have the required static create method.3986    // No binding will be generated for it.3987    return false;3988 3989  if (Binding.isExplicit()) {3990    IntegerLiteral *RegSlot =3991        IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, Binding.getSlot()),3992                               AST.UnsignedIntTy, SourceLocation());3993    Args.push_back(RegSlot);3994  } else {3995    uint32_t OrderID = (Binding.hasImplicitOrderID())3996                           ? Binding.getImplicitOrderID()3997                           : getNextImplicitBindingOrderID();3998    IntegerLiteral *OrderId =3999        IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID),4000                               AST.UnsignedIntTy, SourceLocation());4001    Args.push_back(OrderId);4002  }4003 4004  IntegerLiteral *Space =4005      IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, Binding.getSpace()),4006                             AST.UnsignedIntTy, SourceLocation());4007  Args.push_back(Space);4008 4009  IntegerLiteral *RangeSize = IntegerLiteral::Create(4010      AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());4011  Args.push_back(RangeSize);4012 4013  IntegerLiteral *Index = IntegerLiteral::Create(4014      AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());4015  Args.push_back(Index);4016 4017  StringRef VarName = VD->getName();4018  StringLiteral *Name = StringLiteral::Create(4019      AST, VarName, StringLiteralKind::Ordinary, false,4020      AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()),4021      SourceLocation());4022  ImplicitCastExpr *NameCast = ImplicitCastExpr::Create(4023      AST, AST.getPointerType(AST.CharTy.withConst()), CK_ArrayToPointerDecay,4024      Name, nullptr, VK_PRValue, FPOptionsOverride());4025  Args.push_back(NameCast);4026 4027  if (HasCounter) {4028    // Will this be in the correct order?4029    uint32_t CounterOrderID = getNextImplicitBindingOrderID();4030    IntegerLiteral *CounterId =4031        IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, CounterOrderID),4032                               AST.UnsignedIntTy, SourceLocation());4033    Args.push_back(CounterId);4034  }4035 4036  // Make sure the create method template is instantiated and emitted.4037  if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())4038    SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,4039                                          true);4040 4041  // Create CallExpr with a call to the static method and set it as the decl4042  // initialization.4043  DeclRefExpr *DRE = DeclRefExpr::Create(4044      AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false,4045      CreateMethod->getNameInfo(), CreateMethod->getType(), VK_PRValue);4046 4047  auto *ImpCast = ImplicitCastExpr::Create(4048      AST, AST.getPointerType(CreateMethod->getType()),4049      CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());4050 4051  CallExpr *InitExpr =4052      CallExpr::Create(AST, ImpCast, Args, ResourceTy, VK_PRValue,4053                       SourceLocation(), FPOptionsOverride());4054  VD->setInit(InitExpr);4055  VD->setInitStyle(VarDecl::CallInit);4056  SemaRef.CheckCompleteVariableDeclaration(VD);4057  return true;4058}4059 4060bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {4061  assert(VD->getType()->isHLSLResourceRecordArray() &&4062         "expected array of resource records");4063 4064  // Individual resources in a resource array are not initialized here. They4065  // are initialized later on during codegen when the individual resources are4066  // accessed. Codegen will emit a call to the resource initialization method4067  // with the specified array index. We need to make sure though that the method4068  // for the specific resource type is instantiated, so codegen can emit a call4069  // to it when the array element is accessed.4070 4071  // Find correct initialization method based on the resource binding4072  // information.4073  ASTContext &AST = SemaRef.getASTContext();4074  QualType ResElementTy = AST.getBaseElementType(VD->getType());4075  CXXRecordDecl *ResourceDecl = ResElementTy->getAsCXXRecordDecl();4076  CXXMethodDecl *CreateMethod = nullptr;4077 4078  bool HasCounter = hasCounterHandle(ResourceDecl);4079  ResourceBindingAttrs ResourceAttrs(VD);4080  if (ResourceAttrs.isExplicit())4081    // Resource has explicit binding.4082    CreateMethod =4083        lookupMethod(SemaRef, ResourceDecl,4084                     HasCounter ? "__createFromBindingWithImplicitCounter"4085                                : "__createFromBinding",4086                     VD->getLocation());4087  else4088    // Resource has implicit binding.4089    CreateMethod = lookupMethod(4090        SemaRef, ResourceDecl,4091        HasCounter ? "__createFromImplicitBindingWithImplicitCounter"4092                   : "__createFromImplicitBinding",4093        VD->getLocation());4094 4095  if (!CreateMethod)4096    return false;4097 4098  // Make sure the create method template is instantiated and emitted.4099  if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())4100    SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,4101                                          true);4102  return true;4103}4104 4105// Returns true if the initialization has been handled.4106// Returns false to use default initialization.4107bool SemaHLSL::ActOnUninitializedVarDecl(VarDecl *VD) {4108  // Objects in the hlsl_constant address space are initialized4109  // externally, so don't synthesize an implicit initializer.4110  if (VD->getType().getAddressSpace() == LangAS::hlsl_constant)4111    return true;4112 4113  // Initialize resources at the global scope4114  if (VD->hasGlobalStorage()) {4115    const Type *Ty = VD->getType().getTypePtr();4116    if (Ty->isHLSLResourceRecord())4117      return initGlobalResourceDecl(VD);4118    if (Ty->isHLSLResourceRecordArray())4119      return initGlobalResourceArrayDecl(VD);4120  }4121  return false;4122}4123 4124// Return true if everything is ok; returns false if there was an error.4125bool SemaHLSL::CheckResourceBinOp(BinaryOperatorKind Opc, Expr *LHSExpr,4126                                  Expr *RHSExpr, SourceLocation Loc) {4127  assert((LHSExpr->getType()->isHLSLResourceRecord() ||4128          LHSExpr->getType()->isHLSLResourceRecordArray()) &&4129         "expected LHS to be a resource record or array of resource records");4130  if (Opc != BO_Assign)4131    return true;4132 4133  // If LHS is an array subscript, get the underlying declaration.4134  Expr *E = LHSExpr;4135  while (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))4136    E = ASE->getBase()->IgnoreParenImpCasts();4137 4138  // Report error if LHS is a resource declared at a global scope.4139  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {4140    if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {4141      if (VD->hasGlobalStorage()) {4142        // assignment to global resource is not allowed4143        SemaRef.Diag(Loc, diag::err_hlsl_assign_to_global_resource) << VD;4144        SemaRef.Diag(VD->getLocation(), diag::note_var_declared_here) << VD;4145        return false;4146      }4147    }4148  }4149  return true;4150}4151 4152// Walks though the global variable declaration, collects all resource binding4153// requirements and adds them to Bindings4154void SemaHLSL::collectResourceBindingsOnVarDecl(VarDecl *VD) {4155  assert(VD->hasGlobalStorage() && VD->getType()->isHLSLIntangibleType() &&4156         "expected global variable that contains HLSL resource");4157 4158  // Cbuffers and Tbuffers are HLSLBufferDecl types4159  if (const HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(VD)) {4160    Bindings.addDeclBindingInfo(VD, CBufferOrTBuffer->isCBuffer()4161                                        ? ResourceClass::CBuffer4162                                        : ResourceClass::SRV);4163    return;4164  }4165 4166  // Unwrap arrays4167  // FIXME: Calculate array size while unwrapping4168  const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();4169  while (Ty->isArrayType()) {4170    const ArrayType *AT = cast<ArrayType>(Ty);4171    Ty = AT->getElementType()->getUnqualifiedDesugaredType();4172  }4173 4174  // Resource (or array of resources)4175  if (const HLSLAttributedResourceType *AttrResType =4176          HLSLAttributedResourceType::findHandleTypeOnResource(Ty)) {4177    Bindings.addDeclBindingInfo(VD, AttrResType->getAttrs().ResourceClass);4178    return;4179  }4180 4181  // User defined record type4182  if (const RecordType *RT = dyn_cast<RecordType>(Ty))4183    collectResourceBindingsOnUserRecordDecl(VD, RT);4184}4185 4186// Walks though the explicit resource binding attributes on the declaration,4187// and makes sure there is a resource that matched the binding and updates4188// DeclBindingInfoLists4189void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {4190  assert(VD->hasGlobalStorage() && "expected global variable");4191 4192  bool HasBinding = false;4193  for (Attr *A : VD->attrs()) {4194    if (isa<HLSLVkBindingAttr>(A))4195      HasBinding = true;4196 4197    HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);4198    if (!RBA || !RBA->hasRegisterSlot())4199      continue;4200    HasBinding = true;4201 4202    RegisterType RT = RBA->getRegisterType();4203    assert(RT != RegisterType::I && "invalid or obsolete register type should "4204                                    "never have an attribute created");4205 4206    if (RT == RegisterType::C) {4207      if (Bindings.hasBindingInfoForDecl(VD))4208        SemaRef.Diag(VD->getLocation(),4209                     diag::warn_hlsl_user_defined_type_missing_member)4210            << static_cast<int>(RT);4211      continue;4212    }4213 4214    // Find DeclBindingInfo for this binding and update it, or report error4215    // if it does not exist (user type does to contain resources with the4216    // expected resource class).4217    ResourceClass RC = getResourceClass(RT);4218    if (DeclBindingInfo *BI = Bindings.getDeclBindingInfo(VD, RC)) {4219      // update binding info4220      BI->setBindingAttribute(RBA, BindingType::Explicit);4221    } else {4222      SemaRef.Diag(VD->getLocation(),4223                   diag::warn_hlsl_user_defined_type_missing_member)4224          << static_cast<int>(RT);4225    }4226  }4227 4228  if (!HasBinding && isResourceRecordTypeOrArrayOf(VD))4229    SemaRef.Diag(VD->getLocation(), diag::warn_hlsl_implicit_binding);4230}4231namespace {4232class InitListTransformer {4233  Sema &S;4234  ASTContext &Ctx;4235  QualType InitTy;4236  QualType *DstIt = nullptr;4237  Expr **ArgIt = nullptr;4238  // Is wrapping the destination type iterator required? This is only used for4239  // incomplete array types where we loop over the destination type since we4240  // don't know the full number of elements from the declaration.4241  bool Wrap;4242 4243  bool castInitializer(Expr *E) {4244    assert(DstIt && "This should always be something!");4245    if (DstIt == DestTypes.end()) {4246      if (!Wrap) {4247        ArgExprs.push_back(E);4248        // This is odd, but it isn't technically a failure due to conversion, we4249        // handle mismatched counts of arguments differently.4250        return true;4251      }4252      DstIt = DestTypes.begin();4253    }4254    InitializedEntity Entity = InitializedEntity::InitializeParameter(4255        Ctx, *DstIt, /* Consumed (ObjC) */ false);4256    ExprResult Res = S.PerformCopyInitialization(Entity, E->getBeginLoc(), E);4257    if (Res.isInvalid())4258      return false;4259    Expr *Init = Res.get();4260    ArgExprs.push_back(Init);4261    DstIt++;4262    return true;4263  }4264 4265  bool buildInitializerListImpl(Expr *E) {4266    // If this is an initialization list, traverse the sub initializers.4267    if (auto *Init = dyn_cast<InitListExpr>(E)) {4268      for (auto *SubInit : Init->inits())4269        if (!buildInitializerListImpl(SubInit))4270          return false;4271      return true;4272    }4273 4274    // If this is a scalar type, just enqueue the expression.4275    QualType Ty = E->getType();4276 4277    if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))4278      return castInitializer(E);4279 4280    if (auto *VecTy = Ty->getAs<VectorType>()) {4281      uint64_t Size = VecTy->getNumElements();4282 4283      QualType SizeTy = Ctx.getSizeType();4284      uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);4285      for (uint64_t I = 0; I < Size; ++I) {4286        auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),4287                                           SizeTy, SourceLocation());4288 4289        ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr(4290            E, E->getBeginLoc(), Idx, E->getEndLoc());4291        if (ElExpr.isInvalid())4292          return false;4293        if (!castInitializer(ElExpr.get()))4294          return false;4295      }4296      return true;4297    }4298    if (auto *MTy = Ty->getAs<ConstantMatrixType>()) {4299      unsigned Rows = MTy->getNumRows();4300      unsigned Cols = MTy->getNumColumns();4301      QualType ElemTy = MTy->getElementType();4302 4303      for (unsigned C = 0; C < Cols; ++C) {4304        for (unsigned R = 0; R < Rows; ++R) {4305          // row index literal4306          Expr *RowIdx = IntegerLiteral::Create(4307              Ctx, llvm::APInt(Ctx.getIntWidth(Ctx.IntTy), R), Ctx.IntTy,4308              E->getBeginLoc());4309          // column index literal4310          Expr *ColIdx = IntegerLiteral::Create(4311              Ctx, llvm::APInt(Ctx.getIntWidth(Ctx.IntTy), C), Ctx.IntTy,4312              E->getBeginLoc());4313          ExprResult ElExpr = S.CreateBuiltinMatrixSubscriptExpr(4314              E, RowIdx, ColIdx, E->getEndLoc());4315          if (ElExpr.isInvalid())4316            return false;4317          if (!castInitializer(ElExpr.get()))4318            return false;4319          ElExpr.get()->setType(ElemTy);4320        }4321      }4322      return true;4323    }4324 4325    if (auto *ArrTy = dyn_cast<ConstantArrayType>(Ty.getTypePtr())) {4326      uint64_t Size = ArrTy->getZExtSize();4327      QualType SizeTy = Ctx.getSizeType();4328      uint64_t SizeTySize = Ctx.getTypeSize(SizeTy);4329      for (uint64_t I = 0; I < Size; ++I) {4330        auto *Idx = IntegerLiteral::Create(Ctx, llvm::APInt(SizeTySize, I),4331                                           SizeTy, SourceLocation());4332        ExprResult ElExpr = S.CreateBuiltinArraySubscriptExpr(4333            E, E->getBeginLoc(), Idx, E->getEndLoc());4334        if (ElExpr.isInvalid())4335          return false;4336        if (!buildInitializerListImpl(ElExpr.get()))4337          return false;4338      }4339      return true;4340    }4341 4342    if (auto *RD = Ty->getAsCXXRecordDecl()) {4343      llvm::SmallVector<CXXRecordDecl *> RecordDecls;4344      RecordDecls.push_back(RD);4345      while (RecordDecls.back()->getNumBases()) {4346        CXXRecordDecl *D = RecordDecls.back();4347        assert(D->getNumBases() == 1 &&4348               "HLSL doesn't support multiple inheritance");4349        RecordDecls.push_back(4350            D->bases_begin()->getType()->castAsCXXRecordDecl());4351      }4352      while (!RecordDecls.empty()) {4353        CXXRecordDecl *RD = RecordDecls.pop_back_val();4354        for (auto *FD : RD->fields()) {4355          if (FD->isUnnamedBitField())4356            continue;4357          DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess());4358          DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc());4359          ExprResult Res = S.BuildFieldReferenceExpr(4360              E, false, E->getBeginLoc(), CXXScopeSpec(), FD, Found, NameInfo);4361          if (Res.isInvalid())4362            return false;4363          if (!buildInitializerListImpl(Res.get()))4364            return false;4365        }4366      }4367    }4368    return true;4369  }4370 4371  Expr *generateInitListsImpl(QualType Ty) {4372    assert(ArgIt != ArgExprs.end() && "Something is off in iteration!");4373    if (Ty->isScalarType() || (Ty->isRecordType() && !Ty->isAggregateType()))4374      return *(ArgIt++);4375 4376    llvm::SmallVector<Expr *> Inits;4377    Ty = Ty.getDesugaredType(Ctx);4378    if (Ty->isVectorType() || Ty->isConstantArrayType() ||4379        Ty->isConstantMatrixType()) {4380      QualType ElTy;4381      uint64_t Size = 0;4382      if (auto *ATy = Ty->getAs<VectorType>()) {4383        ElTy = ATy->getElementType();4384        Size = ATy->getNumElements();4385      } else if (auto *CMTy = Ty->getAs<ConstantMatrixType>()) {4386        ElTy = CMTy->getElementType();4387        Size = CMTy->getNumElementsFlattened();4388      } else {4389        auto *VTy = cast<ConstantArrayType>(Ty.getTypePtr());4390        ElTy = VTy->getElementType();4391        Size = VTy->getZExtSize();4392      }4393      for (uint64_t I = 0; I < Size; ++I)4394        Inits.push_back(generateInitListsImpl(ElTy));4395    }4396    if (auto *RD = Ty->getAsCXXRecordDecl()) {4397      llvm::SmallVector<CXXRecordDecl *> RecordDecls;4398      RecordDecls.push_back(RD);4399      while (RecordDecls.back()->getNumBases()) {4400        CXXRecordDecl *D = RecordDecls.back();4401        assert(D->getNumBases() == 1 &&4402               "HLSL doesn't support multiple inheritance");4403        RecordDecls.push_back(4404            D->bases_begin()->getType()->castAsCXXRecordDecl());4405      }4406      while (!RecordDecls.empty()) {4407        CXXRecordDecl *RD = RecordDecls.pop_back_val();4408        for (auto *FD : RD->fields())4409          if (!FD->isUnnamedBitField())4410            Inits.push_back(generateInitListsImpl(FD->getType()));4411      }4412    }4413    auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),4414                                           Inits, Inits.back()->getEndLoc());4415    NewInit->setType(Ty);4416    return NewInit;4417  }4418 4419public:4420  llvm::SmallVector<QualType, 16> DestTypes;4421  llvm::SmallVector<Expr *, 16> ArgExprs;4422  InitListTransformer(Sema &SemaRef, const InitializedEntity &Entity)4423      : S(SemaRef), Ctx(SemaRef.getASTContext()),4424        Wrap(Entity.getType()->isIncompleteArrayType()) {4425    InitTy = Entity.getType().getNonReferenceType();4426    // When we're generating initializer lists for incomplete array types we4427    // need to wrap around both when building the initializers and when4428    // generating the final initializer lists.4429    if (Wrap) {4430      assert(InitTy->isIncompleteArrayType());4431      const IncompleteArrayType *IAT = Ctx.getAsIncompleteArrayType(InitTy);4432      InitTy = IAT->getElementType();4433    }4434    BuildFlattenedTypeList(InitTy, DestTypes);4435    DstIt = DestTypes.begin();4436  }4437 4438  bool buildInitializerList(Expr *E) { return buildInitializerListImpl(E); }4439 4440  Expr *generateInitLists() {4441    assert(!ArgExprs.empty() &&4442           "Call buildInitializerList to generate argument expressions.");4443    ArgIt = ArgExprs.begin();4444    if (!Wrap)4445      return generateInitListsImpl(InitTy);4446    llvm::SmallVector<Expr *> Inits;4447    while (ArgIt != ArgExprs.end())4448      Inits.push_back(generateInitListsImpl(InitTy));4449 4450    auto *NewInit = new (Ctx) InitListExpr(Ctx, Inits.front()->getBeginLoc(),4451                                           Inits, Inits.back()->getEndLoc());4452    llvm::APInt ArySize(64, Inits.size());4453    NewInit->setType(Ctx.getConstantArrayType(InitTy, ArySize, nullptr,4454                                              ArraySizeModifier::Normal, 0));4455    return NewInit;4456  }4457};4458} // namespace4459 4460bool SemaHLSL::transformInitList(const InitializedEntity &Entity,4461                                 InitListExpr *Init) {4462  // If the initializer is a scalar, just return it.4463  if (Init->getType()->isScalarType())4464    return true;4465  ASTContext &Ctx = SemaRef.getASTContext();4466  InitListTransformer ILT(SemaRef, Entity);4467 4468  for (unsigned I = 0; I < Init->getNumInits(); ++I) {4469    Expr *E = Init->getInit(I);4470    if (E->HasSideEffects(Ctx)) {4471      QualType Ty = E->getType();4472      if (Ty->isRecordType())4473        E = new (Ctx) MaterializeTemporaryExpr(Ty, E, E->isLValue());4474      E = new (Ctx) OpaqueValueExpr(E->getBeginLoc(), Ty, E->getValueKind(),4475                                    E->getObjectKind(), E);4476      Init->setInit(I, E);4477    }4478    if (!ILT.buildInitializerList(E))4479      return false;4480  }4481  size_t ExpectedSize = ILT.DestTypes.size();4482  size_t ActualSize = ILT.ArgExprs.size();4483  if (ExpectedSize == 0 && ActualSize == 0)4484    return true;4485 4486  // For incomplete arrays it is completely arbitrary to choose whether we think4487  // the user intended fewer or more elements. This implementation assumes that4488  // the user intended more, and errors that there are too few initializers to4489  // complete the final element.4490  if (Entity.getType()->isIncompleteArrayType())4491    ExpectedSize =4492        ((ActualSize + ExpectedSize - 1) / ExpectedSize) * ExpectedSize;4493 4494  // An initializer list might be attempting to initialize a reference or4495  // rvalue-reference. When checking the initializer we should look through4496  // the reference.4497  QualType InitTy = Entity.getType().getNonReferenceType();4498  if (InitTy.hasAddressSpace())4499    InitTy = SemaRef.getASTContext().removeAddrSpaceQualType(InitTy);4500  if (ExpectedSize != ActualSize) {4501    int TooManyOrFew = ActualSize > ExpectedSize ? 1 : 0;4502    SemaRef.Diag(Init->getBeginLoc(), diag::err_hlsl_incorrect_num_initializers)4503        << TooManyOrFew << InitTy << ExpectedSize << ActualSize;4504    return false;4505  }4506 4507  // generateInitListsImpl will always return an InitListExpr here, because the4508  // scalar case is handled above.4509  auto *NewInit = cast<InitListExpr>(ILT.generateInitLists());4510  Init->resizeInits(Ctx, NewInit->getNumInits());4511  for (unsigned I = 0; I < NewInit->getNumInits(); ++I)4512    Init->updateInit(Ctx, I, NewInit->getInit(I));4513  return true;4514}4515 4516bool SemaHLSL::handleInitialization(VarDecl *VDecl, Expr *&Init) {4517  const HLSLVkConstantIdAttr *ConstIdAttr =4518      VDecl->getAttr<HLSLVkConstantIdAttr>();4519  if (!ConstIdAttr)4520    return true;4521 4522  ASTContext &Context = SemaRef.getASTContext();4523 4524  APValue InitValue;4525  if (!Init->isCXX11ConstantExpr(Context, &InitValue)) {4526    Diag(VDecl->getLocation(), diag::err_specialization_const);4527    VDecl->setInvalidDecl();4528    return false;4529  }4530 4531  Builtin::ID BID =4532      getSpecConstBuiltinId(VDecl->getType()->getUnqualifiedDesugaredType());4533 4534  // Argument 1: The ID from the attribute4535  int ConstantID = ConstIdAttr->getId();4536  llvm::APInt IDVal(Context.getIntWidth(Context.IntTy), ConstantID);4537  Expr *IdExpr = IntegerLiteral::Create(Context, IDVal, Context.IntTy,4538                                        ConstIdAttr->getLocation());4539 4540  SmallVector<Expr *, 2> Args = {IdExpr, Init};4541  Expr *C = SemaRef.BuildBuiltinCallExpr(Init->getExprLoc(), BID, Args);4542  if (C->getType()->getCanonicalTypeUnqualified() !=4543      VDecl->getType()->getCanonicalTypeUnqualified()) {4544    C = SemaRef4545            .BuildCStyleCastExpr(SourceLocation(),4546                                 Context.getTrivialTypeSourceInfo(4547                                     Init->getType(), Init->getExprLoc()),4548                                 SourceLocation(), C)4549            .get();4550  }4551  Init = C;4552  return true;4553}4554