1 //
2 // Copyright (C) 2016 Google, Inc.
3 // Copyright (C) 2016 LunarG, Inc.
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 // Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //
14 // Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following
16 // disclaimer in the documentation and/or other materials provided
17 // with the distribution.
18 //
19 // Neither the name of Google, Inc., nor the names of its
20 // contributors may be used to endorse or promote products derived
21 // from this software without specific prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 // POSSIBILITY OF SUCH DAMAGE.
35 //
36
37 //
38 // HLSL scanning, leveraging the scanning done by the preprocessor.
39 //
40
41 #include <cstring>
42 #include <unordered_map>
43 #include <unordered_set>
44
45 #include "../glslang/Include/Types.h"
46 #include "../glslang/MachineIndependent/SymbolTable.h"
47 #include "../glslang/MachineIndependent/ParseHelper.h"
48 #include "hlslScanContext.h"
49 #include "hlslTokens.h"
50
51 // preprocessor includes
52 #include "../glslang/MachineIndependent/preprocessor/PpContext.h"
53 #include "../glslang/MachineIndependent/preprocessor/PpTokens.h"
54
55 namespace {
56
57 struct str_eq
58 {
operator ()__anon12b653b30111::str_eq59 bool operator()(const char* lhs, const char* rhs) const
60 {
61 return strcmp(lhs, rhs) == 0;
62 }
63 };
64
65 struct str_hash
66 {
operator ()__anon12b653b30111::str_hash67 size_t operator()(const char* str) const
68 {
69 // djb2
70 unsigned long hash = 5381;
71 int c;
72
73 while ((c = *str++) != 0)
74 hash = ((hash << 5) + hash) + c;
75
76 return hash;
77 }
78 };
79
80 // A single global usable by all threads, by all versions, by all languages.
81 // After a single process-level initialization, this is read only and thread safe
82 std::unordered_map<const char*, glslang::EHlslTokenClass, str_hash, str_eq>* KeywordMap = nullptr;
83 std::unordered_set<const char*, str_hash, str_eq>* ReservedSet = nullptr;
84 std::unordered_map<const char*, glslang::TBuiltInVariable, str_hash, str_eq>* SemanticMap = nullptr;
85
86 };
87
88 namespace glslang {
89
fillInKeywordMap()90 void HlslScanContext::fillInKeywordMap()
91 {
92 if (KeywordMap != nullptr) {
93 // this is really an error, as this should called only once per process
94 // but, the only risk is if two threads called simultaneously
95 return;
96 }
97 KeywordMap = new std::unordered_map<const char*, EHlslTokenClass, str_hash, str_eq>;
98
99 (*KeywordMap)["static"] = EHTokStatic;
100 (*KeywordMap)["const"] = EHTokConst;
101 (*KeywordMap)["unorm"] = EHTokUnorm;
102 (*KeywordMap)["snorm"] = EHTokSNorm;
103 (*KeywordMap)["extern"] = EHTokExtern;
104 (*KeywordMap)["uniform"] = EHTokUniform;
105 (*KeywordMap)["volatile"] = EHTokVolatile;
106 (*KeywordMap)["precise"] = EHTokPrecise;
107 (*KeywordMap)["shared"] = EHTokShared;
108 (*KeywordMap)["groupshared"] = EHTokGroupShared;
109 (*KeywordMap)["linear"] = EHTokLinear;
110 (*KeywordMap)["centroid"] = EHTokCentroid;
111 (*KeywordMap)["nointerpolation"] = EHTokNointerpolation;
112 (*KeywordMap)["noperspective"] = EHTokNoperspective;
113 (*KeywordMap)["sample"] = EHTokSample;
114 (*KeywordMap)["row_major"] = EHTokRowMajor;
115 (*KeywordMap)["column_major"] = EHTokColumnMajor;
116 (*KeywordMap)["packoffset"] = EHTokPackOffset;
117 (*KeywordMap)["in"] = EHTokIn;
118 (*KeywordMap)["out"] = EHTokOut;
119 (*KeywordMap)["inout"] = EHTokInOut;
120 (*KeywordMap)["layout"] = EHTokLayout;
121 (*KeywordMap)["globallycoherent"] = EHTokGloballyCoherent;
122 (*KeywordMap)["inline"] = EHTokInline;
123
124 (*KeywordMap)["point"] = EHTokPoint;
125 (*KeywordMap)["line"] = EHTokLine;
126 (*KeywordMap)["triangle"] = EHTokTriangle;
127 (*KeywordMap)["lineadj"] = EHTokLineAdj;
128 (*KeywordMap)["triangleadj"] = EHTokTriangleAdj;
129
130 (*KeywordMap)["PointStream"] = EHTokPointStream;
131 (*KeywordMap)["LineStream"] = EHTokLineStream;
132 (*KeywordMap)["TriangleStream"] = EHTokTriangleStream;
133
134 (*KeywordMap)["InputPatch"] = EHTokInputPatch;
135 (*KeywordMap)["OutputPatch"] = EHTokOutputPatch;
136
137 (*KeywordMap)["Buffer"] = EHTokBuffer;
138 (*KeywordMap)["vector"] = EHTokVector;
139 (*KeywordMap)["matrix"] = EHTokMatrix;
140
141 (*KeywordMap)["void"] = EHTokVoid;
142 (*KeywordMap)["string"] = EHTokString;
143 (*KeywordMap)["bool"] = EHTokBool;
144 (*KeywordMap)["int"] = EHTokInt;
145 (*KeywordMap)["uint"] = EHTokUint;
146 (*KeywordMap)["uint64_t"] = EHTokUint64;
147 (*KeywordMap)["dword"] = EHTokDword;
148 (*KeywordMap)["half"] = EHTokHalf;
149 (*KeywordMap)["float"] = EHTokFloat;
150 (*KeywordMap)["double"] = EHTokDouble;
151 (*KeywordMap)["min16float"] = EHTokMin16float;
152 (*KeywordMap)["min10float"] = EHTokMin10float;
153 (*KeywordMap)["min16int"] = EHTokMin16int;
154 (*KeywordMap)["min12int"] = EHTokMin12int;
155 (*KeywordMap)["min16uint"] = EHTokMin16uint;
156
157 (*KeywordMap)["bool1"] = EHTokBool1;
158 (*KeywordMap)["bool2"] = EHTokBool2;
159 (*KeywordMap)["bool3"] = EHTokBool3;
160 (*KeywordMap)["bool4"] = EHTokBool4;
161 (*KeywordMap)["float1"] = EHTokFloat1;
162 (*KeywordMap)["float2"] = EHTokFloat2;
163 (*KeywordMap)["float3"] = EHTokFloat3;
164 (*KeywordMap)["float4"] = EHTokFloat4;
165 (*KeywordMap)["int1"] = EHTokInt1;
166 (*KeywordMap)["int2"] = EHTokInt2;
167 (*KeywordMap)["int3"] = EHTokInt3;
168 (*KeywordMap)["int4"] = EHTokInt4;
169 (*KeywordMap)["double1"] = EHTokDouble1;
170 (*KeywordMap)["double2"] = EHTokDouble2;
171 (*KeywordMap)["double3"] = EHTokDouble3;
172 (*KeywordMap)["double4"] = EHTokDouble4;
173 (*KeywordMap)["uint1"] = EHTokUint1;
174 (*KeywordMap)["uint2"] = EHTokUint2;
175 (*KeywordMap)["uint3"] = EHTokUint3;
176 (*KeywordMap)["uint4"] = EHTokUint4;
177
178 (*KeywordMap)["half1"] = EHTokHalf1;
179 (*KeywordMap)["half2"] = EHTokHalf2;
180 (*KeywordMap)["half3"] = EHTokHalf3;
181 (*KeywordMap)["half4"] = EHTokHalf4;
182 (*KeywordMap)["min16float1"] = EHTokMin16float1;
183 (*KeywordMap)["min16float2"] = EHTokMin16float2;
184 (*KeywordMap)["min16float3"] = EHTokMin16float3;
185 (*KeywordMap)["min16float4"] = EHTokMin16float4;
186 (*KeywordMap)["min10float1"] = EHTokMin10float1;
187 (*KeywordMap)["min10float2"] = EHTokMin10float2;
188 (*KeywordMap)["min10float3"] = EHTokMin10float3;
189 (*KeywordMap)["min10float4"] = EHTokMin10float4;
190 (*KeywordMap)["min16int1"] = EHTokMin16int1;
191 (*KeywordMap)["min16int2"] = EHTokMin16int2;
192 (*KeywordMap)["min16int3"] = EHTokMin16int3;
193 (*KeywordMap)["min16int4"] = EHTokMin16int4;
194 (*KeywordMap)["min12int1"] = EHTokMin12int1;
195 (*KeywordMap)["min12int2"] = EHTokMin12int2;
196 (*KeywordMap)["min12int3"] = EHTokMin12int3;
197 (*KeywordMap)["min12int4"] = EHTokMin12int4;
198 (*KeywordMap)["min16uint1"] = EHTokMin16uint1;
199 (*KeywordMap)["min16uint2"] = EHTokMin16uint2;
200 (*KeywordMap)["min16uint3"] = EHTokMin16uint3;
201 (*KeywordMap)["min16uint4"] = EHTokMin16uint4;
202
203 (*KeywordMap)["bool1x1"] = EHTokBool1x1;
204 (*KeywordMap)["bool1x2"] = EHTokBool1x2;
205 (*KeywordMap)["bool1x3"] = EHTokBool1x3;
206 (*KeywordMap)["bool1x4"] = EHTokBool1x4;
207 (*KeywordMap)["bool2x1"] = EHTokBool2x1;
208 (*KeywordMap)["bool2x2"] = EHTokBool2x2;
209 (*KeywordMap)["bool2x3"] = EHTokBool2x3;
210 (*KeywordMap)["bool2x4"] = EHTokBool2x4;
211 (*KeywordMap)["bool3x1"] = EHTokBool3x1;
212 (*KeywordMap)["bool3x2"] = EHTokBool3x2;
213 (*KeywordMap)["bool3x3"] = EHTokBool3x3;
214 (*KeywordMap)["bool3x4"] = EHTokBool3x4;
215 (*KeywordMap)["bool4x1"] = EHTokBool4x1;
216 (*KeywordMap)["bool4x2"] = EHTokBool4x2;
217 (*KeywordMap)["bool4x3"] = EHTokBool4x3;
218 (*KeywordMap)["bool4x4"] = EHTokBool4x4;
219 (*KeywordMap)["int1x1"] = EHTokInt1x1;
220 (*KeywordMap)["int1x2"] = EHTokInt1x2;
221 (*KeywordMap)["int1x3"] = EHTokInt1x3;
222 (*KeywordMap)["int1x4"] = EHTokInt1x4;
223 (*KeywordMap)["int2x1"] = EHTokInt2x1;
224 (*KeywordMap)["int2x2"] = EHTokInt2x2;
225 (*KeywordMap)["int2x3"] = EHTokInt2x3;
226 (*KeywordMap)["int2x4"] = EHTokInt2x4;
227 (*KeywordMap)["int3x1"] = EHTokInt3x1;
228 (*KeywordMap)["int3x2"] = EHTokInt3x2;
229 (*KeywordMap)["int3x3"] = EHTokInt3x3;
230 (*KeywordMap)["int3x4"] = EHTokInt3x4;
231 (*KeywordMap)["int4x1"] = EHTokInt4x1;
232 (*KeywordMap)["int4x2"] = EHTokInt4x2;
233 (*KeywordMap)["int4x3"] = EHTokInt4x3;
234 (*KeywordMap)["int4x4"] = EHTokInt4x4;
235 (*KeywordMap)["uint1x1"] = EHTokUint1x1;
236 (*KeywordMap)["uint1x2"] = EHTokUint1x2;
237 (*KeywordMap)["uint1x3"] = EHTokUint1x3;
238 (*KeywordMap)["uint1x4"] = EHTokUint1x4;
239 (*KeywordMap)["uint2x1"] = EHTokUint2x1;
240 (*KeywordMap)["uint2x2"] = EHTokUint2x2;
241 (*KeywordMap)["uint2x3"] = EHTokUint2x3;
242 (*KeywordMap)["uint2x4"] = EHTokUint2x4;
243 (*KeywordMap)["uint3x1"] = EHTokUint3x1;
244 (*KeywordMap)["uint3x2"] = EHTokUint3x2;
245 (*KeywordMap)["uint3x3"] = EHTokUint3x3;
246 (*KeywordMap)["uint3x4"] = EHTokUint3x4;
247 (*KeywordMap)["uint4x1"] = EHTokUint4x1;
248 (*KeywordMap)["uint4x2"] = EHTokUint4x2;
249 (*KeywordMap)["uint4x3"] = EHTokUint4x3;
250 (*KeywordMap)["uint4x4"] = EHTokUint4x4;
251 (*KeywordMap)["bool1x1"] = EHTokBool1x1;
252 (*KeywordMap)["bool1x2"] = EHTokBool1x2;
253 (*KeywordMap)["bool1x3"] = EHTokBool1x3;
254 (*KeywordMap)["bool1x4"] = EHTokBool1x4;
255 (*KeywordMap)["bool2x1"] = EHTokBool2x1;
256 (*KeywordMap)["bool2x2"] = EHTokBool2x2;
257 (*KeywordMap)["bool2x3"] = EHTokBool2x3;
258 (*KeywordMap)["bool2x4"] = EHTokBool2x4;
259 (*KeywordMap)["bool3x1"] = EHTokBool3x1;
260 (*KeywordMap)["bool3x2"] = EHTokBool3x2;
261 (*KeywordMap)["bool3x3"] = EHTokBool3x3;
262 (*KeywordMap)["bool3x4"] = EHTokBool3x4;
263 (*KeywordMap)["bool4x1"] = EHTokBool4x1;
264 (*KeywordMap)["bool4x2"] = EHTokBool4x2;
265 (*KeywordMap)["bool4x3"] = EHTokBool4x3;
266 (*KeywordMap)["bool4x4"] = EHTokBool4x4;
267 (*KeywordMap)["float1x1"] = EHTokFloat1x1;
268 (*KeywordMap)["float1x2"] = EHTokFloat1x2;
269 (*KeywordMap)["float1x3"] = EHTokFloat1x3;
270 (*KeywordMap)["float1x4"] = EHTokFloat1x4;
271 (*KeywordMap)["float2x1"] = EHTokFloat2x1;
272 (*KeywordMap)["float2x2"] = EHTokFloat2x2;
273 (*KeywordMap)["float2x3"] = EHTokFloat2x3;
274 (*KeywordMap)["float2x4"] = EHTokFloat2x4;
275 (*KeywordMap)["float3x1"] = EHTokFloat3x1;
276 (*KeywordMap)["float3x2"] = EHTokFloat3x2;
277 (*KeywordMap)["float3x3"] = EHTokFloat3x3;
278 (*KeywordMap)["float3x4"] = EHTokFloat3x4;
279 (*KeywordMap)["float4x1"] = EHTokFloat4x1;
280 (*KeywordMap)["float4x2"] = EHTokFloat4x2;
281 (*KeywordMap)["float4x3"] = EHTokFloat4x3;
282 (*KeywordMap)["float4x4"] = EHTokFloat4x4;
283 (*KeywordMap)["half1x1"] = EHTokHalf1x1;
284 (*KeywordMap)["half1x2"] = EHTokHalf1x2;
285 (*KeywordMap)["half1x3"] = EHTokHalf1x3;
286 (*KeywordMap)["half1x4"] = EHTokHalf1x4;
287 (*KeywordMap)["half2x1"] = EHTokHalf2x1;
288 (*KeywordMap)["half2x2"] = EHTokHalf2x2;
289 (*KeywordMap)["half2x3"] = EHTokHalf2x3;
290 (*KeywordMap)["half2x4"] = EHTokHalf2x4;
291 (*KeywordMap)["half3x1"] = EHTokHalf3x1;
292 (*KeywordMap)["half3x2"] = EHTokHalf3x2;
293 (*KeywordMap)["half3x3"] = EHTokHalf3x3;
294 (*KeywordMap)["half3x4"] = EHTokHalf3x4;
295 (*KeywordMap)["half4x1"] = EHTokHalf4x1;
296 (*KeywordMap)["half4x2"] = EHTokHalf4x2;
297 (*KeywordMap)["half4x3"] = EHTokHalf4x3;
298 (*KeywordMap)["half4x4"] = EHTokHalf4x4;
299 (*KeywordMap)["double1x1"] = EHTokDouble1x1;
300 (*KeywordMap)["double1x2"] = EHTokDouble1x2;
301 (*KeywordMap)["double1x3"] = EHTokDouble1x3;
302 (*KeywordMap)["double1x4"] = EHTokDouble1x4;
303 (*KeywordMap)["double2x1"] = EHTokDouble2x1;
304 (*KeywordMap)["double2x2"] = EHTokDouble2x2;
305 (*KeywordMap)["double2x3"] = EHTokDouble2x3;
306 (*KeywordMap)["double2x4"] = EHTokDouble2x4;
307 (*KeywordMap)["double3x1"] = EHTokDouble3x1;
308 (*KeywordMap)["double3x2"] = EHTokDouble3x2;
309 (*KeywordMap)["double3x3"] = EHTokDouble3x3;
310 (*KeywordMap)["double3x4"] = EHTokDouble3x4;
311 (*KeywordMap)["double4x1"] = EHTokDouble4x1;
312 (*KeywordMap)["double4x2"] = EHTokDouble4x2;
313 (*KeywordMap)["double4x3"] = EHTokDouble4x3;
314 (*KeywordMap)["double4x4"] = EHTokDouble4x4;
315
316 (*KeywordMap)["sampler"] = EHTokSampler;
317 (*KeywordMap)["sampler1D"] = EHTokSampler1d;
318 (*KeywordMap)["sampler2D"] = EHTokSampler2d;
319 (*KeywordMap)["sampler3D"] = EHTokSampler3d;
320 (*KeywordMap)["samplerCube"] = EHTokSamplerCube;
321 (*KeywordMap)["sampler_state"] = EHTokSamplerState;
322 (*KeywordMap)["SamplerState"] = EHTokSamplerState;
323 (*KeywordMap)["SamplerComparisonState"] = EHTokSamplerComparisonState;
324 (*KeywordMap)["texture"] = EHTokTexture;
325 (*KeywordMap)["Texture1D"] = EHTokTexture1d;
326 (*KeywordMap)["Texture1DArray"] = EHTokTexture1darray;
327 (*KeywordMap)["Texture2D"] = EHTokTexture2d;
328 (*KeywordMap)["Texture2DArray"] = EHTokTexture2darray;
329 (*KeywordMap)["Texture3D"] = EHTokTexture3d;
330 (*KeywordMap)["TextureCube"] = EHTokTextureCube;
331 (*KeywordMap)["TextureCubeArray"] = EHTokTextureCubearray;
332 (*KeywordMap)["Texture2DMS"] = EHTokTexture2DMS;
333 (*KeywordMap)["Texture2DMSArray"] = EHTokTexture2DMSarray;
334 (*KeywordMap)["RWTexture1D"] = EHTokRWTexture1d;
335 (*KeywordMap)["RWTexture1DArray"] = EHTokRWTexture1darray;
336 (*KeywordMap)["RWTexture2D"] = EHTokRWTexture2d;
337 (*KeywordMap)["RWTexture2DArray"] = EHTokRWTexture2darray;
338 (*KeywordMap)["RWTexture3D"] = EHTokRWTexture3d;
339 (*KeywordMap)["RWBuffer"] = EHTokRWBuffer;
340 (*KeywordMap)["SubpassInput"] = EHTokSubpassInput;
341 (*KeywordMap)["SubpassInputMS"] = EHTokSubpassInputMS;
342
343 (*KeywordMap)["AppendStructuredBuffer"] = EHTokAppendStructuredBuffer;
344 (*KeywordMap)["ByteAddressBuffer"] = EHTokByteAddressBuffer;
345 (*KeywordMap)["ConsumeStructuredBuffer"] = EHTokConsumeStructuredBuffer;
346 (*KeywordMap)["RWByteAddressBuffer"] = EHTokRWByteAddressBuffer;
347 (*KeywordMap)["RWStructuredBuffer"] = EHTokRWStructuredBuffer;
348 (*KeywordMap)["StructuredBuffer"] = EHTokStructuredBuffer;
349 (*KeywordMap)["TextureBuffer"] = EHTokTextureBuffer;
350
351 (*KeywordMap)["class"] = EHTokClass;
352 (*KeywordMap)["struct"] = EHTokStruct;
353 (*KeywordMap)["cbuffer"] = EHTokCBuffer;
354 (*KeywordMap)["ConstantBuffer"] = EHTokConstantBuffer;
355 (*KeywordMap)["tbuffer"] = EHTokTBuffer;
356 (*KeywordMap)["typedef"] = EHTokTypedef;
357 (*KeywordMap)["this"] = EHTokThis;
358 (*KeywordMap)["namespace"] = EHTokNamespace;
359
360 (*KeywordMap)["true"] = EHTokBoolConstant;
361 (*KeywordMap)["false"] = EHTokBoolConstant;
362
363 (*KeywordMap)["for"] = EHTokFor;
364 (*KeywordMap)["do"] = EHTokDo;
365 (*KeywordMap)["while"] = EHTokWhile;
366 (*KeywordMap)["break"] = EHTokBreak;
367 (*KeywordMap)["continue"] = EHTokContinue;
368 (*KeywordMap)["if"] = EHTokIf;
369 (*KeywordMap)["else"] = EHTokElse;
370 (*KeywordMap)["discard"] = EHTokDiscard;
371 (*KeywordMap)["return"] = EHTokReturn;
372 (*KeywordMap)["switch"] = EHTokSwitch;
373 (*KeywordMap)["case"] = EHTokCase;
374 (*KeywordMap)["default"] = EHTokDefault;
375
376 // TODO: get correct set here
377 ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
378
379 ReservedSet->insert("auto");
380 ReservedSet->insert("catch");
381 ReservedSet->insert("char");
382 ReservedSet->insert("const_cast");
383 ReservedSet->insert("enum");
384 ReservedSet->insert("explicit");
385 ReservedSet->insert("friend");
386 ReservedSet->insert("goto");
387 ReservedSet->insert("long");
388 ReservedSet->insert("mutable");
389 ReservedSet->insert("new");
390 ReservedSet->insert("operator");
391 ReservedSet->insert("private");
392 ReservedSet->insert("protected");
393 ReservedSet->insert("public");
394 ReservedSet->insert("reinterpret_cast");
395 ReservedSet->insert("short");
396 ReservedSet->insert("signed");
397 ReservedSet->insert("sizeof");
398 ReservedSet->insert("static_cast");
399 ReservedSet->insert("template");
400 ReservedSet->insert("throw");
401 ReservedSet->insert("try");
402 ReservedSet->insert("typename");
403 ReservedSet->insert("union");
404 ReservedSet->insert("unsigned");
405 ReservedSet->insert("using");
406 ReservedSet->insert("virtual");
407
408 SemanticMap = new std::unordered_map<const char*, glslang::TBuiltInVariable, str_hash, str_eq>;
409
410 // in DX9, all outputs had to have a semantic associated with them, that was either consumed
411 // by the system or was a specific register assignment
412 // in DX10+, only semantics with the SV_ prefix have any meaning beyond decoration
413 // Fxc will only accept DX9 style semantics in compat mode
414 // Also, in DX10 if a SV value is present as the input of a stage, but isn't appropriate for that
415 // stage, it would just be ignored as it is likely there as part of an output struct from one stage
416 // to the next
417 bool bParseDX9 = false;
418 if (bParseDX9) {
419 (*SemanticMap)["PSIZE"] = EbvPointSize;
420 (*SemanticMap)["FOG"] = EbvFogFragCoord;
421 (*SemanticMap)["DEPTH"] = EbvFragDepth;
422 (*SemanticMap)["VFACE"] = EbvFace;
423 (*SemanticMap)["VPOS"] = EbvFragCoord;
424 }
425
426 (*SemanticMap)["SV_POSITION"] = EbvPosition;
427 (*SemanticMap)["SV_VERTEXID"] = EbvVertexIndex;
428 (*SemanticMap)["SV_VIEWPORTARRAYINDEX"] = EbvViewportIndex;
429 (*SemanticMap)["SV_TESSFACTOR"] = EbvTessLevelOuter;
430 (*SemanticMap)["SV_SAMPLEINDEX"] = EbvSampleId;
431 (*SemanticMap)["SV_RENDERTARGETARRAYINDEX"] = EbvLayer;
432 (*SemanticMap)["SV_PRIMITIVEID"] = EbvPrimitiveId;
433 (*SemanticMap)["SV_OUTPUTCONTROLPOINTID"] = EbvInvocationId;
434 (*SemanticMap)["SV_ISFRONTFACE"] = EbvFace;
435 (*SemanticMap)["SV_INSTANCEID"] = EbvInstanceIndex;
436 (*SemanticMap)["SV_INSIDETESSFACTOR"] = EbvTessLevelInner;
437 (*SemanticMap)["SV_GSINSTANCEID"] = EbvInvocationId;
438 (*SemanticMap)["SV_DISPATCHTHREADID"] = EbvGlobalInvocationId;
439 (*SemanticMap)["SV_GROUPTHREADID"] = EbvLocalInvocationId;
440 (*SemanticMap)["SV_GROUPINDEX"] = EbvLocalInvocationIndex;
441 (*SemanticMap)["SV_GROUPID"] = EbvWorkGroupId;
442 (*SemanticMap)["SV_DOMAINLOCATION"] = EbvTessCoord;
443 (*SemanticMap)["SV_DEPTH"] = EbvFragDepth;
444 (*SemanticMap)["SV_COVERAGE"] = EbvSampleMask;
445 (*SemanticMap)["SV_DEPTHGREATEREQUAL"] = EbvFragDepthGreater;
446 (*SemanticMap)["SV_DEPTHLESSEQUAL"] = EbvFragDepthLesser;
447 (*SemanticMap)["SV_STENCILREF"] = EbvFragStencilRef;
448 }
449
deleteKeywordMap()450 void HlslScanContext::deleteKeywordMap()
451 {
452 delete KeywordMap;
453 KeywordMap = nullptr;
454 delete ReservedSet;
455 ReservedSet = nullptr;
456 delete SemanticMap;
457 SemanticMap = nullptr;
458 }
459
460 // Wrapper for tokenizeClass() to get everything inside the token.
tokenize(HlslToken & token)461 void HlslScanContext::tokenize(HlslToken& token)
462 {
463 EHlslTokenClass tokenClass = tokenizeClass(token);
464 token.tokenClass = tokenClass;
465 }
466
mapSemantic(const char * upperCase)467 glslang::TBuiltInVariable HlslScanContext::mapSemantic(const char* upperCase)
468 {
469 auto it = SemanticMap->find(upperCase);
470 if (it != SemanticMap->end())
471 return it->second;
472 else
473 return glslang::EbvNone;
474 }
475
476 //
477 // Fill in token information for the next token, except for the token class.
478 // Returns the enum value of the token class of the next token found.
479 // Return 0 (EndOfTokens) on end of input.
480 //
tokenizeClass(HlslToken & token)481 EHlslTokenClass HlslScanContext::tokenizeClass(HlslToken& token)
482 {
483 do {
484 parserToken = &token;
485 TPpToken ppToken;
486 int token = ppContext.tokenize(ppToken);
487 if (token == EndOfInput)
488 return EHTokNone;
489
490 tokenText = ppToken.name;
491 loc = ppToken.loc;
492 parserToken->loc = loc;
493 switch (token) {
494 case ';': return EHTokSemicolon;
495 case ',': return EHTokComma;
496 case ':': return EHTokColon;
497 case '=': return EHTokAssign;
498 case '(': return EHTokLeftParen;
499 case ')': return EHTokRightParen;
500 case '.': return EHTokDot;
501 case '!': return EHTokBang;
502 case '-': return EHTokDash;
503 case '~': return EHTokTilde;
504 case '+': return EHTokPlus;
505 case '*': return EHTokStar;
506 case '/': return EHTokSlash;
507 case '%': return EHTokPercent;
508 case '<': return EHTokLeftAngle;
509 case '>': return EHTokRightAngle;
510 case '|': return EHTokVerticalBar;
511 case '^': return EHTokCaret;
512 case '&': return EHTokAmpersand;
513 case '?': return EHTokQuestion;
514 case '[': return EHTokLeftBracket;
515 case ']': return EHTokRightBracket;
516 case '{': return EHTokLeftBrace;
517 case '}': return EHTokRightBrace;
518 case '\\':
519 parseContext.error(loc, "illegal use of escape character", "\\", "");
520 break;
521
522 case PPAtomAddAssign: return EHTokAddAssign;
523 case PPAtomSubAssign: return EHTokSubAssign;
524 case PPAtomMulAssign: return EHTokMulAssign;
525 case PPAtomDivAssign: return EHTokDivAssign;
526 case PPAtomModAssign: return EHTokModAssign;
527
528 case PpAtomRight: return EHTokRightOp;
529 case PpAtomLeft: return EHTokLeftOp;
530
531 case PpAtomRightAssign: return EHTokRightAssign;
532 case PpAtomLeftAssign: return EHTokLeftAssign;
533 case PpAtomAndAssign: return EHTokAndAssign;
534 case PpAtomOrAssign: return EHTokOrAssign;
535 case PpAtomXorAssign: return EHTokXorAssign;
536
537 case PpAtomAnd: return EHTokAndOp;
538 case PpAtomOr: return EHTokOrOp;
539 case PpAtomXor: return EHTokXorOp;
540
541 case PpAtomEQ: return EHTokEqOp;
542 case PpAtomGE: return EHTokGeOp;
543 case PpAtomNE: return EHTokNeOp;
544 case PpAtomLE: return EHTokLeOp;
545
546 case PpAtomDecrement: return EHTokDecOp;
547 case PpAtomIncrement: return EHTokIncOp;
548
549 case PpAtomColonColon: return EHTokColonColon;
550
551 case PpAtomConstInt: parserToken->i = ppToken.ival; return EHTokIntConstant;
552 case PpAtomConstUint: parserToken->i = ppToken.ival; return EHTokUintConstant;
553 case PpAtomConstFloat16: parserToken->d = ppToken.dval; return EHTokFloat16Constant;
554 case PpAtomConstFloat: parserToken->d = ppToken.dval; return EHTokFloatConstant;
555 case PpAtomConstDouble: parserToken->d = ppToken.dval; return EHTokDoubleConstant;
556 case PpAtomIdentifier:
557 {
558 EHlslTokenClass token = tokenizeIdentifier();
559 return token;
560 }
561
562 case PpAtomConstString: {
563 parserToken->string = NewPoolTString(tokenText);
564 return EHTokStringConstant;
565 }
566
567 case EndOfInput: return EHTokNone;
568
569 default:
570 if (token < PpAtomMaxSingle) {
571 char buf[2];
572 buf[0] = (char)token;
573 buf[1] = 0;
574 parseContext.error(loc, "unexpected token", buf, "");
575 } else if (tokenText[0] != 0)
576 parseContext.error(loc, "unexpected token", tokenText, "");
577 else
578 parseContext.error(loc, "unexpected token", "", "");
579 break;
580 }
581 } while (true);
582 }
583
tokenizeIdentifier()584 EHlslTokenClass HlslScanContext::tokenizeIdentifier()
585 {
586 if (ReservedSet->find(tokenText) != ReservedSet->end())
587 return reservedWord();
588
589 auto it = KeywordMap->find(tokenText);
590 if (it == KeywordMap->end()) {
591 // Should have an identifier of some sort
592 return identifierOrType();
593 }
594 keyword = it->second;
595
596 switch (keyword) {
597
598 // qualifiers
599 case EHTokStatic:
600 case EHTokConst:
601 case EHTokSNorm:
602 case EHTokUnorm:
603 case EHTokExtern:
604 case EHTokUniform:
605 case EHTokVolatile:
606 case EHTokShared:
607 case EHTokGroupShared:
608 case EHTokLinear:
609 case EHTokCentroid:
610 case EHTokNointerpolation:
611 case EHTokNoperspective:
612 case EHTokSample:
613 case EHTokRowMajor:
614 case EHTokColumnMajor:
615 case EHTokPackOffset:
616 case EHTokIn:
617 case EHTokOut:
618 case EHTokInOut:
619 case EHTokPrecise:
620 case EHTokLayout:
621 case EHTokGloballyCoherent:
622 case EHTokInline:
623 return keyword;
624
625 // primitive types
626 case EHTokPoint:
627 case EHTokLine:
628 case EHTokTriangle:
629 case EHTokLineAdj:
630 case EHTokTriangleAdj:
631 return keyword;
632
633 // stream out types
634 case EHTokPointStream:
635 case EHTokLineStream:
636 case EHTokTriangleStream:
637 return keyword;
638
639 // Tessellation patches
640 case EHTokInputPatch:
641 case EHTokOutputPatch:
642 return keyword;
643
644 case EHTokBuffer:
645 case EHTokVector:
646 case EHTokMatrix:
647 return keyword;
648
649 // scalar types
650 case EHTokVoid:
651 case EHTokString:
652 case EHTokBool:
653 case EHTokInt:
654 case EHTokUint:
655 case EHTokUint64:
656 case EHTokDword:
657 case EHTokHalf:
658 case EHTokFloat:
659 case EHTokDouble:
660 case EHTokMin16float:
661 case EHTokMin10float:
662 case EHTokMin16int:
663 case EHTokMin12int:
664 case EHTokMin16uint:
665
666 // vector types
667 case EHTokBool1:
668 case EHTokBool2:
669 case EHTokBool3:
670 case EHTokBool4:
671 case EHTokFloat1:
672 case EHTokFloat2:
673 case EHTokFloat3:
674 case EHTokFloat4:
675 case EHTokInt1:
676 case EHTokInt2:
677 case EHTokInt3:
678 case EHTokInt4:
679 case EHTokDouble1:
680 case EHTokDouble2:
681 case EHTokDouble3:
682 case EHTokDouble4:
683 case EHTokUint1:
684 case EHTokUint2:
685 case EHTokUint3:
686 case EHTokUint4:
687 case EHTokHalf1:
688 case EHTokHalf2:
689 case EHTokHalf3:
690 case EHTokHalf4:
691 case EHTokMin16float1:
692 case EHTokMin16float2:
693 case EHTokMin16float3:
694 case EHTokMin16float4:
695 case EHTokMin10float1:
696 case EHTokMin10float2:
697 case EHTokMin10float3:
698 case EHTokMin10float4:
699 case EHTokMin16int1:
700 case EHTokMin16int2:
701 case EHTokMin16int3:
702 case EHTokMin16int4:
703 case EHTokMin12int1:
704 case EHTokMin12int2:
705 case EHTokMin12int3:
706 case EHTokMin12int4:
707 case EHTokMin16uint1:
708 case EHTokMin16uint2:
709 case EHTokMin16uint3:
710 case EHTokMin16uint4:
711
712 // matrix types
713 case EHTokBool1x1:
714 case EHTokBool1x2:
715 case EHTokBool1x3:
716 case EHTokBool1x4:
717 case EHTokBool2x1:
718 case EHTokBool2x2:
719 case EHTokBool2x3:
720 case EHTokBool2x4:
721 case EHTokBool3x1:
722 case EHTokBool3x2:
723 case EHTokBool3x3:
724 case EHTokBool3x4:
725 case EHTokBool4x1:
726 case EHTokBool4x2:
727 case EHTokBool4x3:
728 case EHTokBool4x4:
729 case EHTokInt1x1:
730 case EHTokInt1x2:
731 case EHTokInt1x3:
732 case EHTokInt1x4:
733 case EHTokInt2x1:
734 case EHTokInt2x2:
735 case EHTokInt2x3:
736 case EHTokInt2x4:
737 case EHTokInt3x1:
738 case EHTokInt3x2:
739 case EHTokInt3x3:
740 case EHTokInt3x4:
741 case EHTokInt4x1:
742 case EHTokInt4x2:
743 case EHTokInt4x3:
744 case EHTokInt4x4:
745 case EHTokUint1x1:
746 case EHTokUint1x2:
747 case EHTokUint1x3:
748 case EHTokUint1x4:
749 case EHTokUint2x1:
750 case EHTokUint2x2:
751 case EHTokUint2x3:
752 case EHTokUint2x4:
753 case EHTokUint3x1:
754 case EHTokUint3x2:
755 case EHTokUint3x3:
756 case EHTokUint3x4:
757 case EHTokUint4x1:
758 case EHTokUint4x2:
759 case EHTokUint4x3:
760 case EHTokUint4x4:
761 case EHTokFloat1x1:
762 case EHTokFloat1x2:
763 case EHTokFloat1x3:
764 case EHTokFloat1x4:
765 case EHTokFloat2x1:
766 case EHTokFloat2x2:
767 case EHTokFloat2x3:
768 case EHTokFloat2x4:
769 case EHTokFloat3x1:
770 case EHTokFloat3x2:
771 case EHTokFloat3x3:
772 case EHTokFloat3x4:
773 case EHTokFloat4x1:
774 case EHTokFloat4x2:
775 case EHTokFloat4x3:
776 case EHTokFloat4x4:
777 case EHTokHalf1x1:
778 case EHTokHalf1x2:
779 case EHTokHalf1x3:
780 case EHTokHalf1x4:
781 case EHTokHalf2x1:
782 case EHTokHalf2x2:
783 case EHTokHalf2x3:
784 case EHTokHalf2x4:
785 case EHTokHalf3x1:
786 case EHTokHalf3x2:
787 case EHTokHalf3x3:
788 case EHTokHalf3x4:
789 case EHTokHalf4x1:
790 case EHTokHalf4x2:
791 case EHTokHalf4x3:
792 case EHTokHalf4x4:
793 case EHTokDouble1x1:
794 case EHTokDouble1x2:
795 case EHTokDouble1x3:
796 case EHTokDouble1x4:
797 case EHTokDouble2x1:
798 case EHTokDouble2x2:
799 case EHTokDouble2x3:
800 case EHTokDouble2x4:
801 case EHTokDouble3x1:
802 case EHTokDouble3x2:
803 case EHTokDouble3x3:
804 case EHTokDouble3x4:
805 case EHTokDouble4x1:
806 case EHTokDouble4x2:
807 case EHTokDouble4x3:
808 case EHTokDouble4x4:
809 return keyword;
810
811 // texturing types
812 case EHTokSampler:
813 case EHTokSampler1d:
814 case EHTokSampler2d:
815 case EHTokSampler3d:
816 case EHTokSamplerCube:
817 case EHTokSamplerState:
818 case EHTokSamplerComparisonState:
819 case EHTokTexture:
820 case EHTokTexture1d:
821 case EHTokTexture1darray:
822 case EHTokTexture2d:
823 case EHTokTexture2darray:
824 case EHTokTexture3d:
825 case EHTokTextureCube:
826 case EHTokTextureCubearray:
827 case EHTokTexture2DMS:
828 case EHTokTexture2DMSarray:
829 case EHTokRWTexture1d:
830 case EHTokRWTexture1darray:
831 case EHTokRWTexture2d:
832 case EHTokRWTexture2darray:
833 case EHTokRWTexture3d:
834 case EHTokRWBuffer:
835 case EHTokAppendStructuredBuffer:
836 case EHTokByteAddressBuffer:
837 case EHTokConsumeStructuredBuffer:
838 case EHTokRWByteAddressBuffer:
839 case EHTokRWStructuredBuffer:
840 case EHTokStructuredBuffer:
841 case EHTokTextureBuffer:
842 case EHTokSubpassInput:
843 case EHTokSubpassInputMS:
844 return keyword;
845
846 // variable, user type, ...
847 case EHTokClass:
848 case EHTokStruct:
849 case EHTokTypedef:
850 case EHTokCBuffer:
851 case EHTokConstantBuffer:
852 case EHTokTBuffer:
853 case EHTokThis:
854 case EHTokNamespace:
855 return keyword;
856
857 case EHTokBoolConstant:
858 if (strcmp("true", tokenText) == 0)
859 parserToken->b = true;
860 else
861 parserToken->b = false;
862 return keyword;
863
864 // control flow
865 case EHTokFor:
866 case EHTokDo:
867 case EHTokWhile:
868 case EHTokBreak:
869 case EHTokContinue:
870 case EHTokIf:
871 case EHTokElse:
872 case EHTokDiscard:
873 case EHTokReturn:
874 case EHTokCase:
875 case EHTokSwitch:
876 case EHTokDefault:
877 return keyword;
878
879 default:
880 parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
881 return EHTokNone;
882 }
883 }
884
identifierOrType()885 EHlslTokenClass HlslScanContext::identifierOrType()
886 {
887 parserToken->string = NewPoolTString(tokenText);
888
889 return EHTokIdentifier;
890 }
891
892 // Give an error for use of a reserved symbol.
893 // However, allow built-in declarations to use reserved words, to allow
894 // extension support before the extension is enabled.
reservedWord()895 EHlslTokenClass HlslScanContext::reservedWord()
896 {
897 if (! parseContext.symbolTable.atBuiltInLevel())
898 parseContext.error(loc, "Reserved word.", tokenText, "", "");
899
900 return EHTokNone;
901 }
902
903 } // end namespace glslang
904