16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/TargetParser/Triple.h"
34 getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
47 constexpr unsigned CBufferAlign = 128;
53 unsigned FieldAlign = 32;
55 FieldAlign = CBufferAlign;
56 Size = llvm::alignTo(Size, FieldAlign);
60 if (
unsigned ElementCount = AT->getSize().getZExtValue()) {
61 unsigned ElementSize =
63 unsigned AlignedElementSize = llvm::alignTo(ElementSize, CBufferAlign);
64 Size = AlignedElementSize * (ElementCount - 1) + ElementSize;
67 unsigned ElementCount = VT->getNumElements();
68 unsigned ElementSize =
70 Size = ElementSize * ElementCount;
78 auto *BufDecl = cast<HLSLBufferDecl>(Dcl);
79 BufDecl->setRBraceLoc(RBrace);
83 bool HasPackOffset =
false;
84 bool HasNonPackOffset =
false;
85 for (
auto *Field : BufDecl->decls()) {
86 VarDecl *Var = dyn_cast<VarDecl>(Field);
89 if (Field->hasAttr<HLSLPackOffsetAttr>()) {
90 PackOffsetVec.emplace_back(Var, Field->getAttr<HLSLPackOffsetAttr>());
93 HasNonPackOffset =
true;
97 if (HasPackOffset && HasNonPackOffset)
98 Diag(BufDecl->getLocation(), diag::warn_hlsl_packoffset_mix);
104 std::sort(PackOffsetVec.begin(), PackOffsetVec.end(),
105 [](
const std::pair<VarDecl *, HLSLPackOffsetAttr *> &LHS,
106 const std::pair<VarDecl *, HLSLPackOffsetAttr *> &RHS) {
107 return LHS.second->getOffset() < RHS.second->getOffset();
110 for (
unsigned i = 0; i < PackOffsetVec.size() - 1; i++) {
111 VarDecl *Var = PackOffsetVec[i].first;
112 HLSLPackOffsetAttr *
Attr = PackOffsetVec[i].second;
115 unsigned End =
Begin + Size;
116 unsigned NextBegin = PackOffsetVec[i + 1].second->getOffset() * 32;
117 if (End > NextBegin) {
118 VarDecl *NextVar = PackOffsetVec[i + 1].first;
130 int X,
int Y,
int Z) {
131 if (HLSLNumThreadsAttr *NT = D->
getAttr<HLSLNumThreadsAttr>()) {
132 if (NT->getX() !=
X || NT->getY() != Y || NT->getZ() != Z) {
133 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
134 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
144 HLSLShaderAttr::ShaderType ShaderType) {
145 if (HLSLShaderAttr *NT = D->
getAttr<HLSLShaderAttr>()) {
146 if (NT->getType() != ShaderType) {
147 Diag(NT->getLocation(), diag::err_hlsl_attribute_param_mismatch) << AL;
148 Diag(AL.
getLoc(), diag::note_conflicting_attribute);
152 return HLSLShaderAttr::Create(
getASTContext(), ShaderType, AL);
155HLSLParamModifierAttr *
157 HLSLParamModifierAttr::Spelling Spelling) {
160 if (HLSLParamModifierAttr *PA = D->
getAttr<HLSLParamModifierAttr>()) {
161 if ((PA->isIn() && Spelling == HLSLParamModifierAttr::Keyword_out) ||
162 (PA->isOut() && Spelling == HLSLParamModifierAttr::Keyword_in)) {
163 D->
dropAttr<HLSLParamModifierAttr>();
165 return HLSLParamModifierAttr::Create(
167 HLSLParamModifierAttr::Keyword_inout);
169 Diag(AL.
getLoc(), diag::err_hlsl_duplicate_parameter_modifier) << AL;
170 Diag(PA->getLocation(), diag::note_conflicting_attribute);
183 HLSLShaderAttr::ShaderType ShaderType;
184 if (HLSLShaderAttr::ConvertStrToShaderType(
Env, ShaderType)) {
185 if (
const auto *Shader = FD->
getAttr<HLSLShaderAttr>()) {
188 if (Shader->getType() != ShaderType) {
189 Diag(Shader->getLocation(), diag::err_hlsl_entry_shader_attr_mismatch)
201 case llvm::Triple::UnknownEnvironment:
202 case llvm::Triple::Library:
205 llvm_unreachable(
"Unhandled environment in triple");
211 const auto *ShaderAttr = FD->
getAttr<HLSLShaderAttr>();
212 assert(ShaderAttr &&
"Entry point has no shader attribute");
213 HLSLShaderAttr::ShaderType ST = ShaderAttr->getType();
216 case HLSLShaderAttr::Pixel:
217 case HLSLShaderAttr::Vertex:
218 case HLSLShaderAttr::Geometry:
219 case HLSLShaderAttr::Hull:
220 case HLSLShaderAttr::Domain:
221 case HLSLShaderAttr::RayGeneration:
222 case HLSLShaderAttr::Intersection:
223 case HLSLShaderAttr::AnyHit:
224 case HLSLShaderAttr::ClosestHit:
225 case HLSLShaderAttr::Miss:
226 case HLSLShaderAttr::Callable:
227 if (
const auto *NT = FD->
getAttr<HLSLNumThreadsAttr>()) {
229 {HLSLShaderAttr::Compute,
230 HLSLShaderAttr::Amplification,
231 HLSLShaderAttr::Mesh});
236 case HLSLShaderAttr::Compute:
237 case HLSLShaderAttr::Amplification:
238 case HLSLShaderAttr::Mesh:
239 if (!FD->
hasAttr<HLSLNumThreadsAttr>()) {
241 << HLSLShaderAttr::ConvertShaderTypeToStr(ST);
254 Diag(Param->getLocation(), diag::note_previous_decl) << Param;
264 auto *ShaderAttr = EntryPoint->
getAttr<HLSLShaderAttr>();
265 assert(ShaderAttr &&
"Entry point has no shader attribute");
266 HLSLShaderAttr::ShaderType ST = ShaderAttr->getType();
268 switch (AnnotationAttr->
getKind()) {
269 case attr::HLSLSV_DispatchThreadID:
270 case attr::HLSLSV_GroupIndex:
271 if (ST == HLSLShaderAttr::Compute)
276 llvm_unreachable(
"Unknown HLSLAnnotationAttr");
281 const Attr *A, HLSLShaderAttr::ShaderType Stage,
282 std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages) {
284 llvm::transform(AllowedStages, std::back_inserter(StageStrings),
285 [](HLSLShaderAttr::ShaderType ST) {
287 HLSLShaderAttr::ConvertShaderTypeToStr(ST));
289 Diag(A->
getLoc(), diag::err_hlsl_attr_unsupported_in_stage)
290 << A << HLSLShaderAttr::ConvertShaderTypeToStr(Stage)
291 << (AllowedStages.size() != 1) << join(StageStrings,
", ");
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static unsigned calculateLegacyCbufferSize(const ASTContext &Context, QualType T)
This file declares semantic analysis for HLSL constructs.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const ConstantArrayType * getAsConstantArrayType(QualType T) const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
const TargetInfo & getTargetInfo() const
Attr - This represents one attribute.
attr::Kind getKind() const
SourceRange getRange() const
SourceLocation getLoc() const
Represents the canonical version of C arrays with a specified constant size.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Decl - This represents one declaration (or definition), e.g.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a member of a struct/union/class.
Represents a function declaration or definition.
ArrayRef< ParmVarDecl * > parameters() const
HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
static HLSLBufferDecl * Create(ASTContext &C, DeclContext *LexicalParent, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *ID, SourceLocation IDLoc, SourceLocation LBrace)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represents a parameter to a function.
A (possibly-)qualified type.
Represents a struct/union/class.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Scope - A scope is a transient data structure that is used while parsing the program.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
void CheckEntryPoint(FunctionDecl *FD)
HLSLNumThreadsAttr * mergeNumThreadsAttr(Decl *D, const AttributeCommonInfo &AL, int X, int Y, int Z)
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr)
HLSLShaderAttr * mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL, HLSLShaderAttr::ShaderType ShaderType)
void ActOnTopLevelFunction(FunctionDecl *FD)
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace)
HLSLParamModifierAttr * mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, HLSLParamModifierAttr::Spelling Spelling)
Decl * ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace)
void DiagnoseAttrStageMismatch(const Attr *A, HLSLShaderAttr::ShaderType Stage, std::initializer_list< HLSLShaderAttr::ShaderType > AllowedStages)
Sema - This implements semantic analysis and AST building for C.
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
DeclContext * getCurLexicalContext() const
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
Exposes information about the current target.
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
std::string HLSLEntry
The entry point name for HLSL shader being compiled as specified by -E.
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
const T * getAs() const
Member-template getAs<specific type>'.
Represents a variable declaration or definition.
Represents a GCC generic vector type.
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
const FunctionProtoType * T