8
8
9
9
#include " clang/Parse/ParseHLSLRootSignature.h"
10
10
11
+ #include " clang/Lex/LiteralSupport.h"
12
+
11
13
#include " llvm/Support/raw_ostream.h"
12
14
13
15
using namespace llvm ::hlsl::rootsig;
@@ -41,12 +43,11 @@ bool RootSignatureParser::parse() {
41
43
break ;
42
44
}
43
45
44
- if (!tryConsumeExpectedToken (TokenKind::end_of_stream)) {
45
- getDiags ().Report (CurToken.TokLoc , diag::err_hlsl_unexpected_end_of_params)
46
- << /* expected=*/ TokenKind::end_of_stream
47
- << /* param of=*/ TokenKind::kw_RootSignature;
46
+ if (consumeExpectedToken (TokenKind::end_of_stream,
47
+ diag::err_hlsl_unexpected_end_of_params,
48
+ /* param of=*/ TokenKind::kw_RootSignature))
48
49
return true ;
49
- }
50
+
50
51
return false ;
51
52
}
52
53
@@ -72,12 +73,10 @@ bool RootSignatureParser::parseDescriptorTable() {
72
73
break ;
73
74
}
74
75
75
- if (!tryConsumeExpectedToken (TokenKind::pu_r_paren)) {
76
- getDiags ().Report (CurToken.TokLoc , diag::err_hlsl_unexpected_end_of_params)
77
- << /* expected=*/ TokenKind::pu_r_paren
78
- << /* param of=*/ TokenKind::kw_DescriptorTable;
76
+ if (consumeExpectedToken (TokenKind::pu_r_paren,
77
+ diag::err_hlsl_unexpected_end_of_params,
78
+ /* param of=*/ TokenKind::kw_DescriptorTable))
79
79
return true ;
80
- }
81
80
82
81
Elements.push_back (Table);
83
82
return false ;
@@ -90,36 +89,170 @@ bool RootSignatureParser::parseDescriptorTableClause() {
90
89
CurToken.TokKind == TokenKind::kw_Sampler) &&
91
90
" Expects to only be invoked starting at given keyword" );
92
91
92
+ TokenKind ParamKind = CurToken.TokKind ;
93
+
94
+ if (consumeExpectedToken (TokenKind::pu_l_paren, diag::err_expected_after,
95
+ CurToken.TokKind ))
96
+ return true ;
97
+
93
98
DescriptorTableClause Clause;
94
- switch (CurToken.TokKind ) {
99
+ TokenKind ExpectedReg;
100
+ switch (ParamKind) {
95
101
default :
96
102
llvm_unreachable (" Switch for consumed token was not provided" );
97
103
case TokenKind::kw_CBV:
98
104
Clause.Type = ClauseType::CBuffer;
105
+ ExpectedReg = TokenKind::bReg;
99
106
break ;
100
107
case TokenKind::kw_SRV:
101
108
Clause.Type = ClauseType::SRV;
109
+ ExpectedReg = TokenKind::tReg;
102
110
break ;
103
111
case TokenKind::kw_UAV:
104
112
Clause.Type = ClauseType::UAV;
113
+ ExpectedReg = TokenKind::uReg;
105
114
break ;
106
115
case TokenKind::kw_Sampler:
107
116
Clause.Type = ClauseType::Sampler;
117
+ ExpectedReg = TokenKind::sReg ;
108
118
break ;
109
119
}
110
120
111
- if ( consumeExpectedToken (TokenKind::pu_l_paren, diag::err_expected_after,
112
- CurToken. TokKind ))
121
+ auto Params = parseDescriptorTableClauseParams (ExpectedReg);
122
+ if (!Params. has_value ( ))
113
123
return true ;
114
124
115
- if (consumeExpectedToken (TokenKind::pu_r_paren, diag::err_expected_after,
116
- CurToken.TokKind ))
125
+ // Check mandatory parameters were provided
126
+ if (!Params->Register .has_value ()) {
127
+ getDiags ().Report (CurToken.TokLoc , diag::err_hlsl_rootsig_missing_param)
128
+ << ExpectedReg;
129
+ return true ;
130
+ }
131
+
132
+ Clause.Register = Params->Register .value ();
133
+
134
+ // Fill in optional values
135
+ if (Params->Space .has_value ())
136
+ Clause.Space = Params->Space .value ();
137
+
138
+ if (consumeExpectedToken (TokenKind::pu_r_paren,
139
+ diag::err_hlsl_unexpected_end_of_params,
140
+ /* param of=*/ ParamKind))
117
141
return true ;
118
142
119
143
Elements.push_back (Clause);
120
144
return false ;
121
145
}
122
146
147
+ std::optional<RootSignatureParser::ParsedClauseParams>
148
+ RootSignatureParser::parseDescriptorTableClauseParams (TokenKind RegType) {
149
+ assert (CurToken.TokKind == TokenKind::pu_l_paren &&
150
+ " Expects to only be invoked starting at given token" );
151
+
152
+ // Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
153
+ // order and only exactly once. Parse through as many arguments as possible
154
+ // reporting an error if a duplicate is seen.
155
+ ParsedClauseParams Params;
156
+ do {
157
+ // ( `b` | `t` | `u` | `s`) POS_INT
158
+ if (tryConsumeExpectedToken (RegType)) {
159
+ if (Params.Register .has_value ()) {
160
+ getDiags ().Report (CurToken.TokLoc , diag::err_hlsl_rootsig_repeat_param)
161
+ << CurToken.TokKind ;
162
+ return std::nullopt;
163
+ }
164
+ auto Reg = parseRegister ();
165
+ if (!Reg.has_value ())
166
+ return std::nullopt;
167
+ Params.Register = Reg;
168
+ }
169
+
170
+ // `space` `=` POS_INT
171
+ if (tryConsumeExpectedToken (TokenKind::kw_space)) {
172
+ if (Params.Space .has_value ()) {
173
+ getDiags ().Report (CurToken.TokLoc , diag::err_hlsl_rootsig_repeat_param)
174
+ << CurToken.TokKind ;
175
+ return std::nullopt;
176
+ }
177
+
178
+ if (consumeExpectedToken (TokenKind::pu_equal))
179
+ return std::nullopt;
180
+
181
+ auto Space = parseUIntParam ();
182
+ if (!Space.has_value ())
183
+ return std::nullopt;
184
+ Params.Space = Space;
185
+ }
186
+ } while (tryConsumeExpectedToken (TokenKind::pu_comma));
187
+
188
+ return Params;
189
+ }
190
+
191
+ std::optional<uint32_t > RootSignatureParser::parseUIntParam () {
192
+ assert (CurToken.TokKind == TokenKind::pu_equal &&
193
+ " Expects to only be invoked starting at given keyword" );
194
+ tryConsumeExpectedToken (TokenKind::pu_plus);
195
+ if (consumeExpectedToken (TokenKind::int_literal, diag::err_expected_after,
196
+ CurToken.TokKind ))
197
+ return std::nullopt;
198
+ return handleUIntLiteral ();
199
+ }
200
+
201
+ std::optional<Register> RootSignatureParser::parseRegister () {
202
+ assert ((CurToken.TokKind == TokenKind::bReg ||
203
+ CurToken.TokKind == TokenKind::tReg ||
204
+ CurToken.TokKind == TokenKind::uReg ||
205
+ CurToken.TokKind == TokenKind::sReg ) &&
206
+ " Expects to only be invoked starting at given keyword" );
207
+
208
+ Register Register;
209
+ switch (CurToken.TokKind ) {
210
+ default :
211
+ llvm_unreachable (" Switch for consumed token was not provided" );
212
+ case TokenKind::bReg:
213
+ Register.ViewType = RegisterType::BReg;
214
+ break ;
215
+ case TokenKind::tReg:
216
+ Register.ViewType = RegisterType::TReg;
217
+ break ;
218
+ case TokenKind::uReg:
219
+ Register.ViewType = RegisterType::UReg;
220
+ break ;
221
+ case TokenKind::sReg :
222
+ Register.ViewType = RegisterType::SReg;
223
+ break ;
224
+ }
225
+
226
+ auto Number = handleUIntLiteral ();
227
+ if (!Number.has_value ())
228
+ return std::nullopt; // propogate NumericLiteralParser error
229
+
230
+ Register.Number = *Number;
231
+ return Register;
232
+ }
233
+
234
+ std::optional<uint32_t > RootSignatureParser::handleUIntLiteral () {
235
+ // Parse the numeric value and do semantic checks on its specification
236
+ clang::NumericLiteralParser Literal (CurToken.NumSpelling , CurToken.TokLoc ,
237
+ PP.getSourceManager (), PP.getLangOpts (),
238
+ PP.getTargetInfo (), PP.getDiagnostics ());
239
+ if (Literal.hadError )
240
+ return true ; // Error has already been reported so just return
241
+
242
+ assert (Literal.isIntegerLiteral () && " IsNumberChar will only support digits" );
243
+
244
+ llvm::APSInt Val = llvm::APSInt (32 , false );
245
+ if (Literal.GetIntegerValue (Val)) {
246
+ // Report that the value has overflowed
247
+ PP.getDiagnostics ().Report (CurToken.TokLoc ,
248
+ diag::err_hlsl_number_literal_overflow)
249
+ << 0 << CurToken.NumSpelling ;
250
+ return std::nullopt;
251
+ }
252
+
253
+ return Val.getExtValue ();
254
+ }
255
+
123
256
bool RootSignatureParser::peekExpectedToken (TokenKind Expected) {
124
257
return peekExpectedToken (ArrayRef{Expected});
125
258
}
@@ -141,6 +274,7 @@ bool RootSignatureParser::consumeExpectedToken(TokenKind Expected,
141
274
case diag::err_expected:
142
275
DB << Expected;
143
276
break ;
277
+ case diag::err_hlsl_unexpected_end_of_params:
144
278
case diag::err_expected_either:
145
279
case diag::err_expected_after:
146
280
DB << Expected << Context;
0 commit comments