diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 994f236337b99..c313b5406f387 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -232,6 +232,41 @@ class HLSLAnnotationAttr : public InheritableAttr { } }; +class HLSLSemanticAttr : public HLSLAnnotationAttr { + unsigned SemanticIndex : 30; + LLVM_PREFERRED_TYPE(bool) + unsigned SemanticIndexable : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SemanticExplicitIndex : 1; + +protected: + HLSLSemanticAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, + attr::Kind AK, bool IsLateParsed, + bool InheritEvenIfAlreadyPresent, bool SemanticIndexable) + : HLSLAnnotationAttr(Context, CommonInfo, AK, IsLateParsed, + InheritEvenIfAlreadyPresent) { + this->SemanticIndexable = SemanticIndexable; + this->SemanticIndex = 0; + this->SemanticExplicitIndex = 0; + } + +public: + bool isSemanticIndexable() const { return SemanticIndexable; } + + void setSemanticIndex(unsigned SemanticIndex) { + this->SemanticIndex = SemanticIndex; + this->SemanticExplicitIndex = true; + } + + unsigned getSemanticIndex() const { return SemanticIndex; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() >= attr::FirstHLSLSemanticAttr && + A->getKind() <= attr::LastHLSLSemanticAttr; + } +}; + /// A parameter attribute which changes the argument-passing ABI rule /// for the parameter. class ParameterABIAttr : public InheritableParamAttr { diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index b3ff45b3e90a3..bbedc020767a0 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -396,7 +396,7 @@ class ClangGCC } // HLSL Annotation spellings -class HLSLAnnotation : Spelling; +class HLSLAnnotation : Spelling {} class Accessor spellings> { string Name = name; @@ -779,6 +779,16 @@ 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]; +} + /// 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 { @@ -4873,27 +4883,6 @@ def HLSLNumThreads: InheritableAttr { let Documentation = [NumThreadsDocs]; } -def HLSLSV_GroupThreadID: HLSLAnnotationAttr { - let Spellings = [HLSLAnnotation<"sv_groupthreadid">]; - let Subjects = SubjectList<[ParmVar, Field]>; - let LangOpts = [HLSL]; - let Documentation = [HLSLSV_GroupThreadIDDocs]; -} - -def HLSLSV_GroupID: HLSLAnnotationAttr { - let Spellings = [HLSLAnnotation<"sv_groupid">]; - let Subjects = SubjectList<[ParmVar, Field]>; - let LangOpts = [HLSL]; - let Documentation = [HLSLSV_GroupIDDocs]; -} - -def HLSLSV_GroupIndex: HLSLAnnotationAttr { - let Spellings = [HLSLAnnotation<"sv_groupindex">]; - let Subjects = SubjectList<[ParmVar, GlobalVar]>; - let LangOpts = [HLSL]; - let Documentation = [HLSLSV_GroupIndexDocs]; -} - def HLSLResourceBinding: InheritableAttr { let Spellings = [HLSLAnnotation<"register">]; let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar], ErrorDiag>; @@ -4943,13 +4932,35 @@ def HLSLResourceBinding: InheritableAttr { }]; } -def HLSLSV_Position : HLSLAnnotationAttr { - let Spellings = [HLSLAnnotation<"sv_position">]; - let Subjects = SubjectList<[ParmVar, Field]>; +def HLSLUnparsedSemantic : HLSLAnnotationAttr { + let Spellings = []; + let Args = [DefaultIntArgument<"Index", 0>, + DefaultBoolArgument<"ExplicitIndex", 0>]; + let Subjects = SubjectList<[ParmVar, Field, Function]>; let LangOpts = [HLSL]; + let Documentation = [InternalOnly]; +} + +def HLSLSV_Position : HLSLSemanticAttr { let Documentation = [HLSLSV_PositionDocs]; } +def HLSLSV_GroupThreadID : HLSLSemanticAttr { + let Documentation = [HLSLSV_GroupThreadIDDocs]; +} + +def HLSLSV_GroupID : HLSLSemanticAttr { + let Documentation = [HLSLSV_GroupIDDocs]; +} + +def HLSLSV_GroupIndex : HLSLSemanticAttr { + let Documentation = [HLSLSV_GroupIndexDocs]; +} + +def HLSLSV_DispatchThreadID : HLSLSemanticAttr { + let Documentation = [HLSLSV_DispatchThreadIDDocs]; +} + def HLSLPackOffset: HLSLAnnotationAttr { let Spellings = [HLSLAnnotation<"packoffset">]; let LangOpts = [HLSL]; @@ -4962,13 +4973,6 @@ def HLSLPackOffset: HLSLAnnotationAttr { }]; } -def HLSLSV_DispatchThreadID: HLSLAnnotationAttr { - let Spellings = [HLSLAnnotation<"sv_dispatchthreadid">]; - let Subjects = SubjectList<[ParmVar, Field]>; - let LangOpts = [HLSL]; - let Documentation = [HLSLSV_DispatchThreadIDDocs]; -} - def HLSLShader : InheritableAttr { let Spellings = [Microsoft<"shader">]; let Subjects = SubjectList<[HLSLEntry]>; diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 8a8db27490f06..6206e559b4729 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -393,6 +393,14 @@ def warn_hlsl_langstd_minimal : "recommend using %1 instead">, InGroup; +def err_hlsl_semantic_index_overlap : Error<"semantic index overlap %0">; + +def err_hlsl_semantic_missing : Error<"semantic annotations must be present " + "for all input and outputs of an entry " + "function or patch constant function">; + +def note_hlsl_semantic_used_here : Note<"%0 used here">; + // ClangIR frontend errors def err_cir_to_cir_transform_failed : Error< "CIR-to-CIR transformation failed">, DefaultFatal; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 165f01514e2b1..e8999d4bd7858 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1851,9 +1851,8 @@ def note_max_tokens_total_override : Note<"total token limit set here">; def err_expected_semantic_identifier : Error< "expected HLSL Semantic identifier">; -def err_invalid_declaration_in_hlsl_buffer : Error< - "invalid declaration inside %select{tbuffer|cbuffer}0">; -def err_unknown_hlsl_semantic : Error<"unknown HLSL semantic %0">; +def err_invalid_declaration_in_hlsl_buffer + : Error<"invalid declaration inside %select{tbuffer|cbuffer}0">; def err_hlsl_separate_attr_arg_and_number : Error<"wrong argument format for hlsl attribute, use %0 instead">; def ext_hlsl_access_specifiers : ExtWarn< "access specifiers are a clang HLSL extension">, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 94b174c758a5c..914ec11ba4554 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13058,6 +13058,11 @@ def err_hlsl_duplicate_parameter_modifier : Error<"duplicate parameter modifier def err_hlsl_missing_semantic_annotation : Error< "semantic annotations must be present for all parameters of an entry " "function or patch constant function">; +def err_hlsl_unknown_semantic : Error<"unknown HLSL semantic %0">; +def err_hlsl_semantic_output_not_supported + : Error<"semantic %0 does not support output">; +def err_hlsl_semantic_indexing_not_supported + : Error<"semantic %0 does not allow indexing">; def err_hlsl_init_priority_unsupported : Error< "initializer priorities are not supported in HLSL">; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 683934321a449..f07b4ebe567e5 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -5188,6 +5188,14 @@ class Parser : public CodeCompletionHandler { ParseHLSLAnnotations(Attrs, EndLoc); } + struct ParsedSemantic { + StringRef Name; + unsigned Index; + bool Explicit; + }; + + ParsedSemantic ParseHLSLSemantic(); + void ParseHLSLAnnotations(ParsedAttributes &Attrs, SourceLocation *EndLoc = nullptr, bool CouldBeBitField = false); diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index c0da80a70bb82..a6bcca7a258f6 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -17,6 +17,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/SemaBase.h" #include "llvm/ADT/SmallVector.h" @@ -129,6 +130,7 @@ class SemaHLSL : public SemaBase { bool ActOnUninitializedVarDecl(VarDecl *D); void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU); void CheckEntryPoint(FunctionDecl *FD); + bool isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D); void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param, const HLSLAnnotationAttr *AnnotationAttr); void DiagnoseAttrStageMismatch( @@ -161,16 +163,31 @@ class SemaHLSL : public SemaBase { void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL); void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL); void handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL); - void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL); - void handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL); - void handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL); - void handleSV_PositionAttr(Decl *D, const ParsedAttr &AL); void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL); void handleShaderAttr(Decl *D, const ParsedAttr &AL); void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL); void handleParamModifierAttr(Decl *D, const ParsedAttr &AL); bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL); + template + T *createSemanticAttr(const ParsedAttr &AL, + std::optional Location) { + T *Attr = ::new (getASTContext()) T(getASTContext(), AL); + if (Attr->isSemanticIndexable()) + Attr->setSemanticIndex(Location ? *Location : 0); + else if (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, + std::optional Index); + void handleSemanticAttr(Decl *D, const ParsedAttr &AL); + void handleVkExtBuiltinInputAttr(Decl *D, const ParsedAttr &AL); bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index 81b186f844b8a..5878a4e3f83a4 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -189,7 +189,12 @@ AttributeCommonInfo::Kind AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name, const IdentifierInfo *ScopeName, Syntax SyntaxUsed) { - return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed); + AttributeCommonInfo::Kind Kind = + ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed); + if (SyntaxUsed == AS_HLSLAnnotation && + Kind == AttributeCommonInfo::Kind::UnknownAttribute) + return AttributeCommonInfo::Kind::AT_HLSLUnparsedSemantic; + return Kind; } AttributeCommonInfo::AttrArgsInfo diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index a47d1cc22980d..346c867e5a0fe 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -22,6 +22,7 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/TargetOptions.h" +#include "clang/Frontend/FrontendDiagnostic.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Frontend/HLSL/RootSignatureMetadata.h" #include "llvm/IR/Constants.h" @@ -383,47 +384,82 @@ static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M, return B.CreateLoad(Ty, GV); } -llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B, - const ParmVarDecl &D, - llvm::Type *Ty) { - assert(D.hasAttrs() && "Entry parameter missing annotation attribute!"); - if (D.hasAttr()) { +llvm::Value * +CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type, + const clang::DeclaratorDecl *Decl, + SemanticInfo &ActiveSemantic) { + if (HLSLSV_GroupIndexAttr *S = + dyn_cast(ActiveSemantic.Semantic)) { llvm::Function *GroupIndex = CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic()); return B.CreateCall(FunctionCallee(GroupIndex)); } - if (D.hasAttr()) { + + if (HLSLSV_DispatchThreadIDAttr *S = + dyn_cast(ActiveSemantic.Semantic)) { llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic(); llvm::Function *ThreadIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty}) : CGM.getIntrinsic(IntrinID); - return buildVectorInput(B, ThreadIDIntrinsic, Ty); + return buildVectorInput(B, ThreadIDIntrinsic, Type); } - if (D.hasAttr()) { + + if (HLSLSV_GroupThreadIDAttr *S = + dyn_cast(ActiveSemantic.Semantic)) { llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic(); llvm::Function *GroupThreadIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty}) : CGM.getIntrinsic(IntrinID); - return buildVectorInput(B, GroupThreadIDIntrinsic, Ty); + return buildVectorInput(B, GroupThreadIDIntrinsic, Type); } - if (D.hasAttr()) { + + if (HLSLSV_GroupIDAttr *S = + dyn_cast(ActiveSemantic.Semantic)) { llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic(); llvm::Function *GroupIDIntrinsic = llvm::Intrinsic::isOverloaded(IntrinID) ? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty}) : CGM.getIntrinsic(IntrinID); - return buildVectorInput(B, GroupIDIntrinsic, Ty); + return buildVectorInput(B, GroupIDIntrinsic, Type); } - if (D.hasAttr()) { - if (getArch() == llvm::Triple::spirv) - return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position", - /* BuiltIn::Position */ 0); - llvm_unreachable("SV_Position semantic not implemented for this target."); + + if (HLSLSV_PositionAttr *S = + dyn_cast(ActiveSemantic.Semantic)) { + if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel) + return createSPIRVBuiltinLoad(B, CGM.getModule(), Type, + S->getAttrName()->getName(), + /* BuiltIn::FragCoord */ 15); } - assert(false && "Unhandled parameter attribute"); - return nullptr; + + llvm_unreachable("non-handled system semantic. FIXME."); +} + +llvm::Value * +CGHLSLRuntime::handleScalarSemanticLoad(IRBuilder<> &B, llvm::Type *Type, + const clang::DeclaratorDecl *Decl, + SemanticInfo &ActiveSemantic) { + + if (!ActiveSemantic.Semantic) { + ActiveSemantic.Semantic = Decl->getAttr(); + if (!ActiveSemantic.Semantic) { + CGM.getDiags().Report(Decl->getInnerLocStart(), + diag::err_hlsl_semantic_missing); + return nullptr; + } + ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex(); + } + + return emitSystemSemanticLoad(B, Type, Decl, ActiveSemantic); +} + +llvm::Value * +CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, llvm::Type *Type, + const clang::DeclaratorDecl *Decl, + SemanticInfo &ActiveSemantic) { + assert(!Type->isStructTy()); + return handleScalarSemanticLoad(B, Type, Decl, ActiveSemantic); } void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, @@ -440,13 +476,13 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, Fn->getAttributes().getFnAttrs()); EntryFn->setAttributes(NewAttrs); setHLSLEntryAttributes(FD, EntryFn); + llvm::SmallVector Args; // Set the called function as internal linkage. Fn->setLinkage(GlobalValue::InternalLinkage); BasicBlock *BB = BasicBlock::Create(Ctx, "entry", EntryFn); IRBuilder<> B(BB); - llvm::SmallVector Args; SmallVector OB; if (CGM.shouldEmitConvergenceTokens()) { @@ -459,6 +495,7 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, // FIXME: support struct parameters where semantics are on members. // See: https://github.com/llvm/llvm-project/issues/57874 + unsigned SRetOffset = 0; for (const auto &Param : Fn->args()) { if (Param.hasStructRetAttr()) { @@ -468,14 +505,17 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, Args.emplace_back(PoisonValue::get(Param.getType())); continue; } + const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset); - Args.push_back(emitInputSemantic(B, *PD, Param.getType())); + SemanticInfo ActiveSemantic = {nullptr, 0}; + Args.push_back(handleSemanticLoad(B, Param.getType(), PD, ActiveSemantic)); } CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB); CI->setCallingConv(Fn->getCallingConv()); // FIXME: Handle codegen for return type semantics. // See: https://github.com/llvm/llvm-project/issues/57875 + B.CreateRetVoid(); // Add and identify root signature to function, if applicable diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 89d2aff85d913..1c78e8bbba7b7 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -21,6 +21,8 @@ #include "llvm/IR/IntrinsicsDirectX.h" #include "llvm/IR/IntrinsicsSPIRV.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/HLSLRuntime.h" @@ -29,6 +31,7 @@ #include "llvm/Frontend/HLSL/HLSLResource.h" #include +#include #include // A function generator macro for picking the right intrinsic @@ -133,8 +136,26 @@ class CGHLSLRuntime { protected: CodeGenModule &CGM; - llvm::Value *emitInputSemantic(llvm::IRBuilder<> &B, const ParmVarDecl &D, - llvm::Type *Ty); + void collectInputSemantic(llvm::IRBuilder<> &B, const DeclaratorDecl *D, + llvm::Type *Type, + SmallVectorImpl &Inputs); + + struct SemanticInfo { + clang::HLSLSemanticAttr *Semantic; + uint32_t Index; + }; + + llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, + const clang::DeclaratorDecl *Decl, + SemanticInfo &ActiveSemantic); + + llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, + const clang::DeclaratorDecl *Decl, + SemanticInfo &ActiveSemantic); + + llvm::Value *handleSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type, + const clang::DeclaratorDecl *Decl, + SemanticInfo &ActiveSemantic); public: CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {} @@ -172,6 +193,9 @@ class CGHLSLRuntime { llvm::Triple::ArchType getArch(); llvm::DenseMap LayoutTypes; + + std::unordered_set ActiveInputSemantics; + std::unordered_set ActiveOutputSemantics; }; } // namespace CodeGen diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp index e6caa81b309ca..dd2f00c36a034 100644 --- a/clang/lib/Parse/ParseHLSL.cpp +++ b/clang/lib/Parse/ParseHLSL.cpp @@ -118,6 +118,48 @@ static void fixSeparateAttrArgAndNumber(StringRef ArgStr, SourceLocation ArgLoc, Slot = new (Ctx) IdentifierLoc(ArgLoc, PP.getIdentifierInfo(FixedArg)); } +Parser::ParsedSemantic Parser::ParseHLSLSemantic() { + assert(Tok.is(tok::identifier) && "Not a HLSL Annotation"); + + // Semantic pattern: [A-Za-z_]+[0-9]* + // The first part is the semantic name, the second is the optional + // semantic index. + bool Invalid = false; + SmallString<256> Buffer; + Buffer.resize(Tok.getLength() + 1); + StringRef Identifier = PP.getSpelling(Tok, Buffer); + if (Invalid) { + // FIXME: fix error message. + Diag(Tok.getLocation(), diag::err_expected_semantic_identifier); + return {/* Name= */ "", /* Location= */ 0, /* Explicit= */ false}; + } + + unsigned I = 0; + for (; I < Identifier.size() && !isDigit(Identifier[I]); ++I) + continue; + StringRef SemanticName = Identifier.take_front(I); + + if (SemanticName.size() == 0) { + // FIXME: fix error message. + Diag(Tok.getLocation(), diag::err_expected_semantic_identifier); + return {/* Name= */ "", /* Location= */ 0, /* Explicit= */ false}; + } + + unsigned Index = 0; + bool Explicit = I < Identifier.size(); + for (; I < Identifier.size() && isDigit(Identifier[I]); ++I) + Index = Index * 10 + Identifier[I] - '0'; + + // The attribute has letters after the index. + if (I != Identifier.size()) { + // FIXME: fix error message. + Diag(Tok.getLocation(), diag::err_expected_semantic_identifier); + return {/* Name= */ "", /* Location= */ 0, /* Explicit= */ false}; + } + + return {SemanticName, Index, Explicit}; +} + void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs, SourceLocation *EndLoc, bool CouldBeBitField) { @@ -141,11 +183,15 @@ void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs, return; } + ParsedAttr::Kind AttrKind = + ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLAnnotation); + Parser::ParsedSemantic Semantic; + if (AttrKind == ParsedAttr::AT_HLSLUnparsedSemantic) + Semantic = ParseHLSLSemantic(); + SourceLocation Loc = ConsumeToken(); if (EndLoc) *EndLoc = Tok.getLocation(); - ParsedAttr::Kind AttrKind = - ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLAnnotation); ArgsVector ArgExprs; switch (AttrKind) { @@ -282,14 +328,17 @@ void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs, return; } } break; - case ParsedAttr::UnknownAttribute: - Diag(Loc, diag::err_unknown_hlsl_semantic) << II; - return; - case ParsedAttr::AT_HLSLSV_GroupThreadID: - case ParsedAttr::AT_HLSLSV_GroupID: - case ParsedAttr::AT_HLSLSV_GroupIndex: - case ParsedAttr::AT_HLSLSV_DispatchThreadID: - case ParsedAttr::AT_HLSLSV_Position: + case ParsedAttr::AT_HLSLUnparsedSemantic: { + ASTContext &Ctx = Actions.getASTContext(); + ArgExprs.push_back(IntegerLiteral::Create( + Ctx, llvm::APInt(Ctx.getTypeSize(Ctx.IntTy), Semantic.Index), Ctx.IntTy, + SourceLocation())); + ArgExprs.push_back(IntegerLiteral::Create( + Ctx, llvm::APInt(1, Semantic.Explicit), Ctx.BoolTy, SourceLocation())); + II = PP.getIdentifierInfo(Semantic.Name.upper()); + break; + } + case ParsedAttr::UnknownAttribute: // FIXME: maybe this is obsolete? break; default: llvm_unreachable("invalid HLSL Annotation"); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 16b18bcb6a2a0..276bcb1365034 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7432,30 +7432,15 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_HLSLWaveSize: S.HLSL().handleWaveSizeAttr(D, AL); break; - case ParsedAttr::AT_HLSLSV_Position: - S.HLSL().handleSV_PositionAttr(D, AL); - break; case ParsedAttr::AT_HLSLVkExtBuiltinInput: S.HLSL().handleVkExtBuiltinInputAttr(D, AL); break; case ParsedAttr::AT_HLSLVkConstantId: S.HLSL().handleVkConstantIdAttr(D, AL); break; - case ParsedAttr::AT_HLSLSV_GroupThreadID: - S.HLSL().handleSV_GroupThreadIDAttr(D, AL); - break; - case ParsedAttr::AT_HLSLSV_GroupID: - S.HLSL().handleSV_GroupIDAttr(D, AL); - break; - case ParsedAttr::AT_HLSLSV_GroupIndex: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_HLSLGroupSharedAddressSpace: handleSimpleAttribute(S, D, AL); break; - case ParsedAttr::AT_HLSLSV_DispatchThreadID: - S.HLSL().handleSV_DispatchThreadIDAttr(D, AL); - break; case ParsedAttr::AT_HLSLPackOffset: S.HLSL().handlePackOffsetAttr(D, AL); break; @@ -7468,6 +7453,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_HLSLParamModifier: S.HLSL().handleParamModifierAttr(D, AL); break; + case ParsedAttr::AT_HLSLUnparsedSemantic: + S.HLSL().handleSemanticAttr(D, AL); + break; case ParsedAttr::AT_AbiTag: handleAbiTagAttr(S, D, AL); diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 9276554bebf9d..1617b07fab208 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -747,6 +747,26 @@ void SemaHLSL::ActOnTopLevelFunction(FunctionDecl *FD) { } } +bool SemaHLSL::isSemanticValid(FunctionDecl *FD, DeclaratorDecl *D) { + const auto *AnnotationAttr = D->getAttr(); + if (AnnotationAttr) { + CheckSemanticAnnotation(FD, D, AnnotationAttr); + return true; + } + + const Type *T = D->getType()->getUnqualifiedDesugaredType(); + const RecordType *RT = dyn_cast(T); + if (!RT) + return false; + + const RecordDecl *RD = RT->getDecl(); + for (FieldDecl *Field : RD->fields()) { + if (!isSemanticValid(FD, Field)) + return false; + } + return true; +} + void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { const auto *ShaderAttr = FD->getAttr(); assert(ShaderAttr && "Entry point has no shader attribute"); @@ -808,11 +828,7 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) { } for (ParmVarDecl *Param : FD->parameters()) { - if (const auto *AnnotationAttr = Param->getAttr()) { - CheckSemanticAnnotation(FD, Param, AnnotationAttr); - } else { - // FIXME: Handle struct parameters where annotations are on struct fields. - // See: https://github.com/llvm/llvm-project/issues/57875 + if (!isSemanticValid(FD, Param)) { Diag(FD->getLocation(), diag::err_hlsl_missing_semantic_annotation); Diag(Param->getLocation(), diag::note_previous_decl) << Param; FD->setInvalidDecl(); @@ -838,8 +854,6 @@ void SemaHLSL::CheckSemanticAnnotation( DiagnoseAttrStageMismatch(AnnotationAttr, 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(AnnotationAttr, ST, {llvm::Triple::Pixel}); @@ -1492,18 +1506,8 @@ bool SemaHLSL::diagnoseInputIDType(QualType T, const ParsedAttr &AL) { return true; } -void SemaHLSL::handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL) { - auto *VD = cast(D); - if (!diagnoseInputIDType(VD->getType(), AL)) - return; - - D->addAttr(::new (getASTContext()) - HLSLSV_DispatchThreadIDAttr(getASTContext(), AL)); -} - bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) { const auto *VT = T->getAs(); - if (!T->hasFloatingRepresentation() || (VT && VT->getNumElements() > 4)) { Diag(AL.getLoc(), diag::err_hlsl_attr_invalid_type) << AL << "float/float1/float2/float3/float4"; @@ -1513,29 +1517,71 @@ bool SemaHLSL::diagnosePositionType(QualType T, const ParsedAttr &AL) { return true; } -void SemaHLSL::handleSV_PositionAttr(Decl *D, const ParsedAttr &AL) { - auto *VD = cast(D); - if (!diagnosePositionType(VD->getType(), AL)) - return; - - D->addAttr(::new (getASTContext()) HLSLSV_PositionAttr(getASTContext(), AL)); -} +void SemaHLSL::diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL, + std::optional Index) { + StringRef SemanticName = AL.getAttrName()->getName(); -void SemaHLSL::handleSV_GroupThreadIDAttr(Decl *D, const ParsedAttr &AL) { auto *VD = cast(D); - if (!diagnoseInputIDType(VD->getType(), AL)) - return; - - D->addAttr(::new (getASTContext()) - HLSLSV_GroupThreadIDAttr(getASTContext(), AL)); -} + QualType ValueType = VD->getType(); + if (auto *FD = dyn_cast(D)) + ValueType = FD->getReturnType(); + + bool IsOutput = false; + if (HLSLParamModifierAttr *MA = D->getAttr()) { + if (MA->isOut()) { + IsOutput = true; + ValueType = cast(ValueType)->getPointeeType(); + } + } -void SemaHLSL::handleSV_GroupIDAttr(Decl *D, const ParsedAttr &AL) { - auto *VD = cast(D); - if (!diagnoseInputIDType(VD->getType(), AL)) +#define CHECK_OUTPUT_FORBIDDEN(AL) \ + if (IsOutput) { \ + Diag(AL.getLoc(), diag::err_hlsl_semantic_output_not_supported) << AL; \ + } + + Attr *Attribute = nullptr; + if (SemanticName == "SV_DISPATCHTHREADID") { + diagnoseInputIDType(ValueType, AL); + CHECK_OUTPUT_FORBIDDEN(AL); + Attribute = createSemanticAttr(AL, Index); + } else if (SemanticName == "SV_GROUPINDEX") { + CHECK_OUTPUT_FORBIDDEN(AL); + Attribute = createSemanticAttr(AL, Index); + } else if (SemanticName == "SV_GROUPTHREADID") { + diagnoseInputIDType(ValueType, AL); + CHECK_OUTPUT_FORBIDDEN(AL); + Attribute = createSemanticAttr(AL, Index); + } else if (SemanticName == "SV_GROUPID") { + diagnoseInputIDType(ValueType, AL); + CHECK_OUTPUT_FORBIDDEN(AL); + Attribute = createSemanticAttr(AL, 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"; + Attribute = createSemanticAttr(AL, Index); + } else + Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL; + + if (!Attribute) return; + D->addAttr(Attribute); +} - D->addAttr(::new (getASTContext()) HLSLSV_GroupIDAttr(getASTContext(), AL)); +void SemaHLSL::handleSemanticAttr(Decl *D, const ParsedAttr &AL) { + uint32_t IndexValue, ExplicitIndex; + SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), IndexValue); + SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), ExplicitIndex); + assert(IndexValue > 0 ? ExplicitIndex : true); + std::optional Index = + ExplicitIndex ? std::optional(IndexValue) : std::nullopt; + + if (AL.getAttrName()->getName().starts_with("SV_")) + diagnoseSystemSemanticAttr(D, AL, Index); + else + Diag(AL.getLoc(), diag::err_hlsl_unknown_semantic) << AL; } 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 new file mode 100644 index 0000000000000..c75efff82a852 --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/DispatchThreadID-noindex.hlsl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error + +[shader("compute")] +[numthreads(8,8,1)] +void foo(uint Idx : SV_DispatchThreadID1) { + // 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 new file mode 100644 index 0000000000000..d18ab9f5d0ff7 --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/SV_GroupID-noindex.hlsl @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error + +[shader("compute")] +[numthreads(8,8,1)] +void foo(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 new file mode 100644 index 0000000000000..55b1f349dd943 --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/SV_GroupThreadID-noindex.hlsl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s -verify -verify-ignore-unexpected=note,error + +[shader("compute")] +[numthreads(8,8,1)] +void foo(uint Idx : SV_GroupThreadID1) { + // expected-error@-1 {{semantic SV_GROUPTHREADID does not allow indexing}} +} diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl index bdba38e028edd..af13eb3ea6af5 100644 --- a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl +++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-pixel -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s -// CHECK: @sv_position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0 +// CHECK: @SV_POSITION = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0 // CHECK: define void @main() {{.*}} { float4 main(float4 p : SV_Position) { - // CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @sv_position, align 16 + // CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_POSITION, align 16 // CHECK: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]]) return p; } diff --git a/clang/test/ParserHLSL/semantic_parsing.hlsl b/clang/test/ParserHLSL/semantic_parsing.hlsl index 34df1805c5a95..1301c84e0211b 100644 --- a/clang/test/ParserHLSL/semantic_parsing.hlsl +++ b/clang/test/ParserHLSL/semantic_parsing.hlsl @@ -3,5 +3,5 @@ // expected-error@+1 {{expected HLSL Semantic identifier}} void Entry(int GI : ) { } -// expected-error@+1 {{unknown HLSL semantic 'SV_IWantAPony'}} +// expected-error@+1 {{unknown HLSL semantic 'SV_IWANTAPONY'}} void Pony(int GI : SV_IWantAPony) { } diff --git a/clang/test/SemaHLSL/Semantics/groupindex.hlsl b/clang/test/SemaHLSL/Semantics/groupindex.hlsl index a33e060c82906..8acdee8e85989 100644 --- a/clang/test/SemaHLSL/Semantics/groupindex.hlsl +++ b/clang/test/SemaHLSL/Semantics/groupindex.hlsl @@ -4,26 +4,26 @@ [shader("compute")][numthreads(32,1,1)] void compute(int GI : SV_GroupIndex) {} -// expected-error@+2 {{attribute 'SV_GroupIndex' is unsupported in 'pixel' shaders}} +// expected-error@+2 {{attribute 'SV_GROUPINDEX' is unsupported in 'pixel' shaders}} [shader("pixel")] void pixel(int GI : SV_GroupIndex) {} -// expected-error@+2 {{attribute 'SV_GroupIndex' is unsupported in 'vertex' shaders}} +// expected-error@+2 {{attribute 'SV_GROUPINDEX' is unsupported in 'vertex' shaders}} [shader("vertex")] void vertex(int GI : SV_GroupIndex) {} -// expected-error@+2 {{attribute 'SV_GroupIndex' is unsupported in 'geometry' shaders}} +// expected-error@+2 {{attribute 'SV_GROUPINDEX' is unsupported in 'geometry' shaders}} [shader("geometry")] void geometry(int GI : SV_GroupIndex) {} -// expected-error@+2 {{attribute 'SV_GroupIndex' is unsupported in 'domain' shaders}} +// expected-error@+2 {{attribute 'SV_GROUPINDEX' is unsupported in 'domain' shaders}} [shader("domain")] void domain(int GI : SV_GroupIndex) {} -// expected-error@+2 {{attribute 'SV_GroupIndex' is unsupported in 'amplification' shaders}} +// expected-error@+2 {{attribute 'SV_GROUPINDEX' is unsupported in 'amplification' shaders}} [shader("amplification")][numthreads(32,1,1)] void amplification(int GI : SV_GroupIndex) {} -// expected-error@+2 {{attribute 'SV_GroupIndex' is unsupported in 'mesh' shaders}} +// expected-error@+2 {{attribute 'SV_GROUPINDEX' is unsupported in 'mesh' shaders}} [shader("mesh")][numthreads(32,1,1)] void mesh(int GI : SV_GroupIndex) {} diff --git a/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl b/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl index 1bb4ee5182d62..18bae5ee322df 100644 --- a/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl +++ b/clang/test/SemaHLSL/Semantics/invalid_entry_parameter.hlsl @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -x hlsl -ast-dump -verify -o - %s [numthreads(8,8,1)] -// expected-error@+1 {{attribute 'SV_DispatchThreadID' only applies to a field or parameter of type 'uint/uint2/uint3'}} +// expected-error@+1 {{attribute 'SV_DISPATCHTHREADID' only applies to a field or parameter of type 'uint/uint2/uint3'}} void CSMain(float ID : SV_DispatchThreadID) { } @@ -11,71 +11,71 @@ struct ST { float b; }; [numthreads(8,8,1)] -// expected-error@+1 {{attribute 'SV_DispatchThreadID' only applies to a field or parameter of type 'uint/uint2/uint3'}} +// expected-error@+1 {{attribute 'SV_DISPATCHTHREADID' only applies to a field or parameter of type 'uint/uint2/uint3'}} void CSMain2(ST ID : SV_DispatchThreadID) { } void foo() { -// expected-warning@+1 {{'SV_DispatchThreadID' attribute only applies to parameters and non-static data members}} +// expected-warning@+1 {{'SV_DISPATCHTHREADID' attribute only applies to parameters, non-static data members, and functions}} uint V : SV_DispatchThreadID; } struct ST2 { -// expected-warning@+1 {{'SV_DispatchThreadID' attribute only applies to parameters and non-static data members}} +// expected-warning@+1 {{'SV_DISPATCHTHREADID' attribute only applies to parameters, non-static data members, and functions}} static uint X : SV_DispatchThreadID; uint s : SV_DispatchThreadID; }; [numthreads(8,8,1)] -// expected-error@+1 {{attribute 'SV_GroupID' only applies to a field or parameter of type 'uint/uint2/uint3'}} +// expected-error@+1 {{attribute 'SV_GROUPID' only applies to a field or parameter of type 'uint/uint2/uint3'}} void CSMain_GID(float ID : SV_GroupID) { } [numthreads(8,8,1)] -// expected-error@+1 {{attribute 'SV_GroupID' only applies to a field or parameter of type 'uint/uint2/uint3'}} +// expected-error@+1 {{attribute 'SV_GROUPID' only applies to a field or parameter of type 'uint/uint2/uint3'}} void CSMain2_GID(ST GID : SV_GroupID) { } void foo_GID() { -// expected-warning@+1 {{'SV_GroupID' attribute only applies to parameters and non-static data members}} +// expected-warning@+1 {{'SV_GROUPID' attribute only applies to parameters, non-static data members, and functions}} uint GIS : SV_GroupID; } struct ST2_GID { -// expected-warning@+1 {{'SV_GroupID' attribute only applies to parameters and non-static data members}} +// expected-warning@+1 {{'SV_GROUPID' attribute only applies to parameters, non-static data members, and functions}} static uint GID : SV_GroupID; uint s_gid : SV_GroupID; }; [numthreads(8,8,1)] -// expected-error@+1 {{attribute 'SV_GroupThreadID' only applies to a field or parameter of type 'uint/uint2/uint3'}} +// expected-error@+1 {{attribute 'SV_GROUPTHREADID' only applies to a field or parameter of type 'uint/uint2/uint3'}} void CSMain_GThreadID(float ID : SV_GroupThreadID) { } [numthreads(8,8,1)] -// expected-error@+1 {{attribute 'SV_GroupThreadID' only applies to a field or parameter of type 'uint/uint2/uint3'}} +// expected-error@+1 {{attribute 'SV_GROUPTHREADID' only applies to a field or parameter of type 'uint/uint2/uint3'}} void CSMain2_GThreadID(ST GID : SV_GroupThreadID) { } void foo_GThreadID() { -// expected-warning@+1 {{'SV_GroupThreadID' attribute only applies to parameters and non-static data members}} +// expected-warning@+1 {{'SV_GROUPTHREADID' attribute only applies to parameters, non-static data members, and functions}} uint GThreadIS : SV_GroupThreadID; } struct ST2_GThreadID { -// expected-warning@+1 {{'SV_GroupThreadID' attribute only applies to parameters and non-static data members}} +// expected-warning@+1 {{'SV_GROUPTHREADID' attribute only applies to parameters, non-static data members, and functions}} static uint GThreadID : SV_GroupThreadID; uint s_gthreadid : SV_GroupThreadID; }; [shader("vertex")] -// expected-error@+4 {{attribute 'SV_GroupIndex' is unsupported in 'vertex' shaders, requires compute}} -// expected-error@+3 {{attribute 'SV_DispatchThreadID' is unsupported in 'vertex' shaders, requires compute}} -// expected-error@+2 {{attribute 'SV_GroupID' is unsupported in 'vertex' shaders, requires compute}} -// expected-error@+1 {{attribute 'SV_GroupThreadID' is unsupported in 'vertex' shaders, requires compute}} +// expected-error@+4 {{attribute 'SV_GROUPINDEX' is unsupported in 'vertex' shaders, requires compute}} +// expected-error@+3 {{attribute 'SV_DISPATCHTHREADID' is unsupported in 'vertex' shaders, requires compute}} +// expected-error@+2 {{attribute 'SV_GROUPID' is unsupported in 'vertex' shaders, requires compute}} +// expected-error@+1 {{attribute 'SV_GROUPTHREADID' is unsupported in 'vertex' shaders, requires compute}} void vs_main(int GI : SV_GroupIndex, uint ID : SV_DispatchThreadID, uint GID : SV_GroupID, uint GThreadID : SV_GroupThreadID) {} diff --git a/clang/test/SemaHLSL/Semantics/position.ps.size.hlsl b/clang/test/SemaHLSL/Semantics/position.ps.size.hlsl index 124d401a9990c..b57ce4e325ca2 100644 --- a/clang/test/SemaHLSL/Semantics/position.ps.size.hlsl +++ b/clang/test/SemaHLSL/Semantics/position.ps.size.hlsl @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -finclude-default-header -o - %s -verify -verify-ignore-unexpected // RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-library -x hlsl -finclude-default-header -o - %s -verify -verify-ignore-unexpected -// expected-error@+1 {{attribute 'SV_Position' only applies to a field or parameter of type 'float/float1/float2/float3/float4'}} +// expected-error@+1 {{attribute 'SV_POSITION' only applies to a field or parameter of type 'float/float1/float2/float3/float4'}} void main(vector a : SV_Position) { } -// expected-error@+1 {{attribute 'SV_Position' only applies to a field or parameter of type 'float/float1/float2/float3/float4'}} +// expected-error@+1 {{attribute 'SV_POSITION' only applies to a field or parameter of type 'float/float1/float2/float3/float4'}} void main(int2 a : SV_Position) { } diff --git a/clang/test/SemaHLSL/Semantics/position.vs.hlsl b/clang/test/SemaHLSL/Semantics/position.vs.hlsl index 19f781fa3757c..e5e8da2484d93 100644 --- a/clang/test/SemaHLSL/Semantics/position.vs.hlsl +++ b/clang/test/SemaHLSL/Semantics/position.vs.hlsl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-vertex -x hlsl -finclude-default-header -o - %s -verify -// expected-error@+1 {{attribute 'SV_Position' is unsupported in 'vertex' shaders, requires pixel}} +// expected-error@+1 {{attribute 'SV_POSITION' is unsupported in 'vertex' shaders, requires pixel}} float4 main(float4 a : SV_Position) { return a; } diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index d63e79a5f5155..c4193110bee01 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,9 @@ 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) { @@ -3270,7 +3276,8 @@ static const AttrClassDescriptor AttrClassDescriptors[] = { {"INHERITABLE_PARAM_ATTR", "InheritableParamAttr"}, {"INHERITABLE_PARAM_OR_STMT_ATTR", "InheritableParamOrStmtAttr"}, {"PARAMETER_ABI_ATTR", "ParameterABIAttr"}, - {"HLSL_ANNOTATION_ATTR", "HLSLAnnotationAttr"}}; + {"HLSL_ANNOTATION_ATTR", "HLSLAnnotationAttr"}, + {"HLSL_SEMANTIC_ATTR", "HLSLSemanticAttr"}}; static void emitDefaultDefine(raw_ostream &OS, StringRef name, const char *superName) {