1//=== LexHLSLRootSignatureTest.cpp - Lex Root Signature tests -------------===//
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#include "clang/Lex/LexHLSLRootSignature.h"
10#include "gtest/gtest.h"
11
12using namespace clang;
13using TokenKind = hlsl::RootSignatureToken::Kind;
14
15namespace {
16
17// The test fixture.
18class LexHLSLRootSignatureTest : public ::testing::Test {
19protected:
20 LexHLSLRootSignatureTest() {}
21
22 void checkTokens(hlsl::RootSignatureLexer &Lexer,
23 SmallVector<hlsl::RootSignatureToken> &Computed,
24 SmallVector<TokenKind> &Expected) {
25 for (unsigned I = 0, E = Expected.size(); I != E; ++I) {
26 // Skip these to help with the macro generated test
27 if (Expected[I] == TokenKind::invalid ||
28 Expected[I] == TokenKind::end_of_stream)
29 continue;
30 hlsl::RootSignatureToken Result = Lexer.consumeToken();
31 ASSERT_EQ(Result.TokKind, Expected[I]);
32 Computed.push_back(Elt: Result);
33 }
34 hlsl::RootSignatureToken EndOfStream = Lexer.consumeToken();
35 ASSERT_EQ(EndOfStream.TokKind, TokenKind::end_of_stream);
36 ASSERT_TRUE(Lexer.isEndOfBuffer());
37 }
38};
39
40// Lexing Tests
41
42TEST_F(LexHLSLRootSignatureTest, ValidLexNumbersTest) {
43 // This test will check that we can lex different number tokens
44 const llvm::StringLiteral Source = R"cc(
45 -42 42 +42 +2147483648
46 42. 4.2 .42
47 42f 4.2F
48 .42e+3 4.2E-12
49 42.e+10f
50 )cc";
51
52 auto TokLoc = SourceLocation();
53
54 hlsl::RootSignatureLexer Lexer(Source, TokLoc);
55
56 SmallVector<hlsl::RootSignatureToken> Tokens;
57 SmallVector<TokenKind> Expected = {
58 TokenKind::pu_minus, TokenKind::int_literal,
59 TokenKind::int_literal, TokenKind::pu_plus,
60 TokenKind::int_literal, TokenKind::pu_plus,
61 TokenKind::int_literal, TokenKind::float_literal,
62 TokenKind::float_literal, TokenKind::float_literal,
63 TokenKind::float_literal, TokenKind::float_literal,
64 TokenKind::float_literal, TokenKind::float_literal,
65 TokenKind::float_literal,
66 };
67 checkTokens(Lexer, Computed&: Tokens, Expected);
68
69 // Sample negative: int component
70 hlsl::RootSignatureToken IntToken = Tokens[1];
71 ASSERT_EQ(IntToken.NumSpelling, "42");
72
73 // Sample unsigned int
74 IntToken = Tokens[2];
75 ASSERT_EQ(IntToken.NumSpelling, "42");
76
77 // Sample positive: int component
78 IntToken = Tokens[4];
79 ASSERT_EQ(IntToken.NumSpelling, "42");
80
81 // Sample positive int that would overflow the signed representation but
82 // is treated as an unsigned integer instead
83 IntToken = Tokens[6];
84 ASSERT_EQ(IntToken.NumSpelling, "2147483648");
85
86 // Sample decimal end
87 hlsl::RootSignatureToken FloatToken = Tokens[7];
88 ASSERT_EQ(FloatToken.NumSpelling, "42.");
89
90 // Sample decimal middle
91 FloatToken = Tokens[8];
92 ASSERT_EQ(FloatToken.NumSpelling, "4.2");
93
94 // Sample decimal start
95 FloatToken = Tokens[9];
96 ASSERT_EQ(FloatToken.NumSpelling, ".42");
97
98 // Sample float lower
99 FloatToken = Tokens[10];
100 ASSERT_EQ(FloatToken.NumSpelling, "42f");
101
102 // Sample float upper
103 FloatToken = Tokens[11];
104 ASSERT_EQ(FloatToken.NumSpelling, "4.2F");
105
106 // Sample exp +
107 FloatToken = Tokens[12];
108 ASSERT_EQ(FloatToken.NumSpelling, ".42e+3");
109
110 // Sample exp -
111 FloatToken = Tokens[13];
112 ASSERT_EQ(FloatToken.NumSpelling, "4.2E-12");
113
114 // Sample all combined
115 FloatToken = Tokens[14];
116 ASSERT_EQ(FloatToken.NumSpelling, "42.e+10f");
117}
118
119TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) {
120 // This test will check that we can lex all defined tokens as defined in
121 // HLSLRootSignatureTokenKinds.def, plus some additional integer variations
122 const llvm::StringLiteral Source = R"cc(
123 42 42.0f
124
125 b0 t43 u987 s234
126
127 (),|=+-
128
129 RootSignature
130
131 RootFlags DescriptorTable RootConstants StaticSampler
132
133 num32BitConstants
134
135 CBV SRV UAV Sampler
136 space visibility flags
137 numDescriptors offset
138
139 filter mipLODBias addressU addressV addressW
140 maxAnisotropy comparisonFunc borderColor
141 minLOD maxLOD
142
143 unbounded
144 DESCRIPTOR_RANGE_OFFSET_APPEND
145
146 allow_input_assembler_input_layout
147 deny_vertex_shader_root_access
148 deny_hull_shader_root_access
149 deny_domain_shader_root_access
150 deny_geometry_shader_root_access
151 deny_pixel_shader_root_access
152 deny_amplification_shader_root_access
153 deny_mesh_shader_root_access
154 allow_stream_output
155 local_root_signature
156 cbv_srv_uav_heap_directly_indexed
157 sampler_heap_directly_indexed
158
159 DATA_VOLATILE
160 DATA_STATIC_WHILE_SET_AT_EXECUTE
161 DATA_STATIC
162 DESCRIPTORS_VOLATILE
163 DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS
164
165 shader_visibility_all
166 shader_visibility_vertex
167 shader_visibility_hull
168 shader_visibility_domain
169 shader_visibility_geometry
170 shader_visibility_pixel
171 shader_visibility_amplification
172 shader_visibility_mesh
173
174 FILTER_MIN_MAG_MIP_POINT
175 FILTER_MIN_MAG_POINT_MIP_LINEAR
176 FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT
177 FILTER_MIN_POINT_MAG_MIP_LINEAR
178 FILTER_MIN_LINEAR_MAG_MIP_POINT
179 FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR
180 FILTER_MIN_MAG_LINEAR_MIP_POINT
181 FILTER_MIN_MAG_MIP_LINEAR
182 FILTER_ANISOTROPIC
183 FILTER_COMPARISON_MIN_MAG_MIP_POINT
184 FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR
185 FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT
186 FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR
187 FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT
188 FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR
189 FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT
190 FILTER_COMPARISON_MIN_MAG_MIP_LINEAR
191 FILTER_COMPARISON_ANISOTROPIC
192 FILTER_MINIMUM_MIN_MAG_MIP_POINT
193 FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR
194 FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT
195 FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR
196 FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT
197 FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR
198 FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT
199 FILTER_MINIMUM_MIN_MAG_MIP_LINEAR
200 FILTER_MINIMUM_ANISOTROPIC
201 FILTER_MAXIMUM_MIN_MAG_MIP_POINT
202 FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR
203 FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT
204 FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR
205 FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT
206 FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR
207 FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT
208 FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR
209 FILTER_MAXIMUM_ANISOTROPIC
210
211 TEXTURE_ADDRESS_WRAP
212 TEXTURE_ADDRESS_MIRROR
213 TEXTURE_ADDRESS_CLAMP
214 TEXTURE_ADDRESS_BORDER
215 TEXTURE_ADDRESS_MIRRORONCE
216
217 comparison_never
218 comparison_less
219 comparison_equal
220 comparison_less_equal
221 comparison_greater
222 comparison_not_equal
223 comparison_greater_equal
224 comparison_always
225
226 STATIC_BORDER_COLOR_TRANSPARENT_BLACK
227 STATIC_BORDER_COLOR_OPAQUE_BLACK
228 STATIC_BORDER_COLOR_OPAQUE_WHITE
229 STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT
230 STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT
231 )cc";
232 auto TokLoc = SourceLocation();
233 hlsl::RootSignatureLexer Lexer(Source, TokLoc);
234
235 SmallVector<hlsl::RootSignatureToken> Tokens;
236 SmallVector<TokenKind> Expected = {
237#define TOK(NAME, SPELLING) TokenKind::NAME,
238#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
239 };
240
241 checkTokens(Lexer, Computed&: Tokens, Expected);
242}
243
244TEST_F(LexHLSLRootSignatureTest, ValidCaseInsensitiveKeywordsTest) {
245 // This test will check that we can lex keywords in an case-insensitive
246 // manner
247 const llvm::StringLiteral Source = R"cc(
248 DeScRiPtOrTaBlE
249
250 CBV srv UAV sampler
251 SPACE visibility FLAGS
252 numDescriptors OFFSET
253 )cc";
254 auto TokLoc = SourceLocation();
255 hlsl::RootSignatureLexer Lexer(Source, TokLoc);
256
257 SmallVector<hlsl::RootSignatureToken> Tokens;
258 SmallVector<TokenKind> Expected = {
259 TokenKind::kw_DescriptorTable,
260 TokenKind::kw_CBV,
261 TokenKind::kw_SRV,
262 TokenKind::kw_UAV,
263 TokenKind::kw_Sampler,
264 TokenKind::kw_space,
265 TokenKind::kw_visibility,
266 TokenKind::kw_flags,
267 TokenKind::kw_numDescriptors,
268 TokenKind::kw_offset,
269 };
270
271 checkTokens(Lexer, Computed&: Tokens, Expected);
272}
273
274TEST_F(LexHLSLRootSignatureTest, ValidLexPeekTest) {
275 // This test will check that we the peek api is correctly used
276 const llvm::StringLiteral Source = R"cc(
277 )1
278 )cc";
279 auto TokLoc = SourceLocation();
280 hlsl::RootSignatureLexer Lexer(Source, TokLoc);
281
282 // Test basic peek
283 hlsl::RootSignatureToken Res = Lexer.peekNextToken();
284 ASSERT_EQ(Res.TokKind, TokenKind::pu_r_paren);
285
286 // Ensure it doesn't peek past one element
287 Res = Lexer.peekNextToken();
288 ASSERT_EQ(Res.TokKind, TokenKind::pu_r_paren);
289
290 Res = Lexer.consumeToken();
291 ASSERT_EQ(Res.TokKind, TokenKind::pu_r_paren);
292
293 // Invoke after reseting the NextToken
294 Res = Lexer.peekNextToken();
295 ASSERT_EQ(Res.TokKind, TokenKind::int_literal);
296
297 // Ensure we can still consume the second token
298 Res = Lexer.consumeToken();
299 ASSERT_EQ(Res.TokKind, TokenKind::int_literal);
300
301 // Ensure end of stream token
302 Res = Lexer.peekNextToken();
303 ASSERT_EQ(Res.TokKind, TokenKind::end_of_stream);
304}
305
306} // anonymous namespace
307

source code of clang/unittests/Lex/LexHLSLRootSignatureTest.cpp