1 //===----- SemaHLSL.h ----- 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file declares semantic analysis for HLSL constructs. 10 /// 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_SEMA_SEMAHLSL_H 14 #define LLVM_CLANG_SEMA_SEMAHLSL_H 15 16 #include "clang/AST/ASTFwd.h" 17 #include "clang/AST/Attr.h" 18 #include "clang/AST/Type.h" 19 #include "clang/AST/TypeLoc.h" 20 #include "clang/Basic/SourceLocation.h" 21 #include "clang/Sema/SemaBase.h" 22 #include "llvm/ADT/SmallVector.h" 23 #include "llvm/TargetParser/Triple.h" 24 #include <initializer_list> 25 26 namespace clang { 27 class AttributeCommonInfo; 28 class IdentifierInfo; 29 class InitializedEntity; 30 class InitializationKind; 31 class ParsedAttr; 32 class Scope; 33 class VarDecl; 34 35 namespace hlsl { 36 37 // Introduce a wrapper struct around the underlying RootElement. This structure 38 // will retain extra clang diagnostic information that is not available in llvm. 39 struct RootSignatureElement { RootSignatureElementRootSignatureElement40 RootSignatureElement(SourceLocation Loc, 41 llvm::hlsl::rootsig::RootElement Element) 42 : Loc(Loc), Element(Element) {} 43 getElementRootSignatureElement44 const llvm::hlsl::rootsig::RootElement &getElement() const { return Element; } getLocationRootSignatureElement45 const SourceLocation &getLocation() const { return Loc; } 46 47 private: 48 SourceLocation Loc; 49 llvm::hlsl::rootsig::RootElement Element; 50 }; 51 52 } // namespace hlsl 53 54 using llvm::dxil::ResourceClass; 55 56 // FIXME: This can be hidden (as static function in SemaHLSL.cpp) once we no 57 // longer need to create builtin buffer types in HLSLExternalSemaSource. 58 bool CreateHLSLAttributedResourceType( 59 Sema &S, QualType Wrapped, ArrayRef<const Attr *> AttrList, 60 QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo = nullptr); 61 62 enum class BindingType : uint8_t { NotAssigned, Explicit, Implicit }; 63 64 // DeclBindingInfo struct stores information about required/assigned resource 65 // binding onon a declaration for specific resource class. 66 struct DeclBindingInfo { 67 const VarDecl *Decl; 68 ResourceClass ResClass; 69 const HLSLResourceBindingAttr *Attr; 70 BindingType BindType; 71 72 DeclBindingInfo(const VarDecl *Decl, ResourceClass ResClass, 73 BindingType BindType = BindingType::NotAssigned, 74 const HLSLResourceBindingAttr *Attr = nullptr) DeclDeclBindingInfo75 : Decl(Decl), ResClass(ResClass), Attr(Attr), BindType(BindType) {} 76 setBindingAttributeDeclBindingInfo77 void setBindingAttribute(HLSLResourceBindingAttr *A, BindingType BT) { 78 assert(Attr == nullptr && BindType == BindingType::NotAssigned && 79 "binding attribute already assigned"); 80 Attr = A; 81 BindType = BT; 82 } 83 }; 84 85 // ResourceBindings class stores information about all resource bindings 86 // in a shader. It is used for binding diagnostics and implicit binding 87 // assigments. 88 class ResourceBindings { 89 public: 90 DeclBindingInfo *addDeclBindingInfo(const VarDecl *VD, 91 ResourceClass ResClass); 92 DeclBindingInfo *getDeclBindingInfo(const VarDecl *VD, 93 ResourceClass ResClass); 94 bool hasBindingInfoForDecl(const VarDecl *VD) const; 95 96 private: 97 // List of all resource bindings required by the shader. 98 // A global declaration can have multiple bindings for different 99 // resource classes. They are all stored sequentially in this list. 100 // The DeclToBindingListIndex hashtable maps a declaration to the 101 // index of the first binding info in the list. 102 llvm::SmallVector<DeclBindingInfo> BindingsList; 103 llvm::DenseMap<const VarDecl *, unsigned> DeclToBindingListIndex; 104 }; 105 106 class SemaHLSL : public SemaBase { 107 public: 108 SemaHLSL(Sema &S); 109 110 Decl *ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, 111 IdentifierInfo *Ident, SourceLocation IdentLoc, 112 SourceLocation LBrace); 113 void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace); 114 HLSLNumThreadsAttr *mergeNumThreadsAttr(Decl *D, 115 const AttributeCommonInfo &AL, int X, 116 int Y, int Z); 117 HLSLWaveSizeAttr *mergeWaveSizeAttr(Decl *D, const AttributeCommonInfo &AL, 118 int Min, int Max, int Preferred, 119 int SpelledArgsCount); 120 HLSLVkConstantIdAttr * 121 mergeVkConstantIdAttr(Decl *D, const AttributeCommonInfo &AL, int Id); 122 HLSLShaderAttr *mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, 123 llvm::Triple::EnvironmentType ShaderType); 124 HLSLParamModifierAttr * 125 mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, 126 HLSLParamModifierAttr::Spelling Spelling); 127 void ActOnTopLevelFunction(FunctionDecl *FD); 128 void ActOnVariableDeclarator(VarDecl *VD); 129 bool ActOnUninitializedVarDecl(VarDecl *D); 130 void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU); 131 void CheckEntryPoint(FunctionDecl *FD); 132 void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, 133 const HLSLAnnotationAttr *AnnotationAttr); 134 void DiagnoseAttrStageMismatch( 135 const Attr *A, llvm::Triple::EnvironmentType Stage, 136 std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages); 137 138 QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS, 139 QualType LHSType, QualType RHSType, 140 bool IsCompAssign); 141 void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc); 142 143 /// Computes the unique Root Signature identifier from the given signature, 144 /// then lookup if there is a previousy created Root Signature decl. 145 /// 146 /// Returns the identifier and if it was found 147 std::pair<IdentifierInfo *, bool> 148 ActOnStartRootSignatureDecl(StringRef Signature); 149 150 /// Creates the Root Signature decl of the parsed Root Signature elements 151 /// onto the AST and push it onto current Scope 152 void 153 ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, 154 ArrayRef<hlsl::RootSignatureElement> Elements); 155 156 // Returns true if any RootSignatureElement is invalid and a diagnostic was 157 // produced 158 bool 159 handleRootSignatureElements(ArrayRef<hlsl::RootSignatureElement> Elements); 160 void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL); 161 void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL); 162 void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL); 163 void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL); 164 void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL); 165 void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL); 166 void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL); 167 void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL); 168 void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL); 169 void handleShaderAttr(Decl *D, const ParsedAttr &AL); 170 void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL); 171 void handleParamModifierAttr(Decl *D, const ParsedAttr &AL); 172 bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL); 173 174 void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL); 175 176 bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); 177 QualType ProcessResourceTypeAttributes(QualType Wrapped); 178 HLSLAttributedResourceLocInfo 179 TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT); 180 181 // HLSL Type trait implementations 182 bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const; 183 bool IsTypedResourceElementCompatible(QualType T1); 184 185 bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old); 186 187 // Diagnose whether the input ID is uint/unit2/uint3 type. 188 bool diagnoseInputIDType(QualType T, const ParsedAttr &AL); 189 bool diagnosePositionType(QualType T, const ParsedAttr &AL); 190 191 bool CanPerformScalarCast(QualType SrcTy, QualType DestTy); 192 bool ContainsBitField(QualType BaseTy); 193 bool CanPerformElementwiseCast(Expr *Src, QualType DestType); 194 bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType); 195 ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg); 196 197 QualType getInoutParameterType(QualType Ty); 198 199 bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init); 200 bool handleInitialization(VarDecl *VDecl, Expr *&Init); 201 void deduceAddressSpace(VarDecl *Decl); 202 203 private: 204 // HLSL resource type attributes need to be processed all at once. 205 // This is a list to collect them. 206 llvm::SmallVector<const Attr *> HLSLResourcesTypeAttrs; 207 208 /// TypeLoc data for HLSLAttributedResourceType instances that we 209 /// have not yet populated. 210 llvm::DenseMap<const HLSLAttributedResourceType *, 211 HLSLAttributedResourceLocInfo> 212 LocsForHLSLAttributedResources; 213 214 // List of all resource bindings 215 ResourceBindings Bindings; 216 217 // Global declaration collected for the $Globals default constant 218 // buffer which will be created at the end of the translation unit. 219 llvm::SmallVector<Decl *> DefaultCBufferDecls; 220 221 uint32_t ImplicitBindingNextOrderID = 0; 222 223 private: 224 void collectResourceBindingsOnVarDecl(VarDecl *D); 225 void collectResourceBindingsOnUserRecordDecl(const VarDecl *VD, 226 const RecordType *RT); 227 void processExplicitBindingsOnDecl(VarDecl *D); 228 229 void diagnoseAvailabilityViolations(TranslationUnitDecl *TU); 230 231 bool initGlobalResourceDecl(VarDecl *VD); getNextImplicitBindingOrderID()232 uint32_t getNextImplicitBindingOrderID() { 233 return ImplicitBindingNextOrderID++; 234 } 235 }; 236 237 } // namespace clang 238 239 #endif // LLVM_CLANG_SEMA_SEMAHLSL_H 240