clang 22.0.0git
ParseHLSLRootSignature.h
Go to the documentation of this file.
1//===--- ParseHLSLRootSignature.h -------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the RootSignatureParser interface.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H
14#define LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H
15
16#include "clang/AST/Expr.h"
20#include "clang/Sema/SemaHLSL.h"
21
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/StringRef.h"
24
25#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
26
27namespace clang {
28namespace hlsl {
29
31public:
32 RootSignatureParser(llvm::dxbc::RootSignatureVersion Version,
33 StringLiteral *Signature, Preprocessor &PP);
34
35 /// Consumes tokens from the Lexer and constructs the in-memory
36 /// representations of the RootElements. Tokens are consumed until an
37 /// error is encountered or the end of the buffer.
38 ///
39 /// Returns true if a parsing error is encountered.
40 bool parse();
41
42 /// Return all elements that have been parsed.
44
45private:
46 DiagnosticsEngine &getDiags() { return PP.getDiagnostics(); }
47
48 // All private parse.* methods follow a similar pattern:
49 // - Each method will start with an assert to denote what the CurToken is
50 // expected to be and will parse from that token forward
51 //
52 // - Therefore, it is the callers responsibility to ensure that you are
53 // at the correct CurToken. This should be done with the pattern of:
54 //
55 // if (tryConsumeExpectedToken(RootSignatureToken::Kind)) {
56 // auto ParsedObject = parse.*();
57 // if (!ParsedObject.has_value())
58 // return std::nullopt;
59 // ...
60 // }
61 //
62 // or,
63 //
64 // if (consumeExpectedToken(RootSignatureToken::Kind, ...))
65 // return std::nullopt;
66 // auto ParsedObject = parse.*();
67 // if (!ParsedObject.has_value())
68 // return std::nullopt;
69 // ...
70 //
71 // - All methods return std::nullopt if a parsing error is encountered. It
72 // is the callers responsibility to propogate this error up, or deal with it
73 // otherwise
74 //
75 // - An error will be raised if the proceeding tokens are not what is
76 // expected, or, there is a lexing error
77
78 /// Root Element parse methods:
79 std::optional<llvm::dxbc::RootFlags> parseRootFlags();
80 std::optional<llvm::hlsl::rootsig::RootConstants> parseRootConstants();
81 std::optional<llvm::hlsl::rootsig::RootDescriptor> parseRootDescriptor();
82 std::optional<llvm::hlsl::rootsig::DescriptorTable> parseDescriptorTable();
83 std::optional<llvm::hlsl::rootsig::DescriptorTableClause>
84 parseDescriptorTableClause();
85 std::optional<llvm::hlsl::rootsig::StaticSampler> parseStaticSampler();
86
87 /// Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
88 /// order and only exactly once. The following methods define a
89 /// `Parsed.*Params` struct to denote the current state of parsed params
90 struct ParsedConstantParams {
91 std::optional<llvm::hlsl::rootsig::Register> Reg;
92 std::optional<uint32_t> Num32BitConstants;
93 std::optional<uint32_t> Space;
94 std::optional<llvm::dxbc::ShaderVisibility> Visibility;
95 };
96 std::optional<ParsedConstantParams> parseRootConstantParams();
97
98 struct ParsedRootDescriptorParams {
99 std::optional<llvm::hlsl::rootsig::Register> Reg;
100 std::optional<uint32_t> Space;
101 std::optional<llvm::dxbc::ShaderVisibility> Visibility;
102 std::optional<llvm::dxbc::RootDescriptorFlags> Flags;
103 };
104 std::optional<ParsedRootDescriptorParams>
105 parseRootDescriptorParams(RootSignatureToken::Kind DescKind,
107
108 struct ParsedClauseParams {
109 std::optional<llvm::hlsl::rootsig::Register> Reg;
110 std::optional<uint32_t> NumDescriptors;
111 std::optional<uint32_t> Space;
112 std::optional<uint32_t> Offset;
113 std::optional<llvm::dxbc::DescriptorRangeFlags> Flags;
114 };
115 std::optional<ParsedClauseParams>
116 parseDescriptorTableClauseParams(RootSignatureToken::Kind ClauseKind,
118
119 struct ParsedStaticSamplerParams {
120 std::optional<llvm::hlsl::rootsig::Register> Reg;
121 std::optional<llvm::dxbc::SamplerFilter> Filter;
122 std::optional<llvm::dxbc::TextureAddressMode> AddressU;
123 std::optional<llvm::dxbc::TextureAddressMode> AddressV;
124 std::optional<llvm::dxbc::TextureAddressMode> AddressW;
125 std::optional<float> MipLODBias;
126 std::optional<uint32_t> MaxAnisotropy;
127 std::optional<llvm::dxbc::ComparisonFunc> CompFunc;
128 std::optional<llvm::dxbc::StaticBorderColor> BorderColor;
129 std::optional<float> MinLOD;
130 std::optional<float> MaxLOD;
131 std::optional<uint32_t> Space;
132 std::optional<llvm::dxbc::ShaderVisibility> Visibility;
133 };
134 std::optional<ParsedStaticSamplerParams> parseStaticSamplerParams();
135
136 // Common parsing methods
137 std::optional<uint32_t> parseUIntParam();
138 std::optional<llvm::hlsl::rootsig::Register> parseRegister();
139 std::optional<float> parseFloatParam();
140
141 /// Parsing methods of various enums
142 std::optional<llvm::dxbc::ShaderVisibility>
143 parseShaderVisibility(RootSignatureToken::Kind Context);
144 std::optional<llvm::dxbc::SamplerFilter>
145 parseSamplerFilter(RootSignatureToken::Kind Context);
146 std::optional<llvm::dxbc::TextureAddressMode>
147 parseTextureAddressMode(RootSignatureToken::Kind Context);
148 std::optional<llvm::dxbc::ComparisonFunc>
149 parseComparisonFunc(RootSignatureToken::Kind Context);
150 std::optional<llvm::dxbc::StaticBorderColor>
151 parseStaticBorderColor(RootSignatureToken::Kind Context);
152 std::optional<llvm::dxbc::RootDescriptorFlags>
153 parseRootDescriptorFlags(RootSignatureToken::Kind Context);
154 std::optional<llvm::dxbc::DescriptorRangeFlags>
155 parseDescriptorRangeFlags(RootSignatureToken::Kind Context);
156
157 /// Use NumericLiteralParser to convert CurToken.NumSpelling into a unsigned
158 /// 32-bit integer
159 std::optional<uint32_t> handleUIntLiteral();
160 /// Use NumericLiteralParser to convert CurToken.NumSpelling into a signed
161 /// 32-bit integer
162 std::optional<int32_t> handleIntLiteral(bool Negated);
163 /// Use NumericLiteralParser to convert CurToken.NumSpelling into a float
164 ///
165 /// This matches the behaviour of DXC, which is as follows:
166 /// - convert the spelling with `strtod`
167 /// - check for a float overflow
168 /// - cast the double to a float
169 /// The behaviour of `strtod` is replicated using:
170 /// Semantics: llvm::APFloat::Semantics::S_IEEEdouble
171 /// RoundingMode: llvm::RoundingMode::NearestTiesToEven
172 std::optional<float> handleFloatLiteral(bool Negated);
173
174 /// Flags may specify the value of '0' to denote that there should be no
175 /// flags set.
176 ///
177 /// Return true if the current int_literal token is '0', otherwise false
178 bool verifyZeroFlag();
179
180 /// Invoke the Lexer to consume a token and update CurToken with the result
181 void consumeNextToken() { CurToken = Lexer.consumeToken(); }
182
183 /// Return true if the next token one of the expected kinds
184 bool peekExpectedToken(RootSignatureToken::Kind Expected);
185 bool peekExpectedToken(ArrayRef<RootSignatureToken::Kind> AnyExpected);
186
187 /// Consumes the next token and report an error if it is not of the expected
188 /// kind.
189 ///
190 /// Returns true if there was an error reported.
191 bool consumeExpectedToken(
192 RootSignatureToken::Kind Expected, unsigned DiagID = diag::err_expected,
193 RootSignatureToken::Kind Context = RootSignatureToken::Kind::invalid);
194
195 /// Peek if the next token is of the expected kind and if it is then consume
196 /// it.
197 ///
198 /// Returns true if it successfully matches the expected kind and the token
199 /// was consumed.
200 bool tryConsumeExpectedToken(RootSignatureToken::Kind Expected);
201 bool tryConsumeExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);
202
203 /// Consume tokens until the expected token has been peeked to be next
204 /// or we have reached the end of the stream. Note that this means the
205 /// expected token will be the next token not CurToken.
206 ///
207 /// Returns true if it found a token of the given type.
208 bool skipUntilExpectedToken(RootSignatureToken::Kind Expected);
209 bool skipUntilExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);
210
211 /// Consume tokens until we reach a closing right paren, ')', or, until we
212 /// have reached the end of the stream. This will place the current token
213 /// to be the end of stream or the right paren.
214 ///
215 /// Returns true if it is closed before the end of stream.
216 bool skipUntilClosedParens(uint32_t NumParens = 1);
217
218 /// Convert the token's offset in the signature string to its SourceLocation
219 ///
220 /// This allows to currently retrieve the location for multi-token
221 /// StringLiterals
222 SourceLocation getTokenLocation(RootSignatureToken Tok);
223
224 /// Construct a diagnostics at the location of the current token
225 DiagnosticBuilder reportDiag(unsigned DiagID) {
226 return getDiags().Report(getTokenLocation(CurToken), DiagID);
227 }
228
229private:
230 llvm::dxbc::RootSignatureVersion Version;
231 SmallVector<RootSignatureElement> Elements;
232 StringLiteral *Signature;
233 RootSignatureLexer Lexer;
234 Preprocessor &PP;
235
236 RootSignatureToken CurToken;
237};
238
239IdentifierInfo *ParseHLSLRootSignature(Sema &Actions,
240 llvm::dxbc::RootSignatureVersion Version,
241 StringLiteral *Signature);
242
243void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig);
244
245} // namespace hlsl
246} // namespace clang
247
248#endif // LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H
Token Tok
The Token.
Defines the clang::Preprocessor interface.
This file declares semantic analysis for HLSL constructs.
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:231
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
DiagnosticsEngine & getDiagnostics() const
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1799
ArrayRef< RootSignatureElement > getElements()
Return all elements that have been parsed.
bool parse()
Consumes tokens from the Lexer and constructs the in-memory representations of the RootElements.
RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature, Preprocessor &PP)
void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig)
IdentifierInfo * ParseHLSLRootSignature(Sema &Actions, llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature)
The JSON file list parser is used to communicate input to InstallAPI.
Visibility
Describes the different kinds of visibility that a declaration may have.
Definition Visibility.h:34