diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index e36184f232f8a..14d7caa0e16d7 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -233,19 +233,44 @@ class HLSLAnnotationAttr : public InheritableAttr { } }; -class HLSLSemanticBaseAttr : public HLSLAnnotationAttr { +class HLSLSemanticAttr : public HLSLAnnotationAttr { + unsigned SemanticIndex = 0; + LLVM_PREFERRED_TYPE(bool) + unsigned SemanticIndexable : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SemanticExplicitIndex : 1; + + Decl *TargetDecl = nullptr; + protected: - HLSLSemanticBaseAttr(ASTContext &Context, - const AttributeCommonInfo &CommonInfo, attr::Kind AK, - bool IsLateParsed, bool InheritEvenIfAlreadyPresent) + HLSLSemanticAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed, + bool InheritEvenIfAlreadyPresent, bool SemanticIndexable) : HLSLAnnotationAttr(Context, CommonInfo, AK, IsLateParsed, - InheritEvenIfAlreadyPresent) {} + InheritEvenIfAlreadyPresent) { + this->SemanticIndexable = SemanticIndexable; + this->SemanticExplicitIndex = false; + } public: + bool isSemanticIndexable() const { return SemanticIndexable; } + + void setSemanticIndex(unsigned SemanticIndex) { + this->SemanticIndex = SemanticIndex; + this->SemanticExplicitIndex = true; + } + + unsigned getSemanticIndex() const { return SemanticIndex; } + + bool isSemanticIndexExplicit() const { return SemanticExplicitIndex; } + + void setTargetDecl(Decl *D) { TargetDecl = D; } + Decl *getTargetDecl() const { return TargetDecl; } + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() >= attr::FirstHLSLSemanticBaseAttr && - A->getKind() <= attr::LastHLSLSemanticBaseAttr; + return A->getKind() >= attr::FirstHLSLSemanticAttr && + A->getKind() <= attr::LastHLSLSemanticAttr; } }; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 8dfe4bc08c48e..aac8c1f550cb2 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -783,6 +783,18 @@ class DeclOrStmtAttr : InheritableAttr; /// An attribute class for HLSL Annotations. class HLSLAnnotationAttr : InheritableAttr; +class HLSLSemanticAttr : HLSLAnnotationAttr { + bit SemanticIndexable = Indexable; + int SemanticIndex = 0; + bit SemanticExplicitIndex = 0; + + let Spellings = []; + let Subjects = SubjectList<[ParmVar, Field, Function]>; + let LangOpts = [HLSL]; + let Args = [DeclArgument, IntArgument<"SemanticIndex">, + BoolArgument<"SemanticExplicitIndex">]; +} + /// A target-specific attribute. This class is meant to be used as a mixin /// with InheritableAttr or Attr depending on the attribute's needs. class TargetSpecificAttr { @@ -5009,28 +5021,28 @@ def HLSLUnparsedSemantic : HLSLAnnotationAttr { let Documentation = [InternalOnly]; } -class HLSLSemanticBaseAttr : HLSLAnnotationAttr { - int SemanticIndex = 0; +def HLSLUserSemantic : HLSLSemanticAttr { + let Documentation = [InternalOnly]; +} - let Spellings = []; - let Subjects = SubjectList<[ParmVar, Field, Function]>; - let LangOpts = [HLSL]; +def HLSLSV_Position : HLSLSemanticAttr { + let Documentation = [HLSLSV_PositionDocs]; +} - let Args = [StringArgument<"SemanticName">, IntArgument<"SemanticIndex">]; +def HLSLSV_GroupThreadID : HLSLSemanticAttr { + let Documentation = [HLSLSV_GroupThreadIDDocs]; } -def HLSLParsedSemantic : HLSLSemanticBaseAttr { - let Spellings = []; - let Subjects = SubjectList<[ParmVar, Field, Function]>; - let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; +def HLSLSV_GroupID : HLSLSemanticAttr { + let Documentation = [HLSLSV_GroupIDDocs]; } -def HLSLAppliedSemantic : HLSLSemanticBaseAttr { - let Spellings = []; - let Subjects = SubjectList<[ParmVar, Field, Function]>; - let LangOpts = [HLSL]; - let Documentation = [InternalOnly]; +def HLSLSV_GroupIndex : HLSLSemanticAttr { + let Documentation = [HLSLSV_GroupIndexDocs]; +} + +def HLSLSV_DispatchThreadID : HLSLSemanticAttr { + let Documentation = [HLSLSV_DispatchThreadIDDocs]; } def HLSLPackOffset: HLSLAnnotationAttr { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 4813191d2d602..f1dbd8af6093a 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -8672,6 +8672,38 @@ randomized. }]; } +def HLSLSV_GroupThreadIDDocs : Documentation { + let Category = DocHLSLSemantics; + let Content = [{ +The ``SV_GroupThreadID`` semantic, when applied to an input parameter, specifies which +individual thread within a thread group is executing in. This attribute is +only supported in compute shaders. + +The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupthreadid + }]; +} + +def HLSLSV_GroupIDDocs : Documentation { + let Category = DocHLSLSemantics; + let Content = [{ +The ``SV_GroupID`` semantic, when applied to an input parameter, specifies which +thread group a shader is executing in. This attribute is only supported in compute shaders. + +The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupid + }]; +} + +def HLSLSV_GroupIndexDocs : Documentation { + let Category = DocHLSLSemantics; + let Content = [{ +The ``SV_GroupIndex`` semantic, when applied to an input parameter, specifies a +data binding to map the group index to the specified parameter. This attribute +is only supported in compute shaders. + +The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupindex + }]; +} + def HLSLResourceBindingDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -8718,6 +8750,35 @@ The full documentation is available here: https://learn.microsoft.com/en-us/wind }]; } +def HLSLSV_DispatchThreadIDDocs : Documentation { + let Category = DocHLSLSemantics; + let Content = [{ +The ``SV_DispatchThreadID`` semantic, when applied to an input parameter, +specifies a data binding to map the global thread offset within the Dispatch +call (per dimension of the group) to the specified parameter. +When applied to a field of a struct, the data binding is specified to the field +when the struct is used as a parameter type. +The semantic on the field is ignored when not used as a parameter. +This attribute is only supported in compute shaders. + +The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-dispatchthreadid + }]; +} + +def HLSLSV_PositionDocs : Documentation { + let Category = DocHLSLSemantics; + let Content = [{ +The ``SV_Position`` semantic, when applied to an input parameter in a pixel +shader, contains the location of the pixel center (x, y) in screen space. +This semantic can be applied to the parameter, or a field in a struct used +as an input parameter. +This attribute is supported as an input in pixel, hull, domain and mesh shaders. +This attribute is supported as an output in vertex, geometry and domain shaders. + +The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics + }]; +} + def HLSLGroupSharedAddressSpaceDocs : Documentation { let Category = DocCatVariable; let Content = [{ diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 86da323892f98..28b03ac4c4676 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -178,11 +178,18 @@ class SemaHLSL : public SemaBase { bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL); template - T *createSemanticAttr(const AttributeCommonInfo &ACI, + T *createSemanticAttr(const AttributeCommonInfo &ACI, NamedDecl *TargetDecl, std::optional Location) { - return ::new (getASTContext()) - T(getASTContext(), ACI, ACI.getAttrName()->getName(), - Location.value_or(0)); + T *Attr = + ::new (getASTContext()) T(getASTContext(), ACI, TargetDecl, + Location.value_or(0), Location.has_value()); + + if (!Attr->isSemanticIndexable() && Location.has_value()) { + Diag(Attr->getLocation(), diag::err_hlsl_semantic_indexing_not_supported) + << Attr->getAttrName()->getName(); + return nullptr; + } + return Attr; } void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, @@ -240,7 +247,7 @@ class SemaHLSL : public SemaBase { IdentifierInfo *RootSigOverrideIdent = nullptr; struct SemanticInfo { - HLSLParsedSemanticAttr *Semantic; + HLSLSemanticAttr *Semantic; std::optional Index; }; @@ -250,14 +257,14 @@ class SemaHLSL : public SemaBase { const RecordType *RT); void checkSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, - const HLSLAppliedSemanticAttr *SemanticAttr); - bool determineActiveSemanticOnScalar(FunctionDecl *FD, - DeclaratorDecl *OutputDecl, - DeclaratorDecl *D, + const HLSLSemanticAttr *SemanticAttr); + HLSLSemanticAttr *createSemantic(const SemanticInfo &Semantic, + DeclaratorDecl *TargetDecl); + bool determineActiveSemanticOnScalar(FunctionDecl *FD, DeclaratorDecl *D, SemanticInfo &ActiveSemantic, llvm::StringSet<> &ActiveInputSemantics); - bool determineActiveSemantic(FunctionDecl *FD, DeclaratorDecl *OutputDecl, - DeclaratorDecl *D, SemanticInfo &ActiveSemantic, + bool determineActiveSemantic(FunctionDecl *FD, DeclaratorDecl *D, + SemanticInfo &ActiveSemantic, llvm::StringSet<> &ActiveInputSemantics); void processExplicitBindingsOnDecl(VarDecl *D); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index ec02096787c7a..4bdba9b3da502 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -573,7 +573,7 @@ static llvm::Value *createSPIRVLocationLoad(IRBuilder<> &B, llvm::Module &M, llvm::Value * CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, - HLSLAppliedSemanticAttr *Semantic, + HLSLSemanticAttr *Semantic, std::optional Index) { Twine BaseName = Twine(Semantic->getAttrName()->getName()); Twine VariableName = BaseName.concat(Twine(Index.value_or(0))); @@ -591,7 +591,7 @@ CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, llvm::Value * CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, - HLSLAppliedSemanticAttr *Semantic, + HLSLSemanticAttr *Semantic, std::optional Index) { Twine BaseName = Twine(Semantic->getAttrName()->getName()); Twine VariableName = BaseName.concat(Twine(Index.value_or(0))); @@ -611,7 +611,7 @@ CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, llvm::Value *CGHLSLRuntime::emitUserSemanticLoad( IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, - HLSLAppliedSemanticAttr *Semantic, std::optional Index) { + HLSLSemanticAttr *Semantic, std::optional Index) { if (CGM.getTarget().getTriple().isSPIRV()) return emitSPIRVUserSemanticLoad(B, Type, Semantic, Index); @@ -623,16 +623,14 @@ llvm::Value *CGHLSLRuntime::emitUserSemanticLoad( llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad( IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, - HLSLAppliedSemanticAttr *Semantic, std::optional Index) { - - std::string SemanticName = Semantic->getAttrName()->getName().upper(); - if (SemanticName == "SV_GROUPINDEX") { + Attr *Semantic, std::optional Index) { + if (isa(Semantic)) { llvm::Function *GroupIndex = CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic()); return B.CreateCall(FunctionCallee(GroupIndex)); } - if (SemanticName == "SV_DISPATCHTHREADID") { + if (isa(Semantic)) { llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic(); llvm::Function *ThreadIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) @@ -641,7 +639,7 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad( return buildVectorInput(B, ThreadIDIntrinsic, Type); } - if (SemanticName == "SV_GROUPTHREADID") { + if (isa(Semantic)) { llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic(); llvm::Function *GroupThreadIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) @@ -650,7 +648,7 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad( return buildVectorInput(B, GroupThreadIDIntrinsic, Type); } - if (SemanticName == "SV_GROUPID") { + if (isa(Semantic)) { llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic(); llvm::Function *GroupIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) @@ -659,32 +657,44 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad( return buildVectorInput(B, GroupIDIntrinsic, Type); } - if (SemanticName == "SV_POSITION") { + if (HLSLSV_PositionAttr *S = dyn_cast(Semantic)) { if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel) return createSPIRVBuiltinLoad(B, CGM.getModule(), Type, - Semantic->getAttrName()->getName(), + S->getAttrName()->getName(), /* BuiltIn::FragCoord */ 15); } llvm_unreachable("non-handled system semantic. FIXME."); } -llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad( - IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) { +llvm::Value * +CGHLSLRuntime::handleScalarSemanticLoad(IRBuilder<> &B, const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl) { + + HLSLSemanticAttr *Semantic = nullptr; + for (HLSLSemanticAttr *Item : FD->specific_attrs()) { + if (Item->getTargetDecl() == Decl) { + Semantic = Item; + break; + } + } + // Sema must create one attribute per scalar field. + assert(Semantic); + + std::optional Index = std::nullopt; + if (Semantic->isSemanticIndexExplicit()) + Index = Semantic->getSemanticIndex(); - std::optional Index = Semantic->getSemanticIndex(); - if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_")) - return emitSystemSemanticLoad(B, Type, Decl, Semantic, Index); - return emitUserSemanticLoad(B, Type, Decl, Semantic, Index); + if (isa(Semantic)) + return emitUserSemanticLoad(B, Type, Decl, Semantic, Index); + return emitSystemSemanticLoad(B, Type, Decl, Semantic, Index); } -std::pair> -CGHLSLRuntime::handleStructSemanticLoad( - IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - specific_attr_iterator AttrBegin, - specific_attr_iterator AttrEnd) { +llvm::Value * +CGHLSLRuntime::handleStructSemanticLoad(IRBuilder<> &B, const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl) { const llvm::StructType *ST = cast(Type); const clang::RecordDecl *RD = Decl->getType()->getAsRecordDecl(); @@ -694,31 +704,23 @@ CGHLSLRuntime::handleStructSemanticLoad( llvm::Value *Aggregate = llvm::PoisonValue::get(Type); auto FieldDecl = RD->field_begin(); for (unsigned I = 0; I < ST->getNumElements(); ++I) { - auto [ChildValue, NextAttr] = handleSemanticLoad( - B, FD, ST->getElementType(I), *FieldDecl, AttrBegin, AttrEnd); - AttrBegin = NextAttr; + llvm::Value *ChildValue = + handleSemanticLoad(B, FD, ST->getElementType(I), *FieldDecl); assert(ChildValue); Aggregate = B.CreateInsertValue(Aggregate, ChildValue, I); ++FieldDecl; } - return std::make_pair(Aggregate, AttrBegin); + return Aggregate; } -std::pair> -CGHLSLRuntime::handleSemanticLoad( - IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - specific_attr_iterator AttrBegin, - specific_attr_iterator AttrEnd) { - assert(AttrBegin != AttrEnd); +llvm::Value * +CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl) { if (Type->isStructTy()) - return handleStructSemanticLoad(B, FD, Type, Decl, AttrBegin, AttrEnd); - - HLSLAppliedSemanticAttr *Attr = *AttrBegin; - ++AttrBegin; - return std::make_pair(handleScalarSemanticLoad(B, FD, Type, Decl, Attr), - AttrBegin); + return handleStructSemanticLoad(B, FD, Type, Decl); + return handleScalarSemanticLoad(B, FD, Type, Decl); } void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, @@ -772,11 +774,7 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, } else { llvm::Type *ParamType = Param.hasByValAttr() ? Param.getParamByValType() : Param.getType(); - auto AttrBegin = PD->specific_attr_begin(); - auto AttrEnd = PD->specific_attr_end(); - auto Result = - handleSemanticLoad(B, FD, ParamType, PD, AttrBegin, AttrEnd); - SemanticValue = Result.first; + SemanticValue = handleSemanticLoad(B, FD, ParamType, PD); if (!SemanticValue) return; if (Param.hasByValAttr()) { diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 48935584f28a2..488a322ca7569 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -173,27 +173,22 @@ class CGHLSLRuntime { llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, - HLSLAppliedSemanticAttr *Semantic, + Attr *Semantic, std::optional Index); llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - HLSLAppliedSemanticAttr *Semantic); - - std::pair> - handleStructSemanticLoad( - llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type, - const clang::DeclaratorDecl *Decl, - specific_attr_iterator begin, - specific_attr_iterator end); - - std::pair> - handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, - llvm::Type *Type, const clang::DeclaratorDecl *Decl, - specific_attr_iterator begin, - specific_attr_iterator end); + const clang::DeclaratorDecl *Decl); + + llvm::Value *handleStructSemanticLoad(llvm::IRBuilder<> &B, + const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl); + + llvm::Value *handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD, + llvm::Type *Type, + const clang::DeclaratorDecl *Decl); public: CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {} @@ -239,14 +234,14 @@ class CGHLSLRuntime { HLSLResourceBindingAttr *RBA); llvm::Value *emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, - HLSLAppliedSemanticAttr *Semantic, + HLSLSemanticAttr *Semantic, std::optional Index); llvm::Value *emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, - HLSLAppliedSemanticAttr *Semantic, + HLSLSemanticAttr *Semantic, std::optional Index); llvm::Value *emitUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl, - HLSLAppliedSemanticAttr *Semantic, + HLSLSemanticAttr *Semantic, std::optional Index); llvm::Triple::ArchType getArch(); diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 21eea5569a3eb..e95fe16e6cb6c 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -771,12 +771,44 @@ void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) { } } +HLSLSemanticAttr *SemaHLSL::createSemantic(const SemanticInfo &Info, + DeclaratorDecl *TargetDecl) { + std::string SemanticName = Info.Semantic->getAttrName()->getName().upper(); + + if (dyn_cast(Info.Semantic)) + return createSemanticAttr(*Info.Semantic, TargetDecl, + Info.Index); + + if (SemanticName == "SV_DISPATCHTHREADID") { + return createSemanticAttr( + *Info.Semantic, TargetDecl, Info.Index); + } else if (SemanticName == "SV_GROUPINDEX") { + return createSemanticAttr(*Info.Semantic, TargetDecl, + Info.Index); + } else if (SemanticName == "SV_GROUPTHREADID") { + return createSemanticAttr(*Info.Semantic, + TargetDecl, Info.Index); + } else if (SemanticName == "SV_GROUPID") { + return createSemanticAttr(*Info.Semantic, TargetDecl, + Info.Index); + } else if (SemanticName == "SV_POSITION") { + return createSemanticAttr(*Info.Semantic, TargetDecl, + Info.Index); + } else + Diag(Info.Semantic->getLoc(), diag::err_hlsl_unknown_semantic) + << *Info.Semantic; + + return nullptr; +} + bool SemaHLSL::determineActiveSemanticOnScalar( - FunctionDecl *FD, DeclaratorDecl *OutputDecl, DeclaratorDecl *D, - SemanticInfo &ActiveSemantic, llvm::StringSet<> &ActiveInputSemantics) { + FunctionDecl *FD, DeclaratorDecl *D, SemanticInfo &ActiveSemantic, + llvm::StringSet<> &ActiveInputSemantics) { + if (ActiveSemantic.Semantic == nullptr) { - ActiveSemantic.Semantic = D->getAttr(); - if (ActiveSemantic.Semantic) + ActiveSemantic.Semantic = D->getAttr(); + if (ActiveSemantic.Semantic && + ActiveSemantic.Semantic->isSemanticIndexExplicit()) ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex(); } @@ -785,15 +817,12 @@ bool SemaHLSL::determineActiveSemanticOnScalar( return false; } - auto *A = ::new (getASTContext()) - HLSLAppliedSemanticAttr(getASTContext(), *ActiveSemantic.Semantic, - ActiveSemantic.Semantic->getAttrName()->getName(), - ActiveSemantic.Index.value_or(0)); + auto *A = createSemantic(ActiveSemantic, D); if (!A) return false; checkSemanticAnnotation(FD, D, A); - OutputDecl->addAttr(A); + FD->addAttr(A); unsigned Location = ActiveSemantic.Index.value_or(0); @@ -817,25 +846,25 @@ bool SemaHLSL::determineActiveSemanticOnScalar( } bool SemaHLSL::determineActiveSemantic( - FunctionDecl *FD, DeclaratorDecl *OutputDecl, DeclaratorDecl *D, - SemanticInfo &ActiveSemantic, llvm::StringSet<> &ActiveInputSemantics) { + FunctionDecl *FD, DeclaratorDecl *D, SemanticInfo &ActiveSemantic, + llvm::StringSet<> &ActiveInputSemantics) { if (ActiveSemantic.Semantic == nullptr) { - ActiveSemantic.Semantic = D->getAttr(); - if (ActiveSemantic.Semantic) + ActiveSemantic.Semantic = D->getAttr(); + if (ActiveSemantic.Semantic && + ActiveSemantic.Semantic->isSemanticIndexExplicit()) ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex(); } const Type *T = D->getType()->getUnqualifiedDesugaredType(); const RecordType *RT = dyn_cast(T); if (!RT) - return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic, + return determineActiveSemanticOnScalar(FD, D, ActiveSemantic, ActiveInputSemantics); const RecordDecl *RD = RT->getDecl(); for (FieldDecl *Field : RD->fields()) { SemanticInfo Info = ActiveSemantic; - if (!determineActiveSemantic(FD, OutputDecl, Field, Info, - ActiveInputSemantics)) { + if (!determineActiveSemantic(FD, Field, Info, ActiveInputSemantics)) { Diag(Field->getLocation(), diag::note_hlsl_semantic_used_here) << Field; return false; } @@ -911,11 +940,10 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { llvm::StringSet<> ActiveInputSemantics; for (ParmVarDecl *Param : FD->parameters()) { SemanticInfo ActiveSemantic; - ActiveSemantic.Semantic = Param->getAttr(); - if (ActiveSemantic.Semantic) - ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex(); + ActiveSemantic.Semantic = nullptr; + ActiveSemantic.Index = std::nullopt; - if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic, + if (!determineActiveSemantic(FD, Param, ActiveSemantic, ActiveInputSemantics)) { Diag(Param->getLocation(), diag::note_previous_decl) << Param; FD->setInvalidDecl(); @@ -924,43 +952,34 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { // FIXME: Verify return type semantic annotation. } -void SemaHLSL::checkSemanticAnnotation( - FunctionDecl *EntryPoint, const Decl *Param, - const HLSLAppliedSemanticAttr *SemanticAttr) { +void SemaHLSL::checkSemanticAnnotation(FunctionDecl *EntryPoint, + const Decl *Param, + const HLSLSemanticAttr *SemanticAttr) { auto *ShaderAttr = EntryPoint->getAttr(); assert(ShaderAttr && "Entry point has no shader attribute"); llvm::Triple::EnvironmentType ST = ShaderAttr->getType(); - auto SemanticName = SemanticAttr->getSemanticName().upper(); - if (SemanticName == "SV_DISPATCHTHREADID" || - SemanticName == "SV_GROUPINDEX" || SemanticName == "SV_GROUPTHREADID" || - SemanticName == "SV_GROUPID") { - - if (ST != llvm::Triple::Compute) - DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Compute}); - - if (SemanticAttr->getSemanticIndex() != 0) { - Twine PrettyName = "'" + SemanticAttr->getSemanticName() + "'"; - Diag(SemanticAttr->getLoc(), - diag::err_hlsl_semantic_indexing_not_supported) - << PrettyName.str(); - } - return; - } - - if (SemanticName == "SV_POSITION") { + switch (SemanticAttr->getKind()) { + case attr::HLSLSV_DispatchThreadID: + case attr::HLSLSV_GroupIndex: + case attr::HLSLSV_GroupThreadID: + case attr::HLSLSV_GroupID: + if (ST == llvm::Triple::Compute) + return; + DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Compute}); + break; + case attr::HLSLSV_Position: // TODO(#143523): allow use on other shader types & output once the overall // semantic logic is implemented. if (ST == llvm::Triple::Pixel) return; DiagnoseAttrStageMismatch(SemanticAttr, ST, {llvm::Triple::Pixel}); + break; + case attr::HLSLUserSemantic: return; - } - - // FIXME: catch-all for non-implemented system semantics reaching this - // location. - if (SemanticAttr->getAttrName()->getName().starts_with_insensitive("SV_")) + default: llvm_unreachable("Unknown SemanticAttr"); + } } void SemaHLSL::DiagnoseAttrStageMismatch( @@ -1729,56 +1748,41 @@ void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, } } + Attr *Attribute = nullptr; if (SemanticName == "SV_DISPATCHTHREADID") { diagnoseInputIDType(ValueType, AL); if (IsOutput) Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; - if (Index.has_value()) - Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL; - D->addAttr(createSemanticAttr(AL, Index)); - return; - } - - if (SemanticName == "SV_GROUPINDEX") { + Attribute = + createSemanticAttr(AL, nullptr, Index); + } else if (SemanticName == "SV_GROUPINDEX") { if (IsOutput) Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; - if (Index.has_value()) - Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL; - D->addAttr(createSemanticAttr(AL, Index)); - return; - } - - if (SemanticName == "SV_GROUPTHREADID") { + Attribute = createSemanticAttr(AL, nullptr, Index); + } else if (SemanticName == "SV_GROUPTHREADID") { diagnoseInputIDType(ValueType, AL); if (IsOutput) Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; - if (Index.has_value()) - Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL; - D->addAttr(createSemanticAttr(AL, Index)); - return; - } - - if (SemanticName == "SV_GROUPID") { + Attribute = + createSemanticAttr(AL, nullptr, Index); + } else if (SemanticName == "SV_GROUPID") { diagnoseInputIDType(ValueType, AL); if (IsOutput) Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; - if (Index.has_value()) - Diag(AL.getLoc(), diag::err_hlsl_semantic_indexing_not_supported) << AL; - D->addAttr(createSemanticAttr(AL, Index)); - return; - } - - if (SemanticName == "SV_POSITION") { + Attribute = createSemanticAttr(AL, nullptr, Index); + } else if (SemanticName == "SV_POSITION") { const auto *VT = ValueType->getAs(); if (!ValueType->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type) << AL << "float/float1/float2/float3/float4"; - D->addAttr(createSemanticAttr(AL, Index)); - return; - } + Attribute = createSemanticAttr(AL, nullptr, Index); + } else + Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL; - Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL; + if (!Attribute) + return; + D->addAttr(Attribute); } void SemaHLSL::handleSemanticAttr(Decl *D, const ParsedAttr &AL) { @@ -1792,7 +1796,7 @@ void SemaHLSL::handleSemanticAttr(Decl *D, const ParsedAttr &AL) { if (AL.getAttrName()->getName().starts_with_insensitive("SV_")) diagnoseSystemSemanticAttr(D, AL, Index); else - D->addAttr(createSemanticAttr(AL, Index)); + D->addAttr(createSemanticAttr(AL, nullptr, Index)); } void SemaHLSL::handlePackOffsetAttr(Decl *D, const ParsedAttr &AL) { diff --git a/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl index b41bb0b0e8995..9ed545762ec94 100644 --- a/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl +++ b/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl @@ -4,5 +4,5 @@ [shader("compute")] [numthreads(8,8,1)] void foo(uint Idx : SV_DispatchThreadID1) { - // expected-error@-1 {{semantic 'SV_DispatchThreadID' does not allow indexing}} + // expected-error@-1 {{semantic SV_DispatchThreadID does not allow indexing}} } diff --git a/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl index 795e880fba0fd..8fa0b07a36027 100644 --- a/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl +++ b/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl @@ -4,11 +4,6 @@ [shader("compute")] [numthreads(8,8,1)] void foo(uint Idx : SV_GroupID1) { - // expected-error@-1 {{semantic 'SV_GroupID' does not allow indexing}} + // expected-error@-1 {{semantic SV_GroupID does not allow indexing}} } -[shader("compute")] -[numthreads(8,8,1)] -void bar(uint Idx : SV_GROUPID1) { - // expected-error@-1 {{semantic 'SV_GROUPID' does not allow indexing}} -} diff --git a/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl b/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl index 1fd5ae4ff488e..da72e85d2600e 100644 --- a/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl +++ b/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl @@ -4,5 +4,5 @@ [shader("compute")] [numthreads(8,8,1)] void foo(uint Idx : SV_GroupThreadID1) { - // expected-error@-1 {{semantic 'SV_GroupThreadID' does not allow indexing}} + // expected-error@-1 {{semantic SV_GroupThreadID does not allow indexing}} } diff --git a/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl index f57ac607db5bd..b2cb3dad9f0ce 100644 --- a/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl +++ b/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl @@ -13,14 +13,14 @@ struct S0 { // CHECK: define void @main0() // CHECK-DXIL: %A0 = call [2 x <4 x float>] @llvm.dx.load.input.a2v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison) -// CHECK-DXIL: %[[#TMP0:]] = insertvalue %struct.S0 poison, [2 x <4 x float>] %A0, 0 -// CHECK-DXIL: %A2 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison) -// CHECK-DXIL: %[[#TMP1:]] = insertvalue %struct.S0 %[[#TMP0]], <4 x float> %A2, 1 +// CHECK-DXIL: %[[#TMP0:]] = insertvalue %struct.S0 poison, [2 x <4 x float>] %A0, 0 +// CHECK-DXIL: %A2 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison) +// CHECK-DXIL: %[[#TMP1:]] = insertvalue %struct.S0 %[[#TMP0]], <4 x float> %A2, 1 // CHECK-SPIRV: %[[#A0:]] = load [2 x <4 x float>], ptr addrspace(7) @A0, align 16 // CHECK-SPIRV: %[[#TMP0:]] = insertvalue %struct.S0 poison, [2 x <4 x float>] %[[#A0]], 0 -// CHECK-SPIRV: %[[#A01:]] = load <4 x float>, ptr addrspace(7) @A2, align 16 -// CHECK-SPIRV: %[[#TMP1:]] = insertvalue %struct.S0 %[[#TMP0]], <4 x float> %[[#A01]], 1 +// CHECK-SPIRV: %[[#A2:]] = load <4 x float>, ptr addrspace(7) @A2, align 16 +// CHECK-SPIRV: %[[#TMP1:]] = insertvalue %struct.S0 %[[#TMP0]], <4 x float> %[[#A2]], 1 // CHECK: %[[#ARG:]] = alloca %struct.S0, align 16 // CHECK: store %struct.S0 %[[#TMP1]], ptr %[[#ARG]], align 16 diff --git a/clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl b/clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl index a52c01d772a72..5b228d039345e 100644 --- a/clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl +++ b/clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl @@ -6,7 +6,7 @@ struct Eg9{ // CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} col:8 implicit struct Eg9 // CHECK: FieldDecl 0x{{[0-9a-f]+}} col:16 referenced a 'unsigned int' - // CHECK: -HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_DispatchThreadID" 0 + // CHECK: -HLSLSV_DispatchThreadIDAttr 0x{{[0-9a-f]+}} unsigned int a : SV_DispatchThreadID; }; Eg9 e9; diff --git a/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl b/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl index 91dbf9c74ad60..bcc94f0632d64 100644 --- a/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl +++ b/clang/test/SemaHLSL/Semantics/entry_parameter.hlsl @@ -4,15 +4,16 @@ void CSMain(int GI : SV_GroupIndex, uint ID : SV_DispatchThreadID, uint GID : SV_GroupID, uint GThreadID : SV_GroupThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain 'void (int, uint, uint, uint)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:17 GI 'int' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupIndex" 0 -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupIndex" 0 +// CHECK-NEXT: HLSLSV_GroupIndexAttr // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:42 ID 'uint' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_DispatchThreadID" 0 -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "SV_DispatchThreadID" 0 +// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:73 GID 'uint' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupID" 0 -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupID" 0 +// CHECK-NEXT: HLSLSV_GroupIDAttr // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:96 GThreadID 'uint' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupThreadID" 0 -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupThreadID" 0 +// CHECK-NEXT: HLSLSV_GroupThreadIDAttr + +// CHECK: HLSLSV_GroupIndexAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'GI' 'int' 0 +// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'ID' 'uint':'unsigned int' 0 +// CHECK-NEXT: HLSLSV_GroupIDAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'GID' 'uint':'unsigned int' 0 +// CHECK-NEXT: HLSLSV_GroupThreadIDAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'GThreadID' 'uint':'unsigned int' 0 } diff --git a/clang/test/SemaHLSL/Semantics/position.ps.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.hlsl index 7adf2a51f01c8..27a8e4a0e2662 100644 --- a/clang/test/SemaHLSL/Semantics/position.ps.hlsl +++ b/clang/test/SemaHLSL/Semantics/position.ps.hlsl @@ -4,6 +4,7 @@ float4 main(float4 a : SV_Position2) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (float4)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 a 'float4':'vector' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_Position" 2 -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "SV_Position" 2 +// CHECK-NEXT: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> + +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> ParmVar 0x{{[0-9a-fA-F]+}} 'a' 'float4':'vector' 2 SemanticExplicitIndex } diff --git a/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl index 3186aadf19946..9f57231bea0c1 100644 --- a/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl +++ b/clang/test/SemaHLSL/Semantics/position.ps.struct.hlsl @@ -3,16 +3,17 @@ struct S { float4 f0 : SV_Position; // CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 f0 'float4':'vector' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_Position" 0 +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <<>> 0 float4 f1 : SV_Position3; // CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 f1 'float4':'vector' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_Position" 3 +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <<>> 3 SemanticExplicitIndex }; // FIXME(Keenuts): add mandatory output semantic once those are implemented. float4 main(S s) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (S)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:15 s 'S' -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "SV_Position" 0 -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "SV_Position" 3 + +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> Field 0x{{[0-9a-fA-F]+}} 'f0' 'float4':'vector' 0 +// CHECK: HLSLSV_PositionAttr 0x{{[0-9a-fA-F]+}} <{{.*}}> Field 0x{{[0-9a-fA-F]+}} 'f1' 'float4':'vector' 3 SemanticExplicitIndex } diff --git a/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl deleted file mode 100644 index f12ac4df0c450..0000000000000 --- a/clang/test/SemaHLSL/Semantics/position.ps.struct.reuse.hlsl +++ /dev/null @@ -1,26 +0,0 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-pixel -x hlsl -finclude-default-header -o - %s -ast-dump | FileCheck %s - -struct A { - float4 x : A; -// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:10 x 'float4':'vector' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "A" 0 -}; - -struct Top { - A f0 : B; -// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:5 f0 'A' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "B" 0 - A f1 : C; -// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:5 f1 'A' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "C" 0 -}; - - -// FIXME(Keenuts): add mandatory output semantic once those are implemented. -float4 main(Top s : D) { -// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:8 main 'float4 (Top)' -// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:17 s 'Top' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "D" 0 -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "D" 0 -// CHECK-NEXT: HLSLAppliedSemanticAttr 0x{{[0-9a-f]+}} "D" 1 -} diff --git a/clang/test/SemaHLSL/Semantics/semantics-valid.hlsl b/clang/test/SemaHLSL/Semantics/semantics-valid.hlsl index 6d1ce27f6741f..1e6bae4fcbca5 100644 --- a/clang/test/SemaHLSL/Semantics/semantics-valid.hlsl +++ b/clang/test/SemaHLSL/Semantics/semantics-valid.hlsl @@ -1,34 +1,33 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -finclude-default-header -ast-dump -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -hlsl-entry CSMain -x hlsl -finclude-default-header -ast-dump -o - %s | FileCheck %s struct s_fields { float a : semantic_a; float b : semantic_b; -// CHECK: CXXRecordDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-3]]:8 struct s_fields definition -// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:9 a 'float' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "semantic_a" 0 -// CHECK: FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:9 b 'float' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "semantic_b" 0 +// CHECK: |-CXXRecordDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-3]]:8 struct s_fields definition +// CHECK: | |-FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:9 a 'float' +// CHECK: | | `-HLSLUserSemanticAttr 0x{{[0-9a-fA-F]+}} +// CHECK: | `-FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:9 b 'float' +// CHECK: | `-HLSLUserSemanticAttr 0x{{[0-9a-fA-F]+}} }; float fn_foo1(float a : a, float b : b) : sem_ret { return 1.0f; } -// CHECK: FunctionDecl {{.*}} <{{.*}}> col:7 fn_foo1 'float (float, float)' -// CHECK-NEXT: ParmVarDecl {{.*}} <{{.*}}> col:21 a 'float' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "a" 0 -// CHECK-NEXT: ParmVarDecl {{.*}} <{{.*}}> col:34 b 'float' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "b" 0 -// CHECK-NEXT: CompoundStmt {{.*}} <{{.*}}> -// CHECK-NEXT: ReturnStmt {{.*}} <{{.*}}> -// CHECK-NEXT: FloatingLiteral {{.*}} <{{.*}}> 'float' 1.000000e+00 -// CHECK-NEXT: HLSLParsedSemanticAttr {{.*}} <{{.*}}> "sem_ret" 0 - +// CHECK: |-FunctionDecl {{.*}} <{{.*}}> col:7 fn_foo1 'float (float, float)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} <{{.*}}> col:21 a 'float' +// CHECK-NEXT: | | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: | |-ParmVarDecl {{.*}} <{{.*}}> col:34 b 'float' +// CHECK-NEXT: | | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: | |-CompoundStmt {{.*}} <{{.*}}> +// CHECK-NEXT: | | `-ReturnStmt {{.*}} <{{.*}}> +// CHECK-NEXT: | | `-FloatingLiteral {{.*}} <{{.*}}> 'float' 1.000000e+00 +// CHECK-NEXT: | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> float fn_foo2(float a : a, float b : b) : sem_ret : also_ret { return 1.0f; } -// CHECK: FunctionDecl {{.*}} <{{.*}}> col:7 fn_foo2 'float (float, float)' -// CHECK-NEXT: ParmVarDecl {{.*}} <{{.*}}> col:21 a 'float' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "a" 0 -// CHECK-NEXT: ParmVarDecl {{.*}} <{{.*}}> col:34 b 'float' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "b" 0 -// CHECK-NEXT: CompoundStmt {{.*}} <{{.*}}> -// CHECK-NEXT: ReturnStmt {{.*}} <{{.*}}> -// CHECK-NEXT: FloatingLiteral {{.*}} <{{.*}}> 'float' 1.000000e+00 -// CHECK-NEXT: HLSLParsedSemanticAttr {{.*}} <{{.*}}> "sem_ret" 0 -// CHECK-NEXT: HLSLParsedSemanticAttr {{.*}} <{{.*}}> "also_ret" 0 +// CHECK: `-FunctionDecl {{.*}} <{{.*}}> col:7 fn_foo2 'float (float, float)' +// CHECK-NEXT: |-ParmVarDecl {{.*}} <{{.*}}> col:21 a 'float' +// CHECK-NEXT: | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: |-ParmVarDecl {{.*}} <{{.*}}> col:34 b 'float' +// CHECK-NEXT: | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: |-CompoundStmt {{.*}} <{{.*}}> +// CHECK-NEXT: | `-ReturnStmt {{.*}} <{{.*}}> +// CHECK-NEXT: | `-FloatingLiteral {{.*}} <{{.*}}> 'float' 1.000000e+00 +// CHECK-NEXT: |-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: `-HLSLUserSemanticAttr {{.*}} <{{.*}}> diff --git a/clang/test/SemaHLSL/Semantics/valid_entry_parameter.hlsl b/clang/test/SemaHLSL/Semantics/valid_entry_parameter.hlsl index 6bb9ae8dd1bb0..a2203692b582b 100644 --- a/clang/test/SemaHLSL/Semantics/valid_entry_parameter.hlsl +++ b/clang/test/SemaHLSL/Semantics/valid_entry_parameter.hlsl @@ -4,91 +4,91 @@ void CSMain(uint ID : SV_DispatchThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain 'void (uint)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:18 ID 'uint' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_DispatchThreadID" 0 +// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr } [numthreads(8,8,1)] void CSMain1(uint2 ID : SV_DispatchThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain1 'void (uint2)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 ID 'uint2' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_DispatchThreadID" 0 +// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr } [numthreads(8,8,1)] void CSMain2(uint3 ID : SV_DispatchThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain2 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 ID 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_DispatchThreadID" 0 +// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr } [numthreads(8,8,1)] void CSMain3(uint3 : SV_DispatchThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain3 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_DispatchThreadID" 0 +// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr } [numthreads(8,8,1)] void CSMain4(uint3 : SV_DispatchThreadId) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain4 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:20 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_DispatchThreadId" 0 +// CHECK-NEXT: HLSLSV_DispatchThreadIDAttr } [numthreads(8,8,1)] void CSMain_GID(uint ID : SV_GroupID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain_GID 'void (uint)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:22 ID 'uint' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupID" 0 +// CHECK-NEXT: HLSLSV_GroupIDAttr } [numthreads(8,8,1)] void CSMain1_GID(uint2 ID : SV_GroupID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain1_GID 'void (uint2)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:24 ID 'uint2' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupID" 0 +// CHECK-NEXT: HLSLSV_GroupIDAttr } [numthreads(8,8,1)] void CSMain2_GID(uint3 ID : SV_GroupID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain2_GID 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:24 ID 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupID" 0 +// CHECK-NEXT: HLSLSV_GroupIDAttr } [numthreads(8,8,1)] void CSMain3_GID(uint3 : SV_GroupID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain3_GID 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:24 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupID" 0 +// CHECK-NEXT: HLSLSV_GroupIDAttr } [numthreads(8,8,1)] void CSMain4_GID(uint3 : Sv_GroupId) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain4_GID 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:24 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "Sv_GroupId" 0 +// CHECK-NEXT: HLSLSV_GroupIDAttr } [numthreads(8,8,1)] void CSMain_GThreadID(uint ID : SV_GroupThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain_GThreadID 'void (uint)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:28 ID 'uint' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupThreadID" 0 +// CHECK-NEXT: HLSLSV_GroupThreadIDAttr } [numthreads(8,8,1)] void CSMain1_GThreadID(uint2 ID : SV_GroupThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain1_GThreadID 'void (uint2)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:30 ID 'uint2' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupThreadID" 0 +// CHECK-NEXT: HLSLSV_GroupThreadIDAttr } [numthreads(8,8,1)] void CSMain2_GThreadID(uint3 ID : SV_GroupThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain2_GThreadID 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:30 ID 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupThreadID" 0 +// CHECK-NEXT: HLSLSV_GroupThreadIDAttr } [numthreads(8,8,1)] void CSMain3_GThreadID(uint3 : SV_GroupThreadID) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain3_GThreadID 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:30 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "SV_GroupThreadID" 0 +// CHECK-NEXT: HLSLSV_GroupThreadIDAttr } [numthreads(8,8,1)] void CSMain4_GThreadID(uint3 : sv_GroupThreadid) { // CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain4_GThreadID 'void (uint3)' // CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:30 'uint3' -// CHECK-NEXT: HLSLParsedSemanticAttr 0x{{[0-9a-f]+}} "sv_GroupThreadid" 0 +// CHECK-NEXT: HLSLSV_GroupThreadIDAttr } diff --git a/clang/test/TableGen/HLSLAttribute-errors.td b/clang/test/TableGen/HLSLAttribute-errors.td index 6680762cc6e30..fc9473dcc1fb4 100644 --- a/clang/test/TableGen/HLSLAttribute-errors.td +++ b/clang/test/TableGen/HLSLAttribute-errors.td @@ -7,5 +7,5 @@ def HLSLSV_FAKE: HLSLAnnotationAttr { let Spellings = [HLSLAnnotation<"SV_Fake">]; let Subjects = SubjectList<[ParmVar, Field]>; let LangOpts = [HLSL]; - let Documentation = []; + let Documentation = [HLSLSV_GroupThreadIDDocs]; } diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index e49dcb9b70b0f..183952af590e1 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -2725,12 +2725,15 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS, assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); std::string SuperName; bool Inheritable = false; + bool HLSLSemantic = false; for (const Record *R : reverse(Supers)) { if (R->getName() != "TargetSpecificAttr" && R->getName() != "DeclOrTypeAttr" && SuperName.empty()) SuperName = R->getName().str(); if (R->getName() == "InheritableAttr") Inheritable = true; + if (R->getName() == "HLSLSemanticAttr") + HLSLSemantic = true; } if (Header) @@ -3054,6 +3057,8 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS, << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true" : "false"); } + if (HLSLSemantic) + OS << ", " << (R.getValueAsBit("SemanticIndexable") ? "true" : "false"); OS << ")\n"; for (auto const &ai : Args) { @@ -3073,6 +3078,17 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS, OS << " {\n"; + // The generator puts the arguments for each attribute in the child class, + // even if those are set in the inherited attribute class (in the TD + // file). This means I cannot access those from the parent class, and have + // to do this weirdness. Maybe the generator should be changed to + // arguments are put in the class they are declared in inside the TD file? + if (HLSLSemantic) { + OS << " if (SemanticExplicitIndex)\n"; + OS << " setSemanticIndex(SemanticIndex);\n"; + OS << " setTargetDecl(Target);\n"; + } + for (auto const &ai : Args) { if (!shouldEmitArg(ai)) continue; @@ -3271,7 +3287,7 @@ static const AttrClassDescriptor AttrClassDescriptors[] = { {"INHERITABLE_PARAM_OR_STMT_ATTR", "InheritableParamOrStmtAttr"}, {"PARAMETER_ABI_ATTR", "ParameterABIAttr"}, {"HLSL_ANNOTATION_ATTR", "HLSLAnnotationAttr"}, - {"HLSL_SEMANTIC_ATTR", "HLSLSemanticBaseAttr"}}; + {"HLSL_SEMANTIC_ATTR", "HLSLSemanticAttr"}}; static void emitDefaultDefine(raw_ostream &OS, StringRef name, const char *superName) {