beanz created this revision. beanz added reviewers: MaskRay, jdoerfert, kuhar, rnk, aaron.ballman, rsmith. Herald added subscribers: StephenFan, arphaman, mgorny. Herald added a project: All. beanz requested review of this revision. Herald added a project: clang.
HLSL has a language feature called Semantics which get attached to declarations like attributes and are used in a variety of ways. One example of semantic use is here with the `SV_GroupIndex` semantic which, when applied to an input for a compute shader is pre-populated by the driver with a flattened thread index. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D122699 Files: clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/AttributeCommonInfo.h clang/include/clang/Basic/Attributes.h clang/include/clang/Parse/Parser.h clang/lib/Parse/CMakeLists.txt clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/ParseHLSL.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/test/SemaHLSL/Semantics/entry_parameter.hlsl clang/utils/TableGen/ClangAttrEmitter.cpp
Index: clang/utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangAttrEmitter.cpp +++ clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1493,6 +1493,9 @@ Spelling += Namespace; Spelling += " "; } + } else if (Variety == "HLSLSemantic") { + Prefix = ":"; + Suffix = ""; } else { llvm_unreachable("Unknown attribute syntax variety!"); } @@ -3300,7 +3303,7 @@ // Separate all of the attributes out into four group: generic, C++11, GNU, // and declspecs. Then generate a big switch statement for each of them. std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); - std::vector<Record *> Declspec, Microsoft, GNU, Pragma; + std::vector<Record *> Declspec, Microsoft, GNU, Pragma, HLSLSemantic; std::map<std::string, std::vector<Record *>> CXX, C2x; // Walk over the list of all attributes, and split them out based on the @@ -3321,6 +3324,8 @@ C2x[SI.nameSpace()].push_back(R); else if (Variety == "Pragma") Pragma.push_back(R); + else if (Variety == "HLSLSemantic") + HLSLSemantic.push_back(R); } } @@ -3338,6 +3343,9 @@ OS << "case AttrSyntax::Pragma:\n"; OS << " return llvm::StringSwitch<int>(Name)\n"; GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma"); + OS << "case AttrSyntax::HLSLSemantic:\n"; + OS << " return llvm::StringSwitch<int>(Name)\n"; + GenerateHasAttrSpellingStringSwitch(HLSLSemantic, OS, "HLSLSemantic"); auto fn = [&OS](const char *Spelling, const char *Variety, const std::map<std::string, std::vector<Record *>> &List) { OS << "case AttrSyntax::" << Variety << ": {\n"; @@ -4286,7 +4294,7 @@ std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11, - Keywords, Pragma, C2x; + Keywords, Pragma, C2x, HLSLSemantic; std::set<std::string> Seen; for (const auto *A : Attrs) { const Record &Attr = *A; @@ -4338,6 +4346,8 @@ Matches = &Keywords; else if (Variety == "Pragma") Matches = &Pragma; + else if (Variety == "HLSLSemantic") + Matches = &HLSLSemantic; assert(Matches && "Unsupported spelling variety found"); @@ -4373,6 +4383,8 @@ StringMatcher("Name", Keywords, OS).Emit(); OS << " } else if (AttributeCommonInfo::AS_Pragma == Syntax) {\n"; StringMatcher("Name", Pragma, OS).Emit(); + OS << " } else if (AttributeCommonInfo::AS_HLSLSemantic == Syntax) {\n"; + StringMatcher("Name", HLSLSemantic, OS).Emit(); OS << " }\n"; OS << " return AttributeCommonInfo::UnknownAttribute;\n" << "}\n"; @@ -4482,7 +4494,7 @@ } } -enum class SpellingKind { +enum class SpellingKind : size_t { GNU, CXX11, C2x, @@ -4490,8 +4502,10 @@ Microsoft, Keyword, Pragma, + HLSLSemantic, + NumSpellingKinds }; -static const size_t NumSpellingKinds = (size_t)SpellingKind::Pragma + 1; +static const size_t NumSpellingKinds = (size_t)SpellingKind::NumSpellingKinds; class SpellingList { std::vector<std::string> Spellings[NumSpellingKinds]; @@ -4509,7 +4523,8 @@ .Case("Declspec", SpellingKind::Declspec) .Case("Microsoft", SpellingKind::Microsoft) .Case("Keyword", SpellingKind::Keyword) - .Case("Pragma", SpellingKind::Pragma); + .Case("Pragma", SpellingKind::Pragma) + .Case("HLSLSemantic", SpellingKind::HLSLSemantic); std::string Name; if (!Spelling.nameSpace().empty()) { switch (Kind) { @@ -4610,8 +4625,8 @@ // List what spelling syntaxes the attribute supports. OS << ".. csv-table:: Supported Syntaxes\n"; OS << " :header: \"GNU\", \"C++11\", \"C2x\", \"``__declspec``\","; - OS << " \"Keyword\", \"``#pragma``\", \"``#pragma clang attribute``\"\n\n"; - OS << " \""; + OS << " \"Keyword\", \"``#pragma``\", \"``#pragma clang attribute``\","; + OS << " \"HLSL Semantic\"\n\n \""; for (size_t Kind = 0; Kind != NumSpellingKinds; ++Kind) { SpellingKind K = (SpellingKind)Kind; // TODO: List Microsoft (IDL-style attribute) spellings once we fully Index: clang/test/SemaHLSL/Semantics/entry_parameter.hlsl =================================================================== --- /dev/null +++ clang/test/SemaHLSL/Semantics/entry_parameter.hlsl @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-mesh -x hlsl -ast-dump -verify -o - %s + +[numthreads(8,8, 1)] +// expected-error@+1 {{attribute 'SV_GroupIndex' is unsupported in Mesh shaders, requires Compute}} +void CSMain(int GI : SV_GroupIndex) { +// CHECK: FunctionDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-1]]:6 CSMain 'void (int)' +// CHECK-NEXT: ParmVarDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:17 GI 'int' +// CHECK-NEXT: HLSLSV_GroupIndexAttr +} Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -6895,6 +6895,21 @@ D->addAttr(::new (S.Context) HLSLNumThreadsAttr(S.Context, AL, X, Y, Z)); } +static void handleHLSLSVGroupIndexAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + using llvm::Triple; + Triple Target = S.Context.getTargetInfo().getTriple(); + if (Target.getEnvironment() != Triple::Compute) { + uint32_t Pipeline = + (uint32_t)S.Context.getTargetInfo().getTriple().getEnvironment() - + (uint32_t)llvm::Triple::Pixel; + S.Diag(AL.getLoc(), diag::err_hlsl_attr_unsupported_in_stage) + << AL << Pipeline << "Compute"; + return; + } + + D->addAttr(::new (S.Context) HLSLSV_GroupIndexAttr(S.Context, AL)); +} + static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.LangOpts.CPlusPlus) { S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang) @@ -8761,6 +8776,9 @@ case ParsedAttr::AT_HLSLNumThreads: handleHLSLNumThreadsAttr(S, D, AL); break; + case ParsedAttr::AT_HLSLSV_GroupIndex: + handleHLSLSVGroupIndexAttr(S, D, AL); + break; case ParsedAttr::AT_AbiTag: handleAbiTagAttr(S, D, AL); Index: clang/lib/Parse/ParseHLSL.cpp =================================================================== --- /dev/null +++ clang/lib/Parse/ParseHLSL.cpp @@ -0,0 +1,37 @@ +//===--- ParseHLSL.cpp - HLSL-specific parsing support --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the parsing logic for HLSL language features. +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/AttributeCommonInfo.h" +#include "clang/Parse/Parser.h" + +using namespace clang; + +void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs, + SourceLocation *EndLoc) { + assert(Tok.is(tok::colon) && "Not a HLSL Semantic"); + ConsumeToken(); + + IdentifierInfo *II = Tok.getIdentifierInfo(); + SourceLocation Loc = ConsumeToken(); + if (EndLoc) + *EndLoc = Tok.getLocation(); + ParsedAttr::Kind AttrKind = + ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLSemantic); + + if (AttrKind == ParsedAttr::UnknownAttribute || + AttrKind == ParsedAttr::IgnoredAttribute) { + ConsumeToken(); + return; + } + Attrs.addNew(II, Loc, nullptr, SourceLocation(), nullptr, 0, + ParsedAttr::AS_HLSLSemantic); +} Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -6963,6 +6963,7 @@ // Parse GNU attributes, if present. MaybeParseGNUAttributes(ParmDeclarator); + MaybeParseHLSLSemantics(DS.getAttributes()); if (Tok.is(tok::kw_requires)) { // User tried to define a requires clause in a parameter declaration, Index: clang/lib/Parse/CMakeLists.txt =================================================================== --- clang/lib/Parse/CMakeLists.txt +++ clang/lib/Parse/CMakeLists.txt @@ -12,6 +12,7 @@ ParseDeclCXX.cpp ParseExpr.cpp ParseExprCXX.cpp + ParseHLSL.cpp ParseInit.cpp ParseObjc.cpp ParseOpenMP.cpp Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -2782,6 +2782,15 @@ Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None, const IdentifierInfo *EnclosingScope = nullptr); + void MaybeParseHLSLSemantics(ParsedAttributes &attrs, + SourceLocation *endLoc = nullptr) { + if (getLangOpts().HLSL && Tok.is(tok::colon)) + ParseHLSLSemantics(attrs, endLoc); + } + + void ParseHLSLSemantics(ParsedAttributes &attrs, + SourceLocation *endLoc = nullptr); + void MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs) { if ((getLangOpts().MicrosoftExt || getLangOpts().HLSL) && Tok.is(tok::l_square)) { Index: clang/include/clang/Basic/Attributes.h =================================================================== --- clang/include/clang/Basic/Attributes.h +++ clang/include/clang/Basic/Attributes.h @@ -28,7 +28,9 @@ // Is the identifier known as a C-style attribute? C, // Is the identifier known as a pragma attribute? - Pragma + Pragma, + // Is the identifier known as a HLSL semantic? + HLSLSemantic, }; /// Return the version number associated with the attribute if we Index: clang/include/clang/Basic/AttributeCommonInfo.h =================================================================== --- clang/include/clang/Basic/AttributeCommonInfo.h +++ clang/include/clang/Basic/AttributeCommonInfo.h @@ -48,6 +48,9 @@ // without adding related code to TableGen/ClangAttrEmitter.cpp. /// Context-sensitive version of a keyword attribute. AS_ContextSensitiveKeyword, + + /// <vardecl> : <semantic> + AS_HLSLSemantic, }; enum Kind { #define PARSED_ATTR(NAME) AT_##NAME, Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -6379,3 +6379,14 @@ The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-attributes-numthreads }]; } + +def HLSLSV_GroupIndexDocs : Documentation { + let Category = DocCatFunction; + 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 + }]; +} Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -295,6 +295,9 @@ bit AllowInC = allowInC; } +// HLSL Semantic spellings +class HLSLSemantic<string name> : Spelling<name, "HLSLSemantic">; + class Accessor<string name, list<Spelling> spellings> { string Name = name; list<Spelling> Spellings = spellings; @@ -3947,3 +3950,10 @@ let LangOpts = [HLSL]; let Documentation = [NumThreadsDocs]; } + +def HLSLSV_GroupIndex: InheritableAttr { + let Spellings = [HLSLSemantic<"SV_GroupIndex">]; + let Subjects = SubjectList<[ParmVar, GlobalVar]>; + let LangOpts = [HLSL]; + let Documentation = [HLSLSV_GroupIndexDocs]; +}
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits