xref: /freebsd/contrib/llvm-project/clang/include/clang/Sema/SemaHLSL.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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