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 std::optional<llvm::dxbc::StaticSamplerFlags> Flags;
134 };
135 std::optional<ParsedStaticSamplerParams> parseStaticSamplerParams();
136
137 // Common parsing methods
138 std::optional<uint32_t> parseUIntParam();
139 std::optional<llvm::hlsl::rootsig::Register> parseRegister();
140 std::optional<float> parseFloatParam();
141
142 /// Parsing methods of various enums
143 std::optional<llvm::dxbc::ShaderVisibility>
144 parseShaderVisibility(RootSignatureToken::Kind Context);
145 std::optional<llvm::dxbc::SamplerFilter>
146 parseSamplerFilter(RootSignatureToken::Kind Context);
147 std::optional<llvm::dxbc::TextureAddressMode>
148 parseTextureAddressMode(RootSignatureToken::Kind Context);
149 std::optional<llvm::dxbc::ComparisonFunc>
150 parseComparisonFunc(RootSignatureToken::Kind Context);
151 std::optional<llvm::dxbc::StaticBorderColor>
152 parseStaticBorderColor(RootSignatureToken::Kind Context);
153 std::optional<llvm::dxbc::RootDescriptorFlags>
154 parseRootDescriptorFlags(RootSignatureToken::Kind Context);
155 std::optional<llvm::dxbc::DescriptorRangeFlags>
156 parseDescriptorRangeFlags(RootSignatureToken::Kind Context);
157 std::optional<llvm::dxbc::StaticSamplerFlags>
158 parseStaticSamplerFlags(RootSignatureToken::Kind Context);
159
160 /// Use NumericLiteralParser to convert CurToken.NumSpelling into a unsigned
161 /// 32-bit integer
162 std::optional<uint32_t> handleUIntLiteral();
163 /// Use NumericLiteralParser to convert CurToken.NumSpelling into a signed
164 /// 32-bit integer
165 std::optional<int32_t> handleIntLiteral(bool Negated);
166 /// Use NumericLiteralParser to convert CurToken.NumSpelling into a float
167 ///
168 /// This matches the behaviour of DXC, which is as follows:
169 /// - convert the spelling with `strtod`
170 /// - check for a float overflow
171 /// - cast the double to a float
172 /// The behaviour of `strtod` is replicated using:
173 /// Semantics: llvm::APFloat::Semantics::S_IEEEdouble
174 /// RoundingMode: llvm::RoundingMode::NearestTiesToEven
175 std::optional<float> handleFloatLiteral(bool Negated);
176
177 /// Flags may specify the value of '0' to denote that there should be no
178 /// flags set.
179 ///
180 /// Return true if the current int_literal token is '0', otherwise false
181 bool verifyZeroFlag();
182
183 /// Invoke the Lexer to consume a token and update CurToken with the result
184 void consumeNextToken() { CurToken = Lexer.consumeToken(); }
185
186 /// Return true if the next token one of the expected kinds
187 bool peekExpectedToken(RootSignatureToken::Kind Expected);
188 bool peekExpectedToken(ArrayRef<RootSignatureToken::Kind> AnyExpected);
189
190 /// Consumes the next token and report an error if it is not of the expected
191 /// kind.
192 ///
193 /// Returns true if there was an error reported.
194 bool consumeExpectedToken(
195 RootSignatureToken::Kind Expected, unsigned DiagID = diag::err_expected,
196 RootSignatureToken::Kind Context = RootSignatureToken::Kind::invalid);
197
198 /// Peek if the next token is of the expected kind and if it is then consume
199 /// it.
200 ///
201 /// Returns true if it successfully matches the expected kind and the token
202 /// was consumed.
203 bool tryConsumeExpectedToken(RootSignatureToken::Kind Expected);
204 bool tryConsumeExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);
205
206 /// Consume tokens until the expected token has been peeked to be next
207 /// or we have reached the end of the stream. Note that this means the
208 /// expected token will be the next token not CurToken.
209 ///
210 /// Returns true if it found a token of the given type.
211 bool skipUntilExpectedToken(RootSignatureToken::Kind Expected);
212 bool skipUntilExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);
213
214 /// Consume tokens until we reach a closing right paren, ')', or, until we
215 /// have reached the end of the stream. This will place the current token
216 /// to be the end of stream or the right paren.
217 ///
218 /// Returns true if it is closed before the end of stream.
219 bool skipUntilClosedParens(uint32_t NumParens = 1);
220
221 /// Convert the token's offset in the signature string to its SourceLocation
222 ///
223 /// This allows to currently retrieve the location for multi-token
224 /// StringLiterals
225 SourceLocation getTokenLocation(RootSignatureToken Tok);
226
227 /// Construct a diagnostics at the location of the current token
228 DiagnosticBuilder reportDiag(unsigned DiagID) {
229 return getDiags().Report(getTokenLocation(CurToken), DiagID);
230 }
231
232private:
233 llvm::dxbc::RootSignatureVersion Version;
234 SmallVector<RootSignatureElement> Elements;
235 StringLiteral *Signature;
236 RootSignatureLexer Lexer;
237 Preprocessor &PP;
238
239 RootSignatureToken CurToken;
240};
241
242IdentifierInfo *ParseHLSLRootSignature(Sema &Actions,
243 llvm::dxbc::RootSignatureVersion Version,
244 StringLiteral *Signature);
245
246void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig);
247
248} // namespace hlsl
249} // namespace clang
250
251#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:232
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