6ddb39d23849390a4c9cf5bc38bb17b40f3fbc9d
[platform/upstream/glslang.git] / hlsl / hlslScanContext.cpp
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 {
59     bool operator()(const char* lhs, const char* rhs) const
60     {
61         return strcmp(lhs, rhs) == 0;
62     }
63 };
64
65 struct str_hash
66 {
67     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
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)["dword"] =                   EHTokDword;
147     (*KeywordMap)["half"] =                    EHTokHalf;
148     (*KeywordMap)["float"] =                   EHTokFloat;
149     (*KeywordMap)["double"] =                  EHTokDouble;
150     (*KeywordMap)["min16float"] =              EHTokMin16float;
151     (*KeywordMap)["min10float"] =              EHTokMin10float;
152     (*KeywordMap)["min16int"] =                EHTokMin16int;
153     (*KeywordMap)["min12int"] =                EHTokMin12int;
154     (*KeywordMap)["min16uint"] =               EHTokMin16uint;
155
156     (*KeywordMap)["bool1"] =                   EHTokBool1;
157     (*KeywordMap)["bool2"] =                   EHTokBool2;
158     (*KeywordMap)["bool3"] =                   EHTokBool3;
159     (*KeywordMap)["bool4"] =                   EHTokBool4;
160     (*KeywordMap)["float1"] =                  EHTokFloat1;
161     (*KeywordMap)["float2"] =                  EHTokFloat2;
162     (*KeywordMap)["float3"] =                  EHTokFloat3;
163     (*KeywordMap)["float4"] =                  EHTokFloat4;
164     (*KeywordMap)["int1"] =                    EHTokInt1;
165     (*KeywordMap)["int2"] =                    EHTokInt2;
166     (*KeywordMap)["int3"] =                    EHTokInt3;
167     (*KeywordMap)["int4"] =                    EHTokInt4;
168     (*KeywordMap)["double1"] =                 EHTokDouble1;
169     (*KeywordMap)["double2"] =                 EHTokDouble2;
170     (*KeywordMap)["double3"] =                 EHTokDouble3;
171     (*KeywordMap)["double4"] =                 EHTokDouble4;
172     (*KeywordMap)["uint1"] =                   EHTokUint1;
173     (*KeywordMap)["uint2"] =                   EHTokUint2;
174     (*KeywordMap)["uint3"] =                   EHTokUint3;
175     (*KeywordMap)["uint4"] =                   EHTokUint4;
176
177     (*KeywordMap)["half1"] =                   EHTokHalf1;
178     (*KeywordMap)["half2"] =                   EHTokHalf2;
179     (*KeywordMap)["half3"] =                   EHTokHalf3;
180     (*KeywordMap)["half4"] =                   EHTokHalf4;
181     (*KeywordMap)["min16float1"] =             EHTokMin16float1;
182     (*KeywordMap)["min16float2"] =             EHTokMin16float2;
183     (*KeywordMap)["min16float3"] =             EHTokMin16float3;
184     (*KeywordMap)["min16float4"] =             EHTokMin16float4;
185     (*KeywordMap)["min10float1"] =             EHTokMin10float1;
186     (*KeywordMap)["min10float2"] =             EHTokMin10float2;
187     (*KeywordMap)["min10float3"] =             EHTokMin10float3;
188     (*KeywordMap)["min10float4"] =             EHTokMin10float4;
189     (*KeywordMap)["min16int1"] =               EHTokMin16int1;
190     (*KeywordMap)["min16int2"] =               EHTokMin16int2;
191     (*KeywordMap)["min16int3"] =               EHTokMin16int3;
192     (*KeywordMap)["min16int4"] =               EHTokMin16int4;
193     (*KeywordMap)["min12int1"] =               EHTokMin12int1;
194     (*KeywordMap)["min12int2"] =               EHTokMin12int2;
195     (*KeywordMap)["min12int3"] =               EHTokMin12int3;
196     (*KeywordMap)["min12int4"] =               EHTokMin12int4;
197     (*KeywordMap)["min16uint1"] =              EHTokMin16uint1;
198     (*KeywordMap)["min16uint2"] =              EHTokMin16uint2;
199     (*KeywordMap)["min16uint3"] =              EHTokMin16uint3;
200     (*KeywordMap)["min16uint4"] =              EHTokMin16uint4;
201
202     (*KeywordMap)["bool1x1"] =                 EHTokBool1x1;
203     (*KeywordMap)["bool1x2"] =                 EHTokBool1x2;
204     (*KeywordMap)["bool1x3"] =                 EHTokBool1x3;
205     (*KeywordMap)["bool1x4"] =                 EHTokBool1x4;
206     (*KeywordMap)["bool2x1"] =                 EHTokBool2x1;
207     (*KeywordMap)["bool2x2"] =                 EHTokBool2x2;
208     (*KeywordMap)["bool2x3"] =                 EHTokBool2x3;
209     (*KeywordMap)["bool2x4"] =                 EHTokBool2x4;
210     (*KeywordMap)["bool3x1"] =                 EHTokBool3x1;
211     (*KeywordMap)["bool3x2"] =                 EHTokBool3x2;
212     (*KeywordMap)["bool3x3"] =                 EHTokBool3x3;
213     (*KeywordMap)["bool3x4"] =                 EHTokBool3x4;
214     (*KeywordMap)["bool4x1"] =                 EHTokBool4x1;
215     (*KeywordMap)["bool4x2"] =                 EHTokBool4x2;
216     (*KeywordMap)["bool4x3"] =                 EHTokBool4x3;
217     (*KeywordMap)["bool4x4"] =                 EHTokBool4x4;
218     (*KeywordMap)["int1x1"] =                  EHTokInt1x1;
219     (*KeywordMap)["int1x2"] =                  EHTokInt1x2;
220     (*KeywordMap)["int1x3"] =                  EHTokInt1x3;
221     (*KeywordMap)["int1x4"] =                  EHTokInt1x4;
222     (*KeywordMap)["int2x1"] =                  EHTokInt2x1;
223     (*KeywordMap)["int2x2"] =                  EHTokInt2x2;
224     (*KeywordMap)["int2x3"] =                  EHTokInt2x3;
225     (*KeywordMap)["int2x4"] =                  EHTokInt2x4;
226     (*KeywordMap)["int3x1"] =                  EHTokInt3x1;
227     (*KeywordMap)["int3x2"] =                  EHTokInt3x2;
228     (*KeywordMap)["int3x3"] =                  EHTokInt3x3;
229     (*KeywordMap)["int3x4"] =                  EHTokInt3x4;
230     (*KeywordMap)["int4x1"] =                  EHTokInt4x1;
231     (*KeywordMap)["int4x2"] =                  EHTokInt4x2;
232     (*KeywordMap)["int4x3"] =                  EHTokInt4x3;
233     (*KeywordMap)["int4x4"] =                  EHTokInt4x4;
234     (*KeywordMap)["uint1x1"] =                 EHTokUint1x1;
235     (*KeywordMap)["uint1x2"] =                 EHTokUint1x2;
236     (*KeywordMap)["uint1x3"] =                 EHTokUint1x3;
237     (*KeywordMap)["uint1x4"] =                 EHTokUint1x4;
238     (*KeywordMap)["uint2x1"] =                 EHTokUint2x1;
239     (*KeywordMap)["uint2x2"] =                 EHTokUint2x2;
240     (*KeywordMap)["uint2x3"] =                 EHTokUint2x3;
241     (*KeywordMap)["uint2x4"] =                 EHTokUint2x4;
242     (*KeywordMap)["uint3x1"] =                 EHTokUint3x1;
243     (*KeywordMap)["uint3x2"] =                 EHTokUint3x2;
244     (*KeywordMap)["uint3x3"] =                 EHTokUint3x3;
245     (*KeywordMap)["uint3x4"] =                 EHTokUint3x4;
246     (*KeywordMap)["uint4x1"] =                 EHTokUint4x1;
247     (*KeywordMap)["uint4x2"] =                 EHTokUint4x2;
248     (*KeywordMap)["uint4x3"] =                 EHTokUint4x3;
249     (*KeywordMap)["uint4x4"] =                 EHTokUint4x4;
250     (*KeywordMap)["bool1x1"] =                 EHTokBool1x1;
251     (*KeywordMap)["bool1x2"] =                 EHTokBool1x2;
252     (*KeywordMap)["bool1x3"] =                 EHTokBool1x3;
253     (*KeywordMap)["bool1x4"] =                 EHTokBool1x4;
254     (*KeywordMap)["bool2x1"] =                 EHTokBool2x1;
255     (*KeywordMap)["bool2x2"] =                 EHTokBool2x2;
256     (*KeywordMap)["bool2x3"] =                 EHTokBool2x3;
257     (*KeywordMap)["bool2x4"] =                 EHTokBool2x4;
258     (*KeywordMap)["bool3x1"] =                 EHTokBool3x1;
259     (*KeywordMap)["bool3x2"] =                 EHTokBool3x2;
260     (*KeywordMap)["bool3x3"] =                 EHTokBool3x3;
261     (*KeywordMap)["bool3x4"] =                 EHTokBool3x4;
262     (*KeywordMap)["bool4x1"] =                 EHTokBool4x1;
263     (*KeywordMap)["bool4x2"] =                 EHTokBool4x2;
264     (*KeywordMap)["bool4x3"] =                 EHTokBool4x3;
265     (*KeywordMap)["bool4x4"] =                 EHTokBool4x4;
266     (*KeywordMap)["float1x1"] =                EHTokFloat1x1;
267     (*KeywordMap)["float1x2"] =                EHTokFloat1x2;
268     (*KeywordMap)["float1x3"] =                EHTokFloat1x3;
269     (*KeywordMap)["float1x4"] =                EHTokFloat1x4;
270     (*KeywordMap)["float2x1"] =                EHTokFloat2x1;
271     (*KeywordMap)["float2x2"] =                EHTokFloat2x2;
272     (*KeywordMap)["float2x3"] =                EHTokFloat2x3;
273     (*KeywordMap)["float2x4"] =                EHTokFloat2x4;
274     (*KeywordMap)["float3x1"] =                EHTokFloat3x1;
275     (*KeywordMap)["float3x2"] =                EHTokFloat3x2;
276     (*KeywordMap)["float3x3"] =                EHTokFloat3x3;
277     (*KeywordMap)["float3x4"] =                EHTokFloat3x4;
278     (*KeywordMap)["float4x1"] =                EHTokFloat4x1;
279     (*KeywordMap)["float4x2"] =                EHTokFloat4x2;
280     (*KeywordMap)["float4x3"] =                EHTokFloat4x3;
281     (*KeywordMap)["float4x4"] =                EHTokFloat4x4;
282     (*KeywordMap)["double1x1"] =               EHTokDouble1x1;
283     (*KeywordMap)["double1x2"] =               EHTokDouble1x2;
284     (*KeywordMap)["double1x3"] =               EHTokDouble1x3;
285     (*KeywordMap)["double1x4"] =               EHTokDouble1x4;
286     (*KeywordMap)["double2x1"] =               EHTokDouble2x1;
287     (*KeywordMap)["double2x2"] =               EHTokDouble2x2;
288     (*KeywordMap)["double2x3"] =               EHTokDouble2x3;
289     (*KeywordMap)["double2x4"] =               EHTokDouble2x4;
290     (*KeywordMap)["double3x1"] =               EHTokDouble3x1;
291     (*KeywordMap)["double3x2"] =               EHTokDouble3x2;
292     (*KeywordMap)["double3x3"] =               EHTokDouble3x3;
293     (*KeywordMap)["double3x4"] =               EHTokDouble3x4;
294     (*KeywordMap)["double4x1"] =               EHTokDouble4x1;
295     (*KeywordMap)["double4x2"] =               EHTokDouble4x2;
296     (*KeywordMap)["double4x3"] =               EHTokDouble4x3;
297     (*KeywordMap)["double4x4"] =               EHTokDouble4x4;
298
299     (*KeywordMap)["sampler"] =                 EHTokSampler;
300     (*KeywordMap)["sampler1D"] =               EHTokSampler1d;
301     (*KeywordMap)["sampler2D"] =               EHTokSampler2d;
302     (*KeywordMap)["sampler3D"] =               EHTokSampler3d;
303     (*KeywordMap)["samplerCube"] =             EHTokSamplerCube;
304     (*KeywordMap)["sampler_state"] =           EHTokSamplerState;
305     (*KeywordMap)["SamplerState"] =            EHTokSamplerState;
306     (*KeywordMap)["SamplerComparisonState"] =  EHTokSamplerComparisonState;
307     (*KeywordMap)["texture"] =                 EHTokTexture;
308     (*KeywordMap)["Texture1D"] =               EHTokTexture1d;
309     (*KeywordMap)["Texture1DArray"] =          EHTokTexture1darray;
310     (*KeywordMap)["Texture2D"] =               EHTokTexture2d;
311     (*KeywordMap)["Texture2DArray"] =          EHTokTexture2darray;
312     (*KeywordMap)["Texture3D"] =               EHTokTexture3d;
313     (*KeywordMap)["TextureCube"] =             EHTokTextureCube;
314     (*KeywordMap)["TextureCubeArray"] =        EHTokTextureCubearray;
315     (*KeywordMap)["Texture2DMS"] =             EHTokTexture2DMS;
316     (*KeywordMap)["Texture2DMSArray"] =        EHTokTexture2DMSarray;
317     (*KeywordMap)["RWTexture1D"] =             EHTokRWTexture1d;
318     (*KeywordMap)["RWTexture1DArray"] =        EHTokRWTexture1darray;
319     (*KeywordMap)["RWTexture2D"] =             EHTokRWTexture2d;
320     (*KeywordMap)["RWTexture2DArray"] =        EHTokRWTexture2darray;
321     (*KeywordMap)["RWTexture3D"] =             EHTokRWTexture3d;
322     (*KeywordMap)["RWBuffer"] =                EHTokRWBuffer;
323
324     (*KeywordMap)["AppendStructuredBuffer"] =  EHTokAppendStructuredBuffer;
325     (*KeywordMap)["ByteAddressBuffer"] =       EHTokByteAddressBuffer;
326     (*KeywordMap)["ConsumeStructuredBuffer"] = EHTokConsumeStructuredBuffer;
327     (*KeywordMap)["RWByteAddressBuffer"] =     EHTokRWByteAddressBuffer;
328     (*KeywordMap)["RWStructuredBuffer"] =      EHTokRWStructuredBuffer;
329     (*KeywordMap)["StructuredBuffer"] =        EHTokStructuredBuffer;
330
331     (*KeywordMap)["class"] =                   EHTokClass;
332     (*KeywordMap)["struct"] =                  EHTokStruct;
333     (*KeywordMap)["cbuffer"] =                 EHTokCBuffer;
334     (*KeywordMap)["tbuffer"] =                 EHTokTBuffer;
335     (*KeywordMap)["typedef"] =                 EHTokTypedef;
336     (*KeywordMap)["this"] =                    EHTokThis;
337     (*KeywordMap)["namespace"] =               EHTokNamespace;
338
339     (*KeywordMap)["true"] =                    EHTokBoolConstant;
340     (*KeywordMap)["false"] =                   EHTokBoolConstant;
341
342     (*KeywordMap)["for"] =                     EHTokFor;
343     (*KeywordMap)["do"] =                      EHTokDo;
344     (*KeywordMap)["while"] =                   EHTokWhile;
345     (*KeywordMap)["break"] =                   EHTokBreak;
346     (*KeywordMap)["continue"] =                EHTokContinue;
347     (*KeywordMap)["if"] =                      EHTokIf;
348     (*KeywordMap)["else"] =                    EHTokElse;
349     (*KeywordMap)["discard"] =                 EHTokDiscard;
350     (*KeywordMap)["return"] =                  EHTokReturn;
351     (*KeywordMap)["switch"] =                  EHTokSwitch;
352     (*KeywordMap)["case"] =                    EHTokCase;
353     (*KeywordMap)["default"] =                 EHTokDefault;
354
355     // TODO: get correct set here
356     ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
357
358     ReservedSet->insert("auto");
359     ReservedSet->insert("catch");
360     ReservedSet->insert("char");
361     ReservedSet->insert("const_cast");
362     ReservedSet->insert("enum");
363     ReservedSet->insert("explicit");
364     ReservedSet->insert("friend");
365     ReservedSet->insert("goto");
366     ReservedSet->insert("long");
367     ReservedSet->insert("mutable");
368     ReservedSet->insert("new");
369     ReservedSet->insert("operator");
370     ReservedSet->insert("private");
371     ReservedSet->insert("protected");
372     ReservedSet->insert("public");
373     ReservedSet->insert("reinterpret_cast");
374     ReservedSet->insert("short");
375     ReservedSet->insert("signed");
376     ReservedSet->insert("sizeof");
377     ReservedSet->insert("static_cast");
378     ReservedSet->insert("template");
379     ReservedSet->insert("throw");
380     ReservedSet->insert("try");
381     ReservedSet->insert("typename");
382     ReservedSet->insert("union");
383     ReservedSet->insert("unsigned");
384     ReservedSet->insert("using");
385     ReservedSet->insert("virtual");
386
387     SemanticMap = new std::unordered_map<const char*, glslang::TBuiltInVariable, str_hash, str_eq>;
388
389     // in DX9, all outputs had to have a semantic associated with them, that was either consumed
390     // by the system or was a specific register assignment
391     // in DX10+, only semantics with the SV_ prefix have any meaning beyond decoration
392     // Fxc will only accept DX9 style semantics in compat mode
393     // Also, in DX10 if a SV value is present as the input of a stage, but isn't appropriate for that
394     // stage, it would just be ignored as it is likely there as part of an output struct from one stage
395     // to the next
396     bool bParseDX9 = false;
397     if (bParseDX9) {
398         (*SemanticMap)["PSIZE"] = EbvPointSize;
399         (*SemanticMap)["FOG"] =   EbvFogFragCoord;
400         (*SemanticMap)["DEPTH"] = EbvFragDepth;
401         (*SemanticMap)["VFACE"] = EbvFace;
402         (*SemanticMap)["VPOS"] =  EbvFragCoord;
403     }
404
405     (*SemanticMap)["SV_POSITION"] =               EbvPosition;
406     (*SemanticMap)["SV_CLIPDISTANCE"] =           EbvClipDistance;
407     (*SemanticMap)["SV_CLIPDISTANCE0"] =          EbvClipDistance;
408     (*SemanticMap)["SV_CLIPDISTANCE1"] =          EbvClipDistance;
409     (*SemanticMap)["SV_CLIPDISTANCE2"] =          EbvClipDistance;
410     (*SemanticMap)["SV_CLIPDISTANCE3"] =          EbvClipDistance;
411     (*SemanticMap)["SV_CLIPDISTANCE4"] =          EbvClipDistance;
412     (*SemanticMap)["SV_CLIPDISTANCE5"] =          EbvClipDistance;
413     (*SemanticMap)["SV_CLIPDISTANCE6"] =          EbvClipDistance;
414     (*SemanticMap)["SV_CLIPDISTANCE7"] =          EbvClipDistance;
415     (*SemanticMap)["SV_CLIPDISTANCE8"] =          EbvClipDistance;
416     (*SemanticMap)["SV_CLIPDISTANCE9"] =          EbvClipDistance;
417     (*SemanticMap)["SV_CLIPDISTANCE10"] =         EbvClipDistance;
418     (*SemanticMap)["SV_CLIPDISTANCE11"] =         EbvClipDistance;
419     (*SemanticMap)["SV_CULLDISTANCE"] =           EbvCullDistance;
420     (*SemanticMap)["SV_CULLDISTANCE0"] =          EbvCullDistance;
421     (*SemanticMap)["SV_CULLDISTANCE1"] =          EbvCullDistance;
422     (*SemanticMap)["SV_CULLDISTANCE2"] =          EbvCullDistance;
423     (*SemanticMap)["SV_CULLDISTANCE3"] =          EbvCullDistance;
424     (*SemanticMap)["SV_CULLDISTANCE4"] =          EbvCullDistance;
425     (*SemanticMap)["SV_CULLDISTANCE5"] =          EbvCullDistance;
426     (*SemanticMap)["SV_CULLDISTANCE6"] =          EbvCullDistance;
427     (*SemanticMap)["SV_CULLDISTANCE7"] =          EbvCullDistance;
428     (*SemanticMap)["SV_CULLDISTANCE8"] =          EbvCullDistance;
429     (*SemanticMap)["SV_CULLDISTANCE9"] =          EbvCullDistance;
430     (*SemanticMap)["SV_CULLDISTANCE10"] =         EbvCullDistance;
431     (*SemanticMap)["SV_CULLDISTANCE11"] =         EbvCullDistance;
432     (*SemanticMap)["SV_VERTEXID"] =               EbvVertexIndex;
433     (*SemanticMap)["SV_VIEWPORTARRAYINDEX"] =     EbvViewportIndex;
434     (*SemanticMap)["SV_TESSFACTOR"] =             EbvTessLevelOuter;
435     (*SemanticMap)["SV_SAMPLEINDEX"] =            EbvSampleId;
436     (*SemanticMap)["SV_RENDERTARGETARRAYINDEX"] = EbvLayer;
437     (*SemanticMap)["SV_PRIMITIVEID"] =            EbvPrimitiveId;
438     (*SemanticMap)["SV_OUTPUTCONTROLPOINTID"] =   EbvInvocationId;
439     (*SemanticMap)["SV_ISFRONTFACE"] =            EbvFace;
440     (*SemanticMap)["SV_INSTANCEID"] =             EbvInstanceIndex;
441     (*SemanticMap)["SV_INSIDETESSFACTOR"] =       EbvTessLevelInner;
442     (*SemanticMap)["SV_GSINSTANCEID"] =           EbvInvocationId;
443     (*SemanticMap)["SV_DISPATCHTHREADID"] =       EbvGlobalInvocationId;
444     (*SemanticMap)["SV_GROUPTHREADID"] =          EbvLocalInvocationId;
445     (*SemanticMap)["SV_GROUPINDEX"] =             EbvLocalInvocationIndex;
446     (*SemanticMap)["SV_GROUPID"] =                EbvWorkGroupId;
447     (*SemanticMap)["SV_DOMAINLOCATION"] =         EbvTessCoord;
448     (*SemanticMap)["SV_DEPTH"] =                  EbvFragDepth;
449     (*SemanticMap)["SV_COVERAGE"] =               EbvSampleMask;
450     (*SemanticMap)["SV_DEPTHGREATEREQUAL"] =      EbvFragDepthGreater;
451     (*SemanticMap)["SV_DEPTHLESSEQUAL"] =         EbvFragDepthLesser;
452     (*SemanticMap)["SV_STENCILREF"] =             EbvStencilRef;
453 }
454
455 void HlslScanContext::deleteKeywordMap()
456 {
457     delete KeywordMap;
458     KeywordMap = nullptr;
459     delete ReservedSet;
460     ReservedSet = nullptr;
461     delete SemanticMap;
462     SemanticMap = nullptr;
463 }
464
465 // Wrapper for tokenizeClass() to get everything inside the token.
466 void HlslScanContext::tokenize(HlslToken& token)
467 {
468     EHlslTokenClass tokenClass = tokenizeClass(token);
469     token.tokenClass = tokenClass;
470 }
471
472 glslang::TBuiltInVariable HlslScanContext::mapSemantic(const char* upperCase)
473 {
474     auto it = SemanticMap->find(upperCase);
475     if (it != SemanticMap->end())
476         return it->second;
477     else
478         return glslang::EbvNone;
479 }
480
481 //
482 // Fill in token information for the next token, except for the token class.
483 // Returns the enum value of the token class of the next token found.
484 // Return 0 (EndOfTokens) on end of input.
485 //
486 EHlslTokenClass HlslScanContext::tokenizeClass(HlslToken& token)
487 {
488     do {
489         parserToken = &token;
490         TPpToken ppToken;
491         int token = ppContext.tokenize(ppToken);
492         if (token == EndOfInput)
493             return EHTokNone;
494
495         tokenText = ppToken.name;
496         loc = ppToken.loc;
497         parserToken->loc = loc;
498         switch (token) {
499         case ';':                       return EHTokSemicolon;
500         case ',':                       return EHTokComma;
501         case ':':                       return EHTokColon;
502         case '=':                       return EHTokAssign;
503         case '(':                       return EHTokLeftParen;
504         case ')':                       return EHTokRightParen;
505         case '.':                       return EHTokDot;
506         case '!':                       return EHTokBang;
507         case '-':                       return EHTokDash;
508         case '~':                       return EHTokTilde;
509         case '+':                       return EHTokPlus;
510         case '*':                       return EHTokStar;
511         case '/':                       return EHTokSlash;
512         case '%':                       return EHTokPercent;
513         case '<':                       return EHTokLeftAngle;
514         case '>':                       return EHTokRightAngle;
515         case '|':                       return EHTokVerticalBar;
516         case '^':                       return EHTokCaret;
517         case '&':                       return EHTokAmpersand;
518         case '?':                       return EHTokQuestion;
519         case '[':                       return EHTokLeftBracket;
520         case ']':                       return EHTokRightBracket;
521         case '{':                       return EHTokLeftBrace;
522         case '}':                       return EHTokRightBrace;
523         case '\\':
524             parseContext.error(loc, "illegal use of escape character", "\\", "");
525             break;
526
527         case PPAtomAddAssign:          return EHTokAddAssign;
528         case PPAtomSubAssign:          return EHTokSubAssign;
529         case PPAtomMulAssign:          return EHTokMulAssign;
530         case PPAtomDivAssign:          return EHTokDivAssign;
531         case PPAtomModAssign:          return EHTokModAssign;
532
533         case PpAtomRight:              return EHTokRightOp;
534         case PpAtomLeft:               return EHTokLeftOp;
535
536         case PpAtomRightAssign:        return EHTokRightAssign;
537         case PpAtomLeftAssign:         return EHTokLeftAssign;
538         case PpAtomAndAssign:          return EHTokAndAssign;
539         case PpAtomOrAssign:           return EHTokOrAssign;
540         case PpAtomXorAssign:          return EHTokXorAssign;
541
542         case PpAtomAnd:                return EHTokAndOp;
543         case PpAtomOr:                 return EHTokOrOp;
544         case PpAtomXor:                return EHTokXorOp;
545
546         case PpAtomEQ:                 return EHTokEqOp;
547         case PpAtomGE:                 return EHTokGeOp;
548         case PpAtomNE:                 return EHTokNeOp;
549         case PpAtomLE:                 return EHTokLeOp;
550
551         case PpAtomDecrement:          return EHTokDecOp;
552         case PpAtomIncrement:          return EHTokIncOp;
553
554         case PpAtomColonColon:         return EHTokColonColon;
555
556         case PpAtomConstInt:           parserToken->i = ppToken.ival;       return EHTokIntConstant;
557         case PpAtomConstUint:          parserToken->i = ppToken.ival;       return EHTokUintConstant;
558         case PpAtomConstFloat:         parserToken->d = ppToken.dval;       return EHTokFloatConstant;
559         case PpAtomConstDouble:        parserToken->d = ppToken.dval;       return EHTokDoubleConstant;
560         case PpAtomIdentifier:
561         {
562             EHlslTokenClass token = tokenizeIdentifier();
563             return token;
564         }
565
566         case PpAtomConstString: {
567             parserToken->string = NewPoolTString(tokenText);
568             return EHTokStringConstant;
569         }
570
571         case EndOfInput:               return EHTokNone;
572
573         default:
574             char buf[2];
575             buf[0] = (char)token;
576             buf[1] = 0;
577             parseContext.error(loc, "unexpected token", buf, "");
578             break;
579         }
580     } while (true);
581 }
582
583 EHlslTokenClass HlslScanContext::tokenizeIdentifier()
584 {
585     if (ReservedSet->find(tokenText) != ReservedSet->end())
586         return reservedWord();
587
588     auto it = KeywordMap->find(tokenText);
589     if (it == KeywordMap->end()) {
590         // Should have an identifier of some sort
591         return identifierOrType();
592     }
593     keyword = it->second;
594
595     switch (keyword) {
596
597     // qualifiers
598     case EHTokStatic:
599     case EHTokConst:
600     case EHTokSNorm:
601     case EHTokUnorm:
602     case EHTokExtern:
603     case EHTokUniform:
604     case EHTokVolatile:
605     case EHTokShared:
606     case EHTokGroupShared:
607     case EHTokLinear:
608     case EHTokCentroid:
609     case EHTokNointerpolation:
610     case EHTokNoperspective:
611     case EHTokSample:
612     case EHTokRowMajor:
613     case EHTokColumnMajor:
614     case EHTokPackOffset:
615     case EHTokIn:
616     case EHTokOut:
617     case EHTokInOut:
618     case EHTokPrecise:
619     case EHTokLayout:
620     case EHTokGloballyCoherent:
621     case EHTokInline:
622         return keyword;
623
624     // primitive types
625     case EHTokPoint:
626     case EHTokLine:
627     case EHTokTriangle:
628     case EHTokLineAdj:
629     case EHTokTriangleAdj:
630         return keyword;
631
632     // stream out types
633     case EHTokPointStream:
634     case EHTokLineStream:
635     case EHTokTriangleStream:
636         return keyword;
637
638     // Tessellation patches
639     case EHTokInputPatch:
640     case EHTokOutputPatch:
641         return keyword;
642
643     case EHTokBuffer:
644     case EHTokVector:
645     case EHTokMatrix:
646         return keyword;
647
648     // scalar types
649     case EHTokVoid:
650     case EHTokString:
651     case EHTokBool:
652     case EHTokInt:
653     case EHTokUint:
654     case EHTokDword:
655     case EHTokHalf:
656     case EHTokFloat:
657     case EHTokDouble:
658     case EHTokMin16float:
659     case EHTokMin10float:
660     case EHTokMin16int:
661     case EHTokMin12int:
662     case EHTokMin16uint:
663
664     // vector types
665     case EHTokBool1:
666     case EHTokBool2:
667     case EHTokBool3:
668     case EHTokBool4:
669     case EHTokFloat1:
670     case EHTokFloat2:
671     case EHTokFloat3:
672     case EHTokFloat4:
673     case EHTokInt1:
674     case EHTokInt2:
675     case EHTokInt3:
676     case EHTokInt4:
677     case EHTokDouble1:
678     case EHTokDouble2:
679     case EHTokDouble3:
680     case EHTokDouble4:
681     case EHTokUint1:
682     case EHTokUint2:
683     case EHTokUint3:
684     case EHTokUint4:
685     case EHTokHalf1:
686     case EHTokHalf2:
687     case EHTokHalf3:
688     case EHTokHalf4:
689     case EHTokMin16float1:
690     case EHTokMin16float2:
691     case EHTokMin16float3:
692     case EHTokMin16float4:
693     case EHTokMin10float1:
694     case EHTokMin10float2:
695     case EHTokMin10float3:
696     case EHTokMin10float4:
697     case EHTokMin16int1:
698     case EHTokMin16int2:
699     case EHTokMin16int3:
700     case EHTokMin16int4:
701     case EHTokMin12int1:
702     case EHTokMin12int2:
703     case EHTokMin12int3:
704     case EHTokMin12int4:
705     case EHTokMin16uint1:
706     case EHTokMin16uint2:
707     case EHTokMin16uint3:
708     case EHTokMin16uint4:
709
710     // matrix types
711     case EHTokBool1x1:
712     case EHTokBool1x2:
713     case EHTokBool1x3:
714     case EHTokBool1x4:
715     case EHTokBool2x1:
716     case EHTokBool2x2:
717     case EHTokBool2x3:
718     case EHTokBool2x4:
719     case EHTokBool3x1:
720     case EHTokBool3x2:
721     case EHTokBool3x3:
722     case EHTokBool3x4:
723     case EHTokBool4x1:
724     case EHTokBool4x2:
725     case EHTokBool4x3:
726     case EHTokBool4x4:
727     case EHTokInt1x1:
728     case EHTokInt1x2:
729     case EHTokInt1x3:
730     case EHTokInt1x4:
731     case EHTokInt2x1:
732     case EHTokInt2x2:
733     case EHTokInt2x3:
734     case EHTokInt2x4:
735     case EHTokInt3x1:
736     case EHTokInt3x2:
737     case EHTokInt3x3:
738     case EHTokInt3x4:
739     case EHTokInt4x1:
740     case EHTokInt4x2:
741     case EHTokInt4x3:
742     case EHTokInt4x4:
743     case EHTokUint1x1:
744     case EHTokUint1x2:
745     case EHTokUint1x3:
746     case EHTokUint1x4:
747     case EHTokUint2x1:
748     case EHTokUint2x2:
749     case EHTokUint2x3:
750     case EHTokUint2x4:
751     case EHTokUint3x1:
752     case EHTokUint3x2:
753     case EHTokUint3x3:
754     case EHTokUint3x4:
755     case EHTokUint4x1:
756     case EHTokUint4x2:
757     case EHTokUint4x3:
758     case EHTokUint4x4:
759     case EHTokFloat1x1:
760     case EHTokFloat1x2:
761     case EHTokFloat1x3:
762     case EHTokFloat1x4:
763     case EHTokFloat2x1:
764     case EHTokFloat2x2:
765     case EHTokFloat2x3:
766     case EHTokFloat2x4:
767     case EHTokFloat3x1:
768     case EHTokFloat3x2:
769     case EHTokFloat3x3:
770     case EHTokFloat3x4:
771     case EHTokFloat4x1:
772     case EHTokFloat4x2:
773     case EHTokFloat4x3:
774     case EHTokFloat4x4:
775     case EHTokDouble1x1:
776     case EHTokDouble1x2:
777     case EHTokDouble1x3:
778     case EHTokDouble1x4:
779     case EHTokDouble2x1:
780     case EHTokDouble2x2:
781     case EHTokDouble2x3:
782     case EHTokDouble2x4:
783     case EHTokDouble3x1:
784     case EHTokDouble3x2:
785     case EHTokDouble3x3:
786     case EHTokDouble3x4:
787     case EHTokDouble4x1:
788     case EHTokDouble4x2:
789     case EHTokDouble4x3:
790     case EHTokDouble4x4:
791         return keyword;
792
793     // texturing types
794     case EHTokSampler:
795     case EHTokSampler1d:
796     case EHTokSampler2d:
797     case EHTokSampler3d:
798     case EHTokSamplerCube:
799     case EHTokSamplerState:
800     case EHTokSamplerComparisonState:
801     case EHTokTexture:
802     case EHTokTexture1d:
803     case EHTokTexture1darray:
804     case EHTokTexture2d:
805     case EHTokTexture2darray:
806     case EHTokTexture3d:
807     case EHTokTextureCube:
808     case EHTokTextureCubearray:
809     case EHTokTexture2DMS:
810     case EHTokTexture2DMSarray:
811     case EHTokRWTexture1d:
812     case EHTokRWTexture1darray:
813     case EHTokRWTexture2d:
814     case EHTokRWTexture2darray:
815     case EHTokRWTexture3d:
816     case EHTokRWBuffer:
817     case EHTokAppendStructuredBuffer:
818     case EHTokByteAddressBuffer:
819     case EHTokConsumeStructuredBuffer:
820     case EHTokRWByteAddressBuffer:
821     case EHTokRWStructuredBuffer:
822     case EHTokStructuredBuffer:
823         return keyword;
824
825     // variable, user type, ...
826     case EHTokClass:
827     case EHTokStruct:
828     case EHTokTypedef:
829     case EHTokCBuffer:
830     case EHTokTBuffer:
831     case EHTokThis:
832     case EHTokNamespace:
833         return keyword;
834
835     case EHTokBoolConstant:
836         if (strcmp("true", tokenText) == 0)
837             parserToken->b = true;
838         else
839             parserToken->b = false;
840         return keyword;
841
842     // control flow
843     case EHTokFor:
844     case EHTokDo:
845     case EHTokWhile:
846     case EHTokBreak:
847     case EHTokContinue:
848     case EHTokIf:
849     case EHTokElse:
850     case EHTokDiscard:
851     case EHTokReturn:
852     case EHTokCase:
853     case EHTokSwitch:
854     case EHTokDefault:
855         return keyword;
856
857     default:
858         parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
859         return EHTokNone;
860     }
861 }
862
863 EHlslTokenClass HlslScanContext::identifierOrType()
864 {
865     parserToken->string = NewPoolTString(tokenText);
866
867     return EHTokIdentifier;
868 }
869
870 // Give an error for use of a reserved symbol.
871 // However, allow built-in declarations to use reserved words, to allow
872 // extension support before the extension is enabled.
873 EHlslTokenClass HlslScanContext::reservedWord()
874 {
875     if (! parseContext.symbolTable.atBuiltInLevel())
876         parseContext.error(loc, "Reserved word.", tokenText, "", "");
877
878     return EHTokNone;
879 }
880
881 EHlslTokenClass HlslScanContext::identifierOrReserved(bool reserved)
882 {
883     if (reserved) {
884         reservedWord();
885
886         return EHTokNone;
887     }
888
889     if (parseContext.forwardCompatible)
890         parseContext.warn(loc, "using future reserved keyword", tokenText, "");
891
892     return identifierOrType();
893 }
894
895 // For a keyword that was never reserved, until it suddenly
896 // showed up.
897 EHlslTokenClass HlslScanContext::nonreservedKeyword(int version)
898 {
899     if (parseContext.version < version)
900         return identifierOrType();
901
902     return keyword;
903 }
904
905 } // end namespace glslang