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 "../Include/Types.h"
46 #include "../MachineIndependent/SymbolTable.h"
47 #include "../MachineIndependent/ParseHelper.h"
48 #include "hlslScanContext.h"
49 #include "hlslTokens.h"
50 
51 // preprocessor includes
52 #include "../MachineIndependent/preprocessor/PpContext.h"
53 #include "../MachineIndependent/preprocessor/PpTokens.h"
54 
55 namespace {
56 
57 struct str_eq
58 {
operator ()__anon67f805720111::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 ()__anon67f805720111::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