1753f127fSDimitry Andric //===--- HLSLExternalSemaSource.cpp - HLSL Sema Source --------------------===// 2753f127fSDimitry Andric // 3753f127fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4753f127fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5753f127fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6753f127fSDimitry Andric // 7753f127fSDimitry Andric //===----------------------------------------------------------------------===// 8753f127fSDimitry Andric // 9753f127fSDimitry Andric // 10753f127fSDimitry Andric //===----------------------------------------------------------------------===// 11753f127fSDimitry Andric 12753f127fSDimitry Andric #include "clang/Sema/HLSLExternalSemaSource.h" 13753f127fSDimitry Andric #include "clang/AST/ASTContext.h" 14bdd1243dSDimitry Andric #include "clang/AST/Attr.h" 15753f127fSDimitry Andric #include "clang/AST/DeclCXX.h" 16753f127fSDimitry Andric #include "clang/Basic/AttrKinds.h" 17bdd1243dSDimitry Andric #include "clang/Basic/HLSLRuntime.h" 18bdd1243dSDimitry Andric #include "clang/Sema/Lookup.h" 19753f127fSDimitry Andric #include "clang/Sema/Sema.h" 20bdd1243dSDimitry Andric #include "llvm/Frontend/HLSL/HLSLResource.h" 21bdd1243dSDimitry Andric 22bdd1243dSDimitry Andric #include <functional> 23753f127fSDimitry Andric 24753f127fSDimitry Andric using namespace clang; 25bdd1243dSDimitry Andric using namespace llvm::hlsl; 26bdd1243dSDimitry Andric 27bdd1243dSDimitry Andric namespace { 28bdd1243dSDimitry Andric 29bdd1243dSDimitry Andric struct TemplateParameterListBuilder; 30bdd1243dSDimitry Andric 31bdd1243dSDimitry Andric struct BuiltinTypeDeclBuilder { 32bdd1243dSDimitry Andric CXXRecordDecl *Record = nullptr; 33bdd1243dSDimitry Andric ClassTemplateDecl *Template = nullptr; 34bdd1243dSDimitry Andric ClassTemplateDecl *PrevTemplate = nullptr; 35bdd1243dSDimitry Andric NamespaceDecl *HLSLNamespace = nullptr; 36bdd1243dSDimitry Andric llvm::StringMap<FieldDecl *> Fields; 37bdd1243dSDimitry Andric 38bdd1243dSDimitry Andric BuiltinTypeDeclBuilder(CXXRecordDecl *R) : Record(R) { 39bdd1243dSDimitry Andric Record->startDefinition(); 40bdd1243dSDimitry Andric Template = Record->getDescribedClassTemplate(); 41bdd1243dSDimitry Andric } 42bdd1243dSDimitry Andric 43bdd1243dSDimitry Andric BuiltinTypeDeclBuilder(Sema &S, NamespaceDecl *Namespace, StringRef Name) 44bdd1243dSDimitry Andric : HLSLNamespace(Namespace) { 45bdd1243dSDimitry Andric ASTContext &AST = S.getASTContext(); 46bdd1243dSDimitry Andric IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier); 47bdd1243dSDimitry Andric 48bdd1243dSDimitry Andric LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName); 49bdd1243dSDimitry Andric CXXRecordDecl *PrevDecl = nullptr; 50bdd1243dSDimitry Andric if (S.LookupQualifiedName(Result, HLSLNamespace)) { 51bdd1243dSDimitry Andric NamedDecl *Found = Result.getFoundDecl(); 52bdd1243dSDimitry Andric if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) { 53bdd1243dSDimitry Andric PrevDecl = TD->getTemplatedDecl(); 54bdd1243dSDimitry Andric PrevTemplate = TD; 55bdd1243dSDimitry Andric } else 56bdd1243dSDimitry Andric PrevDecl = dyn_cast<CXXRecordDecl>(Found); 57bdd1243dSDimitry Andric assert(PrevDecl && "Unexpected lookup result type."); 58bdd1243dSDimitry Andric } 59bdd1243dSDimitry Andric 60bdd1243dSDimitry Andric if (PrevDecl && PrevDecl->isCompleteDefinition()) { 61bdd1243dSDimitry Andric Record = PrevDecl; 62bdd1243dSDimitry Andric return; 63bdd1243dSDimitry Andric } 64bdd1243dSDimitry Andric 65bdd1243dSDimitry Andric Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::TTK_Class, 66bdd1243dSDimitry Andric HLSLNamespace, SourceLocation(), 67bdd1243dSDimitry Andric SourceLocation(), &II, PrevDecl, true); 68bdd1243dSDimitry Andric Record->setImplicit(true); 69bdd1243dSDimitry Andric Record->setLexicalDeclContext(HLSLNamespace); 70bdd1243dSDimitry Andric Record->setHasExternalLexicalStorage(); 71bdd1243dSDimitry Andric 72bdd1243dSDimitry Andric // Don't let anyone derive from built-in types. 73bdd1243dSDimitry Andric Record->addAttr(FinalAttr::CreateImplicit(AST, SourceRange(), 74bdd1243dSDimitry Andric FinalAttr::Keyword_final)); 75bdd1243dSDimitry Andric } 76bdd1243dSDimitry Andric 77bdd1243dSDimitry Andric ~BuiltinTypeDeclBuilder() { 78bdd1243dSDimitry Andric if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace) 79bdd1243dSDimitry Andric HLSLNamespace->addDecl(Record); 80bdd1243dSDimitry Andric } 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric BuiltinTypeDeclBuilder & 83bdd1243dSDimitry Andric addMemberVariable(StringRef Name, QualType Type, 84bdd1243dSDimitry Andric AccessSpecifier Access = AccessSpecifier::AS_private) { 85bdd1243dSDimitry Andric if (Record->isCompleteDefinition()) 86bdd1243dSDimitry Andric return *this; 87bdd1243dSDimitry Andric assert(Record->isBeingDefined() && 88bdd1243dSDimitry Andric "Definition must be started before adding members!"); 89bdd1243dSDimitry Andric ASTContext &AST = Record->getASTContext(); 90bdd1243dSDimitry Andric 91bdd1243dSDimitry Andric IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier); 92bdd1243dSDimitry Andric TypeSourceInfo *MemTySource = 93bdd1243dSDimitry Andric AST.getTrivialTypeSourceInfo(Type, SourceLocation()); 94bdd1243dSDimitry Andric auto *Field = FieldDecl::Create( 95bdd1243dSDimitry Andric AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource, 96bdd1243dSDimitry Andric nullptr, false, InClassInitStyle::ICIS_NoInit); 97bdd1243dSDimitry Andric Field->setAccess(Access); 98bdd1243dSDimitry Andric Field->setImplicit(true); 99bdd1243dSDimitry Andric Record->addDecl(Field); 100bdd1243dSDimitry Andric Fields[Name] = Field; 101bdd1243dSDimitry Andric return *this; 102bdd1243dSDimitry Andric } 103bdd1243dSDimitry Andric 104bdd1243dSDimitry Andric BuiltinTypeDeclBuilder & 105bdd1243dSDimitry Andric addHandleMember(AccessSpecifier Access = AccessSpecifier::AS_private) { 106bdd1243dSDimitry Andric if (Record->isCompleteDefinition()) 107bdd1243dSDimitry Andric return *this; 108bdd1243dSDimitry Andric QualType Ty = Record->getASTContext().VoidPtrTy; 109bdd1243dSDimitry Andric if (Template) { 110bdd1243dSDimitry Andric if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>( 111bdd1243dSDimitry Andric Template->getTemplateParameters()->getParam(0))) 112bdd1243dSDimitry Andric Ty = Record->getASTContext().getPointerType( 113bdd1243dSDimitry Andric QualType(TTD->getTypeForDecl(), 0)); 114bdd1243dSDimitry Andric } 115bdd1243dSDimitry Andric return addMemberVariable("h", Ty, Access); 116bdd1243dSDimitry Andric } 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric BuiltinTypeDeclBuilder & 119bdd1243dSDimitry Andric annotateResourceClass(HLSLResourceAttr::ResourceClass RC, 120bdd1243dSDimitry Andric HLSLResourceAttr::ResourceKind RK) { 121bdd1243dSDimitry Andric if (Record->isCompleteDefinition()) 122bdd1243dSDimitry Andric return *this; 123bdd1243dSDimitry Andric Record->addAttr( 124bdd1243dSDimitry Andric HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RC, RK)); 125bdd1243dSDimitry Andric return *this; 126bdd1243dSDimitry Andric } 127bdd1243dSDimitry Andric 128bdd1243dSDimitry Andric static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S, 129bdd1243dSDimitry Andric StringRef Name) { 130bdd1243dSDimitry Andric CXXScopeSpec SS; 131bdd1243dSDimitry Andric IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier); 132bdd1243dSDimitry Andric DeclarationNameInfo NameInfo = 133bdd1243dSDimitry Andric DeclarationNameInfo(DeclarationName(&II), SourceLocation()); 134bdd1243dSDimitry Andric LookupResult R(S, NameInfo, Sema::LookupOrdinaryName); 135bdd1243dSDimitry Andric S.LookupParsedName(R, S.getCurScope(), &SS, false); 136bdd1243dSDimitry Andric assert(R.isSingleResult() && 137bdd1243dSDimitry Andric "Since this is a builtin it should always resolve!"); 138bdd1243dSDimitry Andric auto *VD = cast<ValueDecl>(R.getFoundDecl()); 139bdd1243dSDimitry Andric QualType Ty = VD->getType(); 140bdd1243dSDimitry Andric return DeclRefExpr::Create(AST, NestedNameSpecifierLoc(), SourceLocation(), 141bdd1243dSDimitry Andric VD, false, NameInfo, Ty, VK_PRValue); 142bdd1243dSDimitry Andric } 143bdd1243dSDimitry Andric 144bdd1243dSDimitry Andric static Expr *emitResourceClassExpr(ASTContext &AST, ResourceClass RC) { 145bdd1243dSDimitry Andric return IntegerLiteral::Create( 146bdd1243dSDimitry Andric AST, 147bdd1243dSDimitry Andric llvm::APInt(AST.getIntWidth(AST.UnsignedCharTy), 148bdd1243dSDimitry Andric static_cast<uint8_t>(RC)), 149bdd1243dSDimitry Andric AST.UnsignedCharTy, SourceLocation()); 150bdd1243dSDimitry Andric } 151bdd1243dSDimitry Andric 152bdd1243dSDimitry Andric BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S, 153bdd1243dSDimitry Andric ResourceClass RC) { 154bdd1243dSDimitry Andric if (Record->isCompleteDefinition()) 155bdd1243dSDimitry Andric return *this; 156bdd1243dSDimitry Andric ASTContext &AST = Record->getASTContext(); 157bdd1243dSDimitry Andric 158bdd1243dSDimitry Andric QualType ConstructorType = 159bdd1243dSDimitry Andric AST.getFunctionType(AST.VoidTy, {}, FunctionProtoType::ExtProtoInfo()); 160bdd1243dSDimitry Andric 161bdd1243dSDimitry Andric CanQualType CanTy = Record->getTypeForDecl()->getCanonicalTypeUnqualified(); 162bdd1243dSDimitry Andric DeclarationName Name = AST.DeclarationNames.getCXXConstructorName(CanTy); 163bdd1243dSDimitry Andric CXXConstructorDecl *Constructor = CXXConstructorDecl::Create( 164bdd1243dSDimitry Andric AST, Record, SourceLocation(), 165bdd1243dSDimitry Andric DeclarationNameInfo(Name, SourceLocation()), ConstructorType, 166bdd1243dSDimitry Andric AST.getTrivialTypeSourceInfo(ConstructorType, SourceLocation()), 167bdd1243dSDimitry Andric ExplicitSpecifier(), false, true, false, 168bdd1243dSDimitry Andric ConstexprSpecKind::Unspecified); 169bdd1243dSDimitry Andric 170bdd1243dSDimitry Andric DeclRefExpr *Fn = 171bdd1243dSDimitry Andric lookupBuiltinFunction(AST, S, "__builtin_hlsl_create_handle"); 172bdd1243dSDimitry Andric 173bdd1243dSDimitry Andric Expr *RCExpr = emitResourceClassExpr(AST, RC); 174bdd1243dSDimitry Andric Expr *Call = CallExpr::Create(AST, Fn, {RCExpr}, AST.VoidPtrTy, VK_PRValue, 175bdd1243dSDimitry Andric SourceLocation(), FPOptionsOverride()); 176bdd1243dSDimitry Andric 177bdd1243dSDimitry Andric CXXThisExpr *This = new (AST) CXXThisExpr( 178bdd1243dSDimitry Andric SourceLocation(), 179bdd1243dSDimitry Andric Constructor->getThisType().getTypePtr()->getPointeeType(), true); 180bdd1243dSDimitry Andric This->setValueKind(ExprValueKind::VK_LValue); 181bdd1243dSDimitry Andric Expr *Handle = MemberExpr::CreateImplicit(AST, This, false, Fields["h"], 182bdd1243dSDimitry Andric Fields["h"]->getType(), VK_LValue, 183bdd1243dSDimitry Andric OK_Ordinary); 184bdd1243dSDimitry Andric 185bdd1243dSDimitry Andric // If the handle isn't a void pointer, cast the builtin result to the 186bdd1243dSDimitry Andric // correct type. 187bdd1243dSDimitry Andric if (Handle->getType().getCanonicalType() != AST.VoidPtrTy) { 188bdd1243dSDimitry Andric Call = CXXStaticCastExpr::Create( 189bdd1243dSDimitry Andric AST, Handle->getType(), VK_PRValue, CK_Dependent, Call, nullptr, 190bdd1243dSDimitry Andric AST.getTrivialTypeSourceInfo(Handle->getType(), SourceLocation()), 191bdd1243dSDimitry Andric FPOptionsOverride(), SourceLocation(), SourceLocation(), 192bdd1243dSDimitry Andric SourceRange()); 193bdd1243dSDimitry Andric } 194bdd1243dSDimitry Andric 195bdd1243dSDimitry Andric BinaryOperator *Assign = BinaryOperator::Create( 196bdd1243dSDimitry Andric AST, Handle, Call, BO_Assign, Handle->getType(), VK_LValue, OK_Ordinary, 197bdd1243dSDimitry Andric SourceLocation(), FPOptionsOverride()); 198bdd1243dSDimitry Andric 199bdd1243dSDimitry Andric Constructor->setBody( 200bdd1243dSDimitry Andric CompoundStmt::Create(AST, {Assign}, FPOptionsOverride(), 201bdd1243dSDimitry Andric SourceLocation(), SourceLocation())); 202bdd1243dSDimitry Andric Constructor->setAccess(AccessSpecifier::AS_public); 203bdd1243dSDimitry Andric Record->addDecl(Constructor); 204bdd1243dSDimitry Andric return *this; 205bdd1243dSDimitry Andric } 206bdd1243dSDimitry Andric 207bdd1243dSDimitry Andric BuiltinTypeDeclBuilder &addArraySubscriptOperators() { 208bdd1243dSDimitry Andric if (Record->isCompleteDefinition()) 209bdd1243dSDimitry Andric return *this; 210bdd1243dSDimitry Andric addArraySubscriptOperator(true); 211bdd1243dSDimitry Andric addArraySubscriptOperator(false); 212bdd1243dSDimitry Andric return *this; 213bdd1243dSDimitry Andric } 214bdd1243dSDimitry Andric 215bdd1243dSDimitry Andric BuiltinTypeDeclBuilder &addArraySubscriptOperator(bool IsConst) { 216bdd1243dSDimitry Andric if (Record->isCompleteDefinition()) 217bdd1243dSDimitry Andric return *this; 218bdd1243dSDimitry Andric assert(Fields.count("h") > 0 && 219bdd1243dSDimitry Andric "Subscript operator must be added after the handle."); 220bdd1243dSDimitry Andric 221bdd1243dSDimitry Andric FieldDecl *Handle = Fields["h"]; 222bdd1243dSDimitry Andric ASTContext &AST = Record->getASTContext(); 223bdd1243dSDimitry Andric 224bdd1243dSDimitry Andric assert(Handle->getType().getCanonicalType() != AST.VoidPtrTy && 225bdd1243dSDimitry Andric "Not yet supported for void pointer handles."); 226bdd1243dSDimitry Andric 227bdd1243dSDimitry Andric QualType ElemTy = 228bdd1243dSDimitry Andric QualType(Handle->getType()->getPointeeOrArrayElementType(), 0); 229bdd1243dSDimitry Andric QualType ReturnTy = ElemTy; 230bdd1243dSDimitry Andric 231bdd1243dSDimitry Andric FunctionProtoType::ExtProtoInfo ExtInfo; 232bdd1243dSDimitry Andric 233bdd1243dSDimitry Andric // Subscript operators return references to elements, const makes the 234bdd1243dSDimitry Andric // reference and method const so that the underlying data is not mutable. 235bdd1243dSDimitry Andric ReturnTy = AST.getLValueReferenceType(ReturnTy); 236bdd1243dSDimitry Andric if (IsConst) { 237bdd1243dSDimitry Andric ExtInfo.TypeQuals.addConst(); 238bdd1243dSDimitry Andric ReturnTy.addConst(); 239bdd1243dSDimitry Andric } 240bdd1243dSDimitry Andric 241bdd1243dSDimitry Andric QualType MethodTy = 242bdd1243dSDimitry Andric AST.getFunctionType(ReturnTy, {AST.UnsignedIntTy}, ExtInfo); 243bdd1243dSDimitry Andric auto *TSInfo = AST.getTrivialTypeSourceInfo(MethodTy, SourceLocation()); 244bdd1243dSDimitry Andric auto *MethodDecl = CXXMethodDecl::Create( 245bdd1243dSDimitry Andric AST, Record, SourceLocation(), 246bdd1243dSDimitry Andric DeclarationNameInfo( 247bdd1243dSDimitry Andric AST.DeclarationNames.getCXXOperatorName(OO_Subscript), 248bdd1243dSDimitry Andric SourceLocation()), 249bdd1243dSDimitry Andric MethodTy, TSInfo, SC_None, false, false, ConstexprSpecKind::Unspecified, 250bdd1243dSDimitry Andric SourceLocation()); 251bdd1243dSDimitry Andric 252bdd1243dSDimitry Andric IdentifierInfo &II = AST.Idents.get("Idx", tok::TokenKind::identifier); 253bdd1243dSDimitry Andric auto *IdxParam = ParmVarDecl::Create( 254bdd1243dSDimitry Andric AST, MethodDecl->getDeclContext(), SourceLocation(), SourceLocation(), 255bdd1243dSDimitry Andric &II, AST.UnsignedIntTy, 256bdd1243dSDimitry Andric AST.getTrivialTypeSourceInfo(AST.UnsignedIntTy, SourceLocation()), 257bdd1243dSDimitry Andric SC_None, nullptr); 258bdd1243dSDimitry Andric MethodDecl->setParams({IdxParam}); 259bdd1243dSDimitry Andric 260bdd1243dSDimitry Andric // Also add the parameter to the function prototype. 261bdd1243dSDimitry Andric auto FnProtoLoc = TSInfo->getTypeLoc().getAs<FunctionProtoTypeLoc>(); 262bdd1243dSDimitry Andric FnProtoLoc.setParam(0, IdxParam); 263bdd1243dSDimitry Andric 264bdd1243dSDimitry Andric auto *This = new (AST) CXXThisExpr( 265bdd1243dSDimitry Andric SourceLocation(), 266bdd1243dSDimitry Andric MethodDecl->getThisType().getTypePtr()->getPointeeType(), true); 267bdd1243dSDimitry Andric This->setValueKind(ExprValueKind::VK_LValue); 268bdd1243dSDimitry Andric auto *HandleAccess = MemberExpr::CreateImplicit( 269bdd1243dSDimitry Andric AST, This, false, Handle, Handle->getType(), VK_LValue, OK_Ordinary); 270bdd1243dSDimitry Andric 271bdd1243dSDimitry Andric auto *IndexExpr = DeclRefExpr::Create( 272bdd1243dSDimitry Andric AST, NestedNameSpecifierLoc(), SourceLocation(), IdxParam, false, 273bdd1243dSDimitry Andric DeclarationNameInfo(IdxParam->getDeclName(), SourceLocation()), 274bdd1243dSDimitry Andric AST.UnsignedIntTy, VK_PRValue); 275bdd1243dSDimitry Andric 276bdd1243dSDimitry Andric auto *Array = 277bdd1243dSDimitry Andric new (AST) ArraySubscriptExpr(HandleAccess, IndexExpr, ElemTy, VK_LValue, 278bdd1243dSDimitry Andric OK_Ordinary, SourceLocation()); 279bdd1243dSDimitry Andric 280bdd1243dSDimitry Andric auto *Return = ReturnStmt::Create(AST, SourceLocation(), Array, nullptr); 281bdd1243dSDimitry Andric 282bdd1243dSDimitry Andric MethodDecl->setBody(CompoundStmt::Create(AST, {Return}, FPOptionsOverride(), 283bdd1243dSDimitry Andric SourceLocation(), 284bdd1243dSDimitry Andric SourceLocation())); 285bdd1243dSDimitry Andric MethodDecl->setLexicalDeclContext(Record); 286bdd1243dSDimitry Andric MethodDecl->setAccess(AccessSpecifier::AS_public); 287bdd1243dSDimitry Andric MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit( 288*06c3fb27SDimitry Andric AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline)); 289bdd1243dSDimitry Andric Record->addDecl(MethodDecl); 290bdd1243dSDimitry Andric 291bdd1243dSDimitry Andric return *this; 292bdd1243dSDimitry Andric } 293bdd1243dSDimitry Andric 294bdd1243dSDimitry Andric BuiltinTypeDeclBuilder &startDefinition() { 295bdd1243dSDimitry Andric if (Record->isCompleteDefinition()) 296bdd1243dSDimitry Andric return *this; 297bdd1243dSDimitry Andric Record->startDefinition(); 298bdd1243dSDimitry Andric return *this; 299bdd1243dSDimitry Andric } 300bdd1243dSDimitry Andric 301bdd1243dSDimitry Andric BuiltinTypeDeclBuilder &completeDefinition() { 302bdd1243dSDimitry Andric if (Record->isCompleteDefinition()) 303bdd1243dSDimitry Andric return *this; 304bdd1243dSDimitry Andric assert(Record->isBeingDefined() && 305bdd1243dSDimitry Andric "Definition must be started before completing it."); 306bdd1243dSDimitry Andric 307bdd1243dSDimitry Andric Record->completeDefinition(); 308bdd1243dSDimitry Andric return *this; 309bdd1243dSDimitry Andric } 310bdd1243dSDimitry Andric 311bdd1243dSDimitry Andric TemplateParameterListBuilder addTemplateArgumentList(); 312bdd1243dSDimitry Andric }; 313bdd1243dSDimitry Andric 314bdd1243dSDimitry Andric struct TemplateParameterListBuilder { 315bdd1243dSDimitry Andric BuiltinTypeDeclBuilder &Builder; 316bdd1243dSDimitry Andric ASTContext &AST; 317bdd1243dSDimitry Andric llvm::SmallVector<NamedDecl *> Params; 318bdd1243dSDimitry Andric 319bdd1243dSDimitry Andric TemplateParameterListBuilder(BuiltinTypeDeclBuilder &RB) 320bdd1243dSDimitry Andric : Builder(RB), AST(RB.Record->getASTContext()) {} 321bdd1243dSDimitry Andric 322bdd1243dSDimitry Andric ~TemplateParameterListBuilder() { finalizeTemplateArgs(); } 323bdd1243dSDimitry Andric 324bdd1243dSDimitry Andric TemplateParameterListBuilder & 325bdd1243dSDimitry Andric addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) { 326bdd1243dSDimitry Andric if (Builder.Record->isCompleteDefinition()) 327bdd1243dSDimitry Andric return *this; 328bdd1243dSDimitry Andric unsigned Position = static_cast<unsigned>(Params.size()); 329bdd1243dSDimitry Andric auto *Decl = TemplateTypeParmDecl::Create( 330bdd1243dSDimitry Andric AST, Builder.Record->getDeclContext(), SourceLocation(), 331bdd1243dSDimitry Andric SourceLocation(), /* TemplateDepth */ 0, Position, 332bdd1243dSDimitry Andric &AST.Idents.get(Name, tok::TokenKind::identifier), /* Typename */ false, 333bdd1243dSDimitry Andric /* ParameterPack */ false); 334bdd1243dSDimitry Andric if (!DefaultValue.isNull()) 335bdd1243dSDimitry Andric Decl->setDefaultArgument(AST.getTrivialTypeSourceInfo(DefaultValue)); 336bdd1243dSDimitry Andric 337bdd1243dSDimitry Andric Params.emplace_back(Decl); 338bdd1243dSDimitry Andric return *this; 339bdd1243dSDimitry Andric } 340bdd1243dSDimitry Andric 341bdd1243dSDimitry Andric BuiltinTypeDeclBuilder &finalizeTemplateArgs() { 342bdd1243dSDimitry Andric if (Params.empty()) 343bdd1243dSDimitry Andric return Builder; 344bdd1243dSDimitry Andric auto *ParamList = 345bdd1243dSDimitry Andric TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(), 346bdd1243dSDimitry Andric Params, SourceLocation(), nullptr); 347bdd1243dSDimitry Andric Builder.Template = ClassTemplateDecl::Create( 348bdd1243dSDimitry Andric AST, Builder.Record->getDeclContext(), SourceLocation(), 349bdd1243dSDimitry Andric DeclarationName(Builder.Record->getIdentifier()), ParamList, 350bdd1243dSDimitry Andric Builder.Record); 351bdd1243dSDimitry Andric Builder.Record->setDescribedClassTemplate(Builder.Template); 352bdd1243dSDimitry Andric Builder.Template->setImplicit(true); 353bdd1243dSDimitry Andric Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext()); 354bdd1243dSDimitry Andric // NOTE: setPreviousDecl before addDecl so new decl replace old decl when 355bdd1243dSDimitry Andric // make visible. 356bdd1243dSDimitry Andric Builder.Template->setPreviousDecl(Builder.PrevTemplate); 357bdd1243dSDimitry Andric Builder.Record->getDeclContext()->addDecl(Builder.Template); 358bdd1243dSDimitry Andric Params.clear(); 359bdd1243dSDimitry Andric 360bdd1243dSDimitry Andric QualType T = Builder.Template->getInjectedClassNameSpecialization(); 361bdd1243dSDimitry Andric T = AST.getInjectedClassNameType(Builder.Record, T); 362bdd1243dSDimitry Andric 363bdd1243dSDimitry Andric return Builder; 364bdd1243dSDimitry Andric } 365bdd1243dSDimitry Andric }; 366bdd1243dSDimitry Andric 367bdd1243dSDimitry Andric TemplateParameterListBuilder BuiltinTypeDeclBuilder::addTemplateArgumentList() { 368bdd1243dSDimitry Andric return TemplateParameterListBuilder(*this); 369bdd1243dSDimitry Andric } 370bdd1243dSDimitry Andric } // namespace 371753f127fSDimitry Andric 372753f127fSDimitry Andric HLSLExternalSemaSource::~HLSLExternalSemaSource() {} 373753f127fSDimitry Andric 374753f127fSDimitry Andric void HLSLExternalSemaSource::InitializeSema(Sema &S) { 375753f127fSDimitry Andric SemaPtr = &S; 376753f127fSDimitry Andric ASTContext &AST = SemaPtr->getASTContext(); 377bdd1243dSDimitry Andric // If the translation unit has external storage force external decls to load. 378bdd1243dSDimitry Andric if (AST.getTranslationUnitDecl()->hasExternalLexicalStorage()) 379bdd1243dSDimitry Andric (void)AST.getTranslationUnitDecl()->decls_begin(); 380bdd1243dSDimitry Andric 381753f127fSDimitry Andric IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier); 382bdd1243dSDimitry Andric LookupResult Result(S, &HLSL, SourceLocation(), Sema::LookupNamespaceName); 383bdd1243dSDimitry Andric NamespaceDecl *PrevDecl = nullptr; 384bdd1243dSDimitry Andric if (S.LookupQualifiedName(Result, AST.getTranslationUnitDecl())) 385bdd1243dSDimitry Andric PrevDecl = Result.getAsSingle<NamespaceDecl>(); 386bdd1243dSDimitry Andric HLSLNamespace = NamespaceDecl::Create( 387bdd1243dSDimitry Andric AST, AST.getTranslationUnitDecl(), /*Inline=*/false, SourceLocation(), 388bdd1243dSDimitry Andric SourceLocation(), &HLSL, PrevDecl, /*Nested=*/false); 389753f127fSDimitry Andric HLSLNamespace->setImplicit(true); 390bdd1243dSDimitry Andric HLSLNamespace->setHasExternalLexicalStorage(); 391753f127fSDimitry Andric AST.getTranslationUnitDecl()->addDecl(HLSLNamespace); 392bdd1243dSDimitry Andric 393bdd1243dSDimitry Andric // Force external decls in the HLSL namespace to load from the PCH. 394bdd1243dSDimitry Andric (void)HLSLNamespace->getCanonicalDecl()->decls_begin(); 395bdd1243dSDimitry Andric defineTrivialHLSLTypes(); 396bdd1243dSDimitry Andric forwardDeclareHLSLTypes(); 397753f127fSDimitry Andric 398753f127fSDimitry Andric // This adds a `using namespace hlsl` directive. In DXC, we don't put HLSL's 399753f127fSDimitry Andric // built in types inside a namespace, but we are planning to change that in 400753f127fSDimitry Andric // the near future. In order to be source compatible older versions of HLSL 401753f127fSDimitry Andric // will need to implicitly use the hlsl namespace. For now in clang everything 402753f127fSDimitry Andric // will get added to the namespace, and we can remove the using directive for 403753f127fSDimitry Andric // future language versions to match HLSL's evolution. 404753f127fSDimitry Andric auto *UsingDecl = UsingDirectiveDecl::Create( 405753f127fSDimitry Andric AST, AST.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), 406753f127fSDimitry Andric NestedNameSpecifierLoc(), SourceLocation(), HLSLNamespace, 407753f127fSDimitry Andric AST.getTranslationUnitDecl()); 408753f127fSDimitry Andric 409753f127fSDimitry Andric AST.getTranslationUnitDecl()->addDecl(UsingDecl); 410753f127fSDimitry Andric } 411753f127fSDimitry Andric 412753f127fSDimitry Andric void HLSLExternalSemaSource::defineHLSLVectorAlias() { 413753f127fSDimitry Andric ASTContext &AST = SemaPtr->getASTContext(); 414753f127fSDimitry Andric 415753f127fSDimitry Andric llvm::SmallVector<NamedDecl *> TemplateParams; 416753f127fSDimitry Andric 417753f127fSDimitry Andric auto *TypeParam = TemplateTypeParmDecl::Create( 418753f127fSDimitry Andric AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 0, 419753f127fSDimitry Andric &AST.Idents.get("element", tok::TokenKind::identifier), false, false); 420753f127fSDimitry Andric TypeParam->setDefaultArgument(AST.getTrivialTypeSourceInfo(AST.FloatTy)); 421753f127fSDimitry Andric 422753f127fSDimitry Andric TemplateParams.emplace_back(TypeParam); 423753f127fSDimitry Andric 424753f127fSDimitry Andric auto *SizeParam = NonTypeTemplateParmDecl::Create( 425753f127fSDimitry Andric AST, HLSLNamespace, SourceLocation(), SourceLocation(), 0, 1, 426753f127fSDimitry Andric &AST.Idents.get("element_count", tok::TokenKind::identifier), AST.IntTy, 427753f127fSDimitry Andric false, AST.getTrivialTypeSourceInfo(AST.IntTy)); 428753f127fSDimitry Andric Expr *LiteralExpr = 429753f127fSDimitry Andric IntegerLiteral::Create(AST, llvm::APInt(AST.getIntWidth(AST.IntTy), 4), 430753f127fSDimitry Andric AST.IntTy, SourceLocation()); 431753f127fSDimitry Andric SizeParam->setDefaultArgument(LiteralExpr); 432753f127fSDimitry Andric TemplateParams.emplace_back(SizeParam); 433753f127fSDimitry Andric 434753f127fSDimitry Andric auto *ParamList = 435753f127fSDimitry Andric TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(), 436753f127fSDimitry Andric TemplateParams, SourceLocation(), nullptr); 437753f127fSDimitry Andric 438753f127fSDimitry Andric IdentifierInfo &II = AST.Idents.get("vector", tok::TokenKind::identifier); 439753f127fSDimitry Andric 440753f127fSDimitry Andric QualType AliasType = AST.getDependentSizedExtVectorType( 441753f127fSDimitry Andric AST.getTemplateTypeParmType(0, 0, false, TypeParam), 442753f127fSDimitry Andric DeclRefExpr::Create( 443753f127fSDimitry Andric AST, NestedNameSpecifierLoc(), SourceLocation(), SizeParam, false, 444753f127fSDimitry Andric DeclarationNameInfo(SizeParam->getDeclName(), SourceLocation()), 445753f127fSDimitry Andric AST.IntTy, VK_LValue), 446753f127fSDimitry Andric SourceLocation()); 447753f127fSDimitry Andric 448753f127fSDimitry Andric auto *Record = TypeAliasDecl::Create(AST, HLSLNamespace, SourceLocation(), 449753f127fSDimitry Andric SourceLocation(), &II, 450753f127fSDimitry Andric AST.getTrivialTypeSourceInfo(AliasType)); 451753f127fSDimitry Andric Record->setImplicit(true); 452753f127fSDimitry Andric 453753f127fSDimitry Andric auto *Template = 454753f127fSDimitry Andric TypeAliasTemplateDecl::Create(AST, HLSLNamespace, SourceLocation(), 455753f127fSDimitry Andric Record->getIdentifier(), ParamList, Record); 456753f127fSDimitry Andric 457753f127fSDimitry Andric Record->setDescribedAliasTemplate(Template); 458753f127fSDimitry Andric Template->setImplicit(true); 459753f127fSDimitry Andric Template->setLexicalDeclContext(Record->getDeclContext()); 460753f127fSDimitry Andric HLSLNamespace->addDecl(Template); 461753f127fSDimitry Andric } 462bdd1243dSDimitry Andric 463bdd1243dSDimitry Andric void HLSLExternalSemaSource::defineTrivialHLSLTypes() { 464bdd1243dSDimitry Andric defineHLSLVectorAlias(); 465bdd1243dSDimitry Andric 466bdd1243dSDimitry Andric ResourceDecl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "Resource") 467bdd1243dSDimitry Andric .startDefinition() 468bdd1243dSDimitry Andric .addHandleMember(AccessSpecifier::AS_public) 469bdd1243dSDimitry Andric .completeDefinition() 470bdd1243dSDimitry Andric .Record; 471bdd1243dSDimitry Andric } 472bdd1243dSDimitry Andric 473bdd1243dSDimitry Andric void HLSLExternalSemaSource::forwardDeclareHLSLTypes() { 474bdd1243dSDimitry Andric CXXRecordDecl *Decl; 475bdd1243dSDimitry Andric Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") 476bdd1243dSDimitry Andric .addTemplateArgumentList() 477bdd1243dSDimitry Andric .addTypeParameter("element_type", SemaPtr->getASTContext().FloatTy) 478bdd1243dSDimitry Andric .finalizeTemplateArgs() 479bdd1243dSDimitry Andric .Record; 480bdd1243dSDimitry Andric if (!Decl->isCompleteDefinition()) 481bdd1243dSDimitry Andric Completions.insert( 482bdd1243dSDimitry Andric std::make_pair(Decl->getCanonicalDecl(), 483bdd1243dSDimitry Andric std::bind(&HLSLExternalSemaSource::completeBufferType, 484bdd1243dSDimitry Andric this, std::placeholders::_1))); 485bdd1243dSDimitry Andric } 486bdd1243dSDimitry Andric 487bdd1243dSDimitry Andric void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) { 488bdd1243dSDimitry Andric if (!isa<CXXRecordDecl>(Tag)) 489bdd1243dSDimitry Andric return; 490bdd1243dSDimitry Andric auto Record = cast<CXXRecordDecl>(Tag); 491bdd1243dSDimitry Andric 492bdd1243dSDimitry Andric // If this is a specialization, we need to get the underlying templated 493bdd1243dSDimitry Andric // declaration and complete that. 494bdd1243dSDimitry Andric if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record)) 495bdd1243dSDimitry Andric Record = TDecl->getSpecializedTemplate()->getTemplatedDecl(); 496bdd1243dSDimitry Andric Record = Record->getCanonicalDecl(); 497bdd1243dSDimitry Andric auto It = Completions.find(Record); 498bdd1243dSDimitry Andric if (It == Completions.end()) 499bdd1243dSDimitry Andric return; 500bdd1243dSDimitry Andric It->second(Record); 501bdd1243dSDimitry Andric } 502bdd1243dSDimitry Andric 503bdd1243dSDimitry Andric void HLSLExternalSemaSource::completeBufferType(CXXRecordDecl *Record) { 504bdd1243dSDimitry Andric BuiltinTypeDeclBuilder(Record) 505bdd1243dSDimitry Andric .addHandleMember() 506bdd1243dSDimitry Andric .addDefaultHandleConstructor(*SemaPtr, ResourceClass::UAV) 507bdd1243dSDimitry Andric .addArraySubscriptOperators() 508bdd1243dSDimitry Andric .annotateResourceClass(HLSLResourceAttr::UAV, 509bdd1243dSDimitry Andric HLSLResourceAttr::TypedBuffer) 510bdd1243dSDimitry Andric .completeDefinition(); 511bdd1243dSDimitry Andric } 512