fix cases where symbols in the tree didn't get updated during block merging
[platform/upstream/glslang.git] / glslang / MachineIndependent / localintermediate.h
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2016 LunarG, Inc.
4 // Copyright (C) 2017 ARM Limited.
5 // Copyright (C) 2015-2018 Google, Inc.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 //    Redistributions of source code must retain the above copyright
14 //    notice, this list of conditions and the following disclaimer.
15 //
16 //    Redistributions in binary form must reproduce the above
17 //    copyright notice, this list of conditions and the following
18 //    disclaimer in the documentation and/or other materials provided
19 //    with the distribution.
20 //
21 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
22 //    contributors may be used to endorse or promote products derived
23 //    from this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 // POSSIBILITY OF SUCH DAMAGE.
37 //
38
39 #ifndef _LOCAL_INTERMEDIATE_INCLUDED_
40 #define _LOCAL_INTERMEDIATE_INCLUDED_
41
42 #include "../Include/intermediate.h"
43 #include "../Public/ShaderLang.h"
44 #include "Versions.h"
45
46 #include <string>
47 #include <vector>
48 #include <algorithm>
49 #include <set>
50 #include <array>
51
52 class TInfoSink;
53
54 namespace glslang {
55
56 struct TMatrixSelector {
57     int coord1;  // stay agnostic about column/row; this is parse order
58     int coord2;
59 };
60
61 typedef int TVectorSelector;
62
63 const int MaxSwizzleSelectors = 4;
64
65 template<typename selectorType>
66 class TSwizzleSelectors {
67 public:
68     TSwizzleSelectors() : size_(0) { }
69
70     void push_back(selectorType comp)
71     {
72         if (size_ < MaxSwizzleSelectors)
73             components[size_++] = comp;
74     }
75     void resize(int s)
76     {
77         assert(s <= size_);
78         size_ = s;
79     }
80     int size() const { return size_; }
81     selectorType operator[](int i) const
82     {
83         assert(i < MaxSwizzleSelectors);
84         return components[i];
85     }
86
87 private:
88     int size_;
89     selectorType components[MaxSwizzleSelectors];
90 };
91
92 //
93 // Some helper structures for TIntermediate.  Their contents are encapsulated
94 // by TIntermediate.
95 //
96
97 // Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies.
98 // A "call" is a pair: <caller, callee>.
99 // There can be duplicates. General assumption is the list is small.
100 struct TCall {
101     TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
102     TString caller;
103     TString callee;
104     bool visited;
105     bool currentPath;
106     bool errorGiven;
107     int calleeBodyPosition;
108 };
109
110 // A generic 1-D range.
111 struct TRange {
112     TRange(int start, int last) : start(start), last(last) { }
113     bool overlap(const TRange& rhs) const
114     {
115         return last >= rhs.start && start <= rhs.last;
116     }
117     int start;
118     int last;
119 };
120
121 // An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying
122 // within the same location range, component range, and index value.  Locations don't alias unless
123 // all other dimensions of their range overlap.
124 struct TIoRange {
125     TIoRange(TRange location, TRange component, TBasicType basicType, int index)
126         : location(location), component(component), basicType(basicType), index(index) { }
127     bool overlap(const TIoRange& rhs) const
128     {
129         return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
130     }
131     TRange location;
132     TRange component;
133     TBasicType basicType;
134     int index;
135 };
136
137 // An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying
138 // within the same binding and offset range.
139 struct TOffsetRange {
140     TOffsetRange(TRange binding, TRange offset)
141         : binding(binding), offset(offset) { }
142     bool overlap(const TOffsetRange& rhs) const
143     {
144         return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
145     }
146     TRange binding;
147     TRange offset;
148 };
149
150 #ifndef GLSLANG_WEB
151 // Things that need to be tracked per xfb buffer.
152 struct TXfbBuffer {
153     TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false),
154                    contains32BitType(false), contains16BitType(false) { }
155     std::vector<TRange> ranges;  // byte offsets that have already been assigned
156     unsigned int stride;
157     unsigned int implicitStride;
158     bool contains64BitType;
159     bool contains32BitType;
160     bool contains16BitType;
161 };
162 #endif
163
164 // Track a set of strings describing how the module was processed.
165 // This includes command line options, transforms, etc., ideally inclusive enough
166 // to reproduce the steps used to transform the input source to the output.
167 // E.g., see SPIR-V OpModuleProcessed.
168 // Each "process" or "transform" uses is expressed in the form:
169 //   process arg0 arg1 arg2 ...
170 //   process arg0 arg1 arg2 ...
171 // where everything is textual, and there can be zero or more arguments
172 class TProcesses {
173 public:
174     TProcesses() {}
175     ~TProcesses() {}
176
177     void addProcess(const char* process)
178     {
179         processes.push_back(process);
180     }
181     void addProcess(const std::string& process)
182     {
183         processes.push_back(process);
184     }
185     void addArgument(int arg)
186     {
187         processes.back().append(" ");
188         std::string argString = std::to_string(arg);
189         processes.back().append(argString);
190     }
191     void addArgument(const char* arg)
192     {
193         processes.back().append(" ");
194         processes.back().append(arg);
195     }
196     void addArgument(const std::string& arg)
197     {
198         processes.back().append(" ");
199         processes.back().append(arg);
200     }
201     void addIfNonZero(const char* process, int value)
202     {
203         if (value != 0) {
204             addProcess(process);
205             addArgument(value);
206         }
207     }
208
209     const std::vector<std::string>& getProcesses() const { return processes; }
210
211 private:
212     std::vector<std::string> processes;
213 };
214
215 class TSymbolTable;
216 class TSymbol;
217 class TVariable;
218
219 //
220 // Texture and Sampler transformation mode.
221 //
222 enum ComputeDerivativeMode {
223     LayoutDerivativeNone,         // default layout as SPV_NV_compute_shader_derivatives not enabled
224     LayoutDerivativeGroupQuads,   // derivative_group_quadsNV
225     LayoutDerivativeGroupLinear,  // derivative_group_linearNV
226 };
227
228 class TIdMaps {
229 public:
230     TMap<TString, long long>& operator[](long long i) { return maps[i]; }
231     const TMap<TString, long long>& operator[](long long i) const { return maps[i]; }
232 private:
233     TMap<TString, long long> maps[EsiCount];
234 };
235
236 class TNumericFeatures {
237 public:
238     TNumericFeatures() : features(0) { }
239     TNumericFeatures(const TNumericFeatures&) = delete;
240     TNumericFeatures& operator=(const TNumericFeatures&) = delete;
241     typedef enum : unsigned int {
242         shader_explicit_arithmetic_types          = 1 << 0,
243         shader_explicit_arithmetic_types_int8     = 1 << 1,
244         shader_explicit_arithmetic_types_int16    = 1 << 2,
245         shader_explicit_arithmetic_types_int32    = 1 << 3,
246         shader_explicit_arithmetic_types_int64    = 1 << 4,
247         shader_explicit_arithmetic_types_float16  = 1 << 5,
248         shader_explicit_arithmetic_types_float32  = 1 << 6,
249         shader_explicit_arithmetic_types_float64  = 1 << 7,
250         shader_implicit_conversions               = 1 << 8,
251         gpu_shader_fp64                           = 1 << 9,
252         gpu_shader_int16                          = 1 << 10,
253         gpu_shader_half_float                     = 1 << 11,
254     } feature;
255     void insert(feature f) { features |= f; }
256     void erase(feature f) { features &= ~f; }
257     bool contains(feature f) const { return (features & f) != 0; }
258 private:
259     unsigned int features;
260 };
261
262 // MustBeAssigned wraps a T, asserting that it has been assigned with 
263 // operator =() before attempting to read with operator T() or operator ->().
264 // Used to catch cases where fields are read before they have been assigned.
265 template<typename T>
266 class MustBeAssigned
267 {
268 public:
269     MustBeAssigned() = default;
270     MustBeAssigned(const T& v) : value(v) {}
271     operator const T&() const { assert(isSet); return value; }
272     const T* operator ->() const { assert(isSet); return &value; }
273     MustBeAssigned& operator = (const T& v) { value = v; isSet = true; return *this; } 
274 private:
275     T value;
276     bool isSet = false;
277 };
278
279 //
280 // Set of helper functions to help parse and build the tree.
281 //
282 class TIntermediate {
283 public:
284     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) :
285         language(l),
286 #ifndef GLSLANG_ANGLE
287         profile(p), version(v),
288 #endif
289         treeRoot(0),
290         resources(TBuiltInResource{}),
291         numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false),
292         invertY(false),
293         dxPositionW(false),
294         useStorageBuffer(false),
295         invariantAll(false),
296         nanMinMaxClamp(false),
297         depthReplacing(false),
298         uniqueId(0),
299         globalUniformBlockName(""),
300         atomicCounterBlockName(""),
301         globalUniformBlockSet(TQualifier::layoutSetEnd),
302         globalUniformBlockBinding(TQualifier::layoutBindingEnd),
303         atomicCounterBlockSet(TQualifier::layoutSetEnd)
304 #ifndef GLSLANG_WEB
305         ,
306         implicitThisName("@this"), implicitCounterName("@count"),
307         source(EShSourceNone),
308         useVulkanMemoryModel(false),
309         invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
310         inputPrimitive(ElgNone), outputPrimitive(ElgNone),
311         pixelCenterInteger(false), originUpperLeft(false),
312         vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
313         postDepthCoverage(false), depthLayout(EldNone),
314         hlslFunctionality1(false),
315         blendEquations(0), xfbMode(false), multiStream(false),
316         layoutOverrideCoverage(false),
317         geoPassthroughEXT(false),
318         numShaderRecordBlocks(0),
319         computeDerivativeMode(LayoutDerivativeNone),
320         primitives(TQualifier::layoutNotSet),
321         numTaskNVBlocks(0),
322         layoutPrimitiveCulling(false),
323         autoMapBindings(false),
324         autoMapLocations(false),
325         flattenUniformArrays(false),
326         useUnknownFormat(false),
327         hlslOffsets(false),
328         hlslIoMapping(false),
329         useVariablePointers(false),
330         textureSamplerTransformMode(EShTexSampTransKeep),
331         needToLegalize(false),
332         binaryDoubleOutput(false),
333         subgroupUniformControlFlow(false),
334         usePhysicalStorageBuffer(false),
335         spirvRequirement(nullptr),
336         spirvExecutionMode(nullptr),
337         uniformLocationBase(0)
338 #endif
339     {
340         localSize[0] = 1;
341         localSize[1] = 1;
342         localSize[2] = 1;
343         localSizeNotDefault[0] = false;
344         localSizeNotDefault[1] = false;
345         localSizeNotDefault[2] = false;
346         localSizeSpecId[0] = TQualifier::layoutNotSet;
347         localSizeSpecId[1] = TQualifier::layoutNotSet;
348         localSizeSpecId[2] = TQualifier::layoutNotSet;
349 #ifndef GLSLANG_WEB
350         xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
351         shiftBinding.fill(0);
352 #endif
353     }
354
355     void setVersion(int v)
356     {
357 #ifndef GLSLANG_ANGLE
358         version = v;
359 #endif
360     }
361     void setProfile(EProfile p)
362     {
363 #ifndef GLSLANG_ANGLE
364         profile = p;
365 #endif
366     }
367
368     int getVersion() const { return version; }
369     EProfile getProfile() const { return profile; }
370     void setSpv(const SpvVersion& s)
371     {
372         spvVersion = s;
373
374         // client processes
375         if (spvVersion.vulkan > 0)
376             processes.addProcess("client vulkan100");
377         if (spvVersion.openGl > 0)
378             processes.addProcess("client opengl100");
379
380         // target SPV
381         switch (spvVersion.spv) {
382         case 0:
383             break;
384         case EShTargetSpv_1_0:
385             break;
386         case EShTargetSpv_1_1:
387             processes.addProcess("target-env spirv1.1");
388             break;
389         case EShTargetSpv_1_2:
390             processes.addProcess("target-env spirv1.2");
391             break;
392         case EShTargetSpv_1_3:
393             processes.addProcess("target-env spirv1.3");
394             break;
395         case EShTargetSpv_1_4:
396             processes.addProcess("target-env spirv1.4");
397             break;
398         case EShTargetSpv_1_5:
399             processes.addProcess("target-env spirv1.5");
400             break;
401         case EShTargetSpv_1_6:
402             processes.addProcess("target-env spirv1.6");
403             break;
404         default:
405             processes.addProcess("target-env spirvUnknown");
406             break;
407         }
408
409         // target-environment processes
410         switch (spvVersion.vulkan) {
411         case 0:
412             break;
413         case EShTargetVulkan_1_0:
414             processes.addProcess("target-env vulkan1.0");
415             break;
416         case EShTargetVulkan_1_1:
417             processes.addProcess("target-env vulkan1.1");
418             break;
419         case EShTargetVulkan_1_2:
420             processes.addProcess("target-env vulkan1.2");
421             break;
422         default:
423             processes.addProcess("target-env vulkanUnknown");
424             break;
425         }
426         if (spvVersion.openGl > 0)
427             processes.addProcess("target-env opengl");
428     }
429     const SpvVersion& getSpv() const { return spvVersion; }
430     EShLanguage getStage() const { return language; }
431     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
432     const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
433     bool isRayTracingStage() const {
434         return language >= EShLangRayGen && language <= EShLangCallableNV;
435     }
436
437     void setTreeRoot(TIntermNode* r) { treeRoot = r; }
438     TIntermNode* getTreeRoot() const { return treeRoot; }
439     void incrementEntryPointCount() { ++numEntryPoints; }
440     int getNumEntryPoints() const { return numEntryPoints; }
441     int getNumErrors() const { return numErrors; }
442     void addPushConstantCount() { ++numPushConstants; }
443     void setLimits(const TBuiltInResource& r) { resources = r; }
444     const TBuiltInResource& getLimits() const { return resources; }
445
446     bool postProcess(TIntermNode*, EShLanguage);
447     void removeTree();
448
449     void setEntryPointName(const char* ep)
450     {
451         entryPointName = ep;
452         processes.addProcess("entry-point");
453         processes.addArgument(entryPointName);
454     }
455     void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
456     const std::string& getEntryPointName() const { return entryPointName; }
457     const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
458
459     void setInvertY(bool invert)
460     {
461         invertY = invert;
462         if (invertY)
463             processes.addProcess("invert-y");
464     }
465     bool getInvertY() const { return invertY; }
466
467     void setDxPositionW(bool dxPosW)
468     {
469       dxPositionW = dxPosW;
470       if (dxPositionW)
471         processes.addProcess("dx-position-w");
472     }
473     bool getDxPositionW() const { return dxPositionW; }
474
475 #ifdef ENABLE_HLSL
476     void setSource(EShSource s) { source = s; }
477     EShSource getSource() const { return source; }
478 #else
479     void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; }
480     EShSource getSource() const { return EShSourceGlsl; }
481 #endif
482
483     bool isRecursive() const { return recursive; }
484
485     TIntermSymbol* addSymbol(const TVariable&);
486     TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
487     TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
488     TIntermSymbol* addSymbol(const TIntermSymbol&);
489     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
490     std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
491     TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
492     TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
493     void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
494     TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
495     TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
496     TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
497     TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
498     TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&);
499     TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
500     bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
501     bool isIntegralPromotion(TBasicType from, TBasicType to) const;
502     bool isFPPromotion(TBasicType from, TBasicType to) const;
503     bool isIntegralConversion(TBasicType from, TBasicType to) const;
504     bool isFPConversion(TBasicType from, TBasicType to) const;
505     bool isFPIntegralConversion(TBasicType from, TBasicType to) const;
506     TOperator mapTypeToConstructorOp(const TType&) const;
507     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
508     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
509     TIntermAggregate* makeAggregate(TIntermNode* node);
510     TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
511     TIntermAggregate* makeAggregate(const TSourceLoc&);
512     TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&);
513     bool areAllChildConst(TIntermAggregate* aggrNode);
514     TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
515     TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
516     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
517     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
518     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
519     TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const;
520     TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const;
521     TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const;
522     TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
523     TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
524     TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
525     TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
526     TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
527     TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
528     TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
529     TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
530     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
531     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
532     TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
533     TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst,
534         const TSourceLoc&, TIntermLoop*&);
535     TIntermBranch* addBranch(TOperator, const TSourceLoc&);
536     TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
537     template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
538
539     // Low level functions to add nodes (no conversions or other higher level transformations)
540     // If a type is provided, the node's type will be set to it.
541     TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const;
542     TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&,
543         const TType&) const;
544     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const;
545     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const;
546
547     // Constant folding (in Constant.cpp)
548     TIntermTyped* fold(TIntermAggregate* aggrNode);
549     TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
550     TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&);
551     TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&);
552
553     // Tree ops
554     static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay , bool BufferReferenceOk = false);
555
556     // Linkage related
557     void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
558     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
559     TIntermAggregate* findLinkerObjects() const;
560
561     void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); }
562     const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); }
563     void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; }
564     unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; }
565     void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; }
566     unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; }
567
568     void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); }
569     const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); }
570     void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; }
571     unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; }
572
573
574     void setUseStorageBuffer() { useStorageBuffer = true; }
575     bool usingStorageBuffer() const { return useStorageBuffer; }
576     void setInvariantAll() { invariantAll = true; }
577     bool isInvariantAll() const { return invariantAll; }
578     void setDepthReplacing() { depthReplacing = true; }
579     bool isDepthReplacing() const { return depthReplacing; }
580     bool setLocalSize(int dim, int size)
581     {
582         if (localSizeNotDefault[dim])
583             return size == localSize[dim];
584         localSizeNotDefault[dim] = true;
585         localSize[dim] = size;
586         return true;
587     }
588     unsigned int getLocalSize(int dim) const { return localSize[dim]; }
589     bool isLocalSizeSet() const
590     {
591         // Return true if any component has been set (i.e. any component is not default).
592         return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2];
593     }
594     bool setLocalSizeSpecId(int dim, int id)
595     {
596         if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
597             return id == localSizeSpecId[dim];
598         localSizeSpecId[dim] = id;
599         return true;
600     }
601     int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
602     bool isLocalSizeSpecialized() const
603     {
604         // Return true if any component has been specialized.
605         return localSizeSpecId[0] != TQualifier::layoutNotSet ||
606                localSizeSpecId[1] != TQualifier::layoutNotSet ||
607                localSizeSpecId[2] != TQualifier::layoutNotSet;
608     }
609 #ifdef GLSLANG_WEB
610     void output(TInfoSink&, bool tree) { }
611
612     bool isEsProfile() const { return false; }
613     bool getXfbMode() const { return false; }
614     bool isMultiStream() const { return false; }
615     TLayoutGeometry getOutputPrimitive() const { return ElgNone; }
616     bool getPostDepthCoverage() const { return false; }
617     bool getEarlyFragmentTests() const { return false; }
618     TLayoutDepth getDepth() const { return EldNone; }
619     bool getPixelCenterInteger() const { return false; }
620     void setOriginUpperLeft() { }
621     bool getOriginUpperLeft() const { return true; }
622     TInterlockOrdering getInterlockOrdering() const { return EioNone; }
623
624     bool getAutoMapBindings() const { return false; }
625     bool getAutoMapLocations() const { return false; }
626     int getNumPushConstants() const { return 0; }
627     void addShaderRecordCount() { }
628     void addTaskNVCount() { }
629     void setUseVulkanMemoryModel() { }
630     bool usingVulkanMemoryModel() const { return false; }
631     bool usingPhysicalStorageBuffer() const { return false; }
632     bool usingVariablePointers() const { return false; }
633     unsigned getXfbStride(int buffer) const { return 0; }
634     bool hasLayoutDerivativeModeNone() const { return false; }
635     ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; }
636 #else
637     void output(TInfoSink&, bool tree);
638
639     bool isEsProfile() const { return profile == EEsProfile; }
640
641     void setShiftBinding(TResourceType res, unsigned int shift)
642     {
643         shiftBinding[res] = shift;
644
645         const char* name = getResourceName(res);
646         if (name != nullptr)
647             processes.addIfNonZero(name, shift);
648     }
649
650     unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; }
651
652     void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set)
653     {
654         if (shift == 0) // ignore if there's no shift: it's a no-op.
655             return;
656
657         shiftBindingForSet[res][set] = shift;
658
659         const char* name = getResourceName(res);
660         if (name != nullptr) {
661             processes.addProcess(name);
662             processes.addArgument(shift);
663             processes.addArgument(set);
664         }
665     }
666
667     int getShiftBindingForSet(TResourceType res, unsigned int set) const
668     {
669         const auto shift = shiftBindingForSet[res].find(set);
670         return shift == shiftBindingForSet[res].end() ? -1 : shift->second;
671     }
672     bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); }
673
674     void setResourceSetBinding(const std::vector<std::string>& shift)
675     {
676         resourceSetBinding = shift;
677         if (shift.size() > 0) {
678             processes.addProcess("resource-set-binding");
679             for (int s = 0; s < (int)shift.size(); ++s)
680                 processes.addArgument(shift[s]);
681         }
682     }
683     const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
684     void setAutoMapBindings(bool map)
685     {
686         autoMapBindings = map;
687         if (autoMapBindings)
688             processes.addProcess("auto-map-bindings");
689     }
690     bool getAutoMapBindings() const { return autoMapBindings; }
691     void setAutoMapLocations(bool map)
692     {
693         autoMapLocations = map;
694         if (autoMapLocations)
695             processes.addProcess("auto-map-locations");
696     }
697     bool getAutoMapLocations() const { return autoMapLocations; }
698
699 #ifdef ENABLE_HLSL
700     void setFlattenUniformArrays(bool flatten)
701     {
702         flattenUniformArrays = flatten;
703         if (flattenUniformArrays)
704             processes.addProcess("flatten-uniform-arrays");
705     }
706     bool getFlattenUniformArrays() const { return flattenUniformArrays; }
707 #endif
708     void setNoStorageFormat(bool b)
709     {
710         useUnknownFormat = b;
711         if (useUnknownFormat)
712             processes.addProcess("no-storage-format");
713     }
714     bool getNoStorageFormat() const { return useUnknownFormat; }
715     void setUseVulkanMemoryModel()
716     {
717         useVulkanMemoryModel = true;
718         processes.addProcess("use-vulkan-memory-model");
719     }
720     bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; }
721     void setUsePhysicalStorageBuffer()
722     {
723         usePhysicalStorageBuffer = true;
724     }
725     bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; }
726     void setUseVariablePointers()
727     {
728         useVariablePointers = true;
729         processes.addProcess("use-variable-pointers");
730     }
731     bool usingVariablePointers() const { return useVariablePointers; }
732
733 #ifdef ENABLE_HLSL
734     template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
735     bool hasCounterBufferName(const TString& name) const {
736         size_t len = strlen(implicitCounterName);
737         return name.size() > len &&
738                name.compare(name.size() - len, len, implicitCounterName) == 0;
739     }
740 #endif
741
742     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
743     int getNumPushConstants() const { return numPushConstants; }
744     void addShaderRecordCount() { ++numShaderRecordBlocks; }
745     void addTaskNVCount() { ++numTaskNVBlocks; }
746
747     bool setInvocations(int i)
748     {
749         if (invocations != TQualifier::layoutNotSet)
750             return invocations == i;
751         invocations = i;
752         return true;
753     }
754     int getInvocations() const { return invocations; }
755     bool setVertices(int m)
756     {
757         if (vertices != TQualifier::layoutNotSet)
758             return vertices == m;
759         vertices = m;
760         return true;
761     }
762     int getVertices() const { return vertices; }
763     bool setInputPrimitive(TLayoutGeometry p)
764     {
765         if (inputPrimitive != ElgNone)
766             return inputPrimitive == p;
767         inputPrimitive = p;
768         return true;
769     }
770     TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
771     bool setVertexSpacing(TVertexSpacing s)
772     {
773         if (vertexSpacing != EvsNone)
774             return vertexSpacing == s;
775         vertexSpacing = s;
776         return true;
777     }
778     TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
779     bool setVertexOrder(TVertexOrder o)
780     {
781         if (vertexOrder != EvoNone)
782             return vertexOrder == o;
783         vertexOrder = o;
784         return true;
785     }
786     TVertexOrder getVertexOrder() const { return vertexOrder; }
787     void setPointMode() { pointMode = true; }
788     bool getPointMode() const { return pointMode; }
789
790     bool setInterlockOrdering(TInterlockOrdering o)
791     {
792         if (interlockOrdering != EioNone)
793             return interlockOrdering == o;
794         interlockOrdering = o;
795         return true;
796     }
797     TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; }
798
799     void setXfbMode() { xfbMode = true; }
800     bool getXfbMode() const { return xfbMode; }
801     void setMultiStream() { multiStream = true; }
802     bool isMultiStream() const { return multiStream; }
803     bool setOutputPrimitive(TLayoutGeometry p)
804     {
805         if (outputPrimitive != ElgNone)
806             return outputPrimitive == p;
807         outputPrimitive = p;
808         return true;
809     }
810     TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
811     void setPostDepthCoverage() { postDepthCoverage = true; }
812     bool getPostDepthCoverage() const { return postDepthCoverage; }
813     void setEarlyFragmentTests() { earlyFragmentTests = true; }
814     bool getEarlyFragmentTests() const { return earlyFragmentTests; }
815     bool setDepth(TLayoutDepth d)
816     {
817         if (depthLayout != EldNone)
818             return depthLayout == d;
819         depthLayout = d;
820         return true;
821     }
822     TLayoutDepth getDepth() const { return depthLayout; }
823     void setOriginUpperLeft() { originUpperLeft = true; }
824     bool getOriginUpperLeft() const { return originUpperLeft; }
825     void setPixelCenterInteger() { pixelCenterInteger = true; }
826     bool getPixelCenterInteger() const { return pixelCenterInteger; }
827     void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
828     unsigned int getBlendEquations() const { return blendEquations; }
829     bool setXfbBufferStride(int buffer, unsigned stride)
830     {
831         if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
832             return xfbBuffers[buffer].stride == stride;
833         xfbBuffers[buffer].stride = stride;
834         return true;
835     }
836     unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; }
837     int addXfbBufferOffset(const TType&);
838     unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const;
839     unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const;
840     void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; }
841     bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
842     void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
843     bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
844     void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
845     bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
846     ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
847     void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; }
848     bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; }
849     bool setPrimitives(int m)
850     {
851         if (primitives != TQualifier::layoutNotSet)
852             return primitives == m;
853         primitives = m;
854         return true;
855     }
856     int getPrimitives() const { return primitives; }
857     const char* addSemanticName(const TString& name)
858     {
859         return semanticNameSet.insert(name).first->c_str();
860     }
861     void addUniformLocationOverride(const char* nameStr, int location)
862     {
863         std::string name = nameStr;
864         uniformLocationOverrides[name] = location;
865     }
866
867     int getUniformLocationOverride(const char* nameStr) const
868     {
869         std::string name = nameStr;
870         auto pos = uniformLocationOverrides.find(name);
871         if (pos == uniformLocationOverrides.end())
872             return -1;
873         else
874             return pos->second;
875     }
876
877     void setUniformLocationBase(int base) { uniformLocationBase = base; }
878     int getUniformLocationBase() const { return uniformLocationBase; }
879
880     void setNeedsLegalization() { needToLegalize = true; }
881     bool needsLegalization() const { return needToLegalize; }
882
883     void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
884     bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
885
886     void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
887     bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
888
889     // GL_EXT_spirv_intrinsics
890     void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
891     bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
892     const TSpirvRequirement& getSpirvRequirement() const { return *spirvRequirement; }
893     void insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args = nullptr);
894     void insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args);
895     bool hasSpirvExecutionMode() const { return spirvExecutionMode != nullptr; }
896     const TSpirvExecutionMode& getSpirvExecutionMode() const { return *spirvExecutionMode; }
897 #endif // GLSLANG_WEB
898
899     void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
900     {
901         std::string name(nameStr);
902         blockBackingOverrides[name] = backing;
903     }
904     TBlockStorageClass getBlockStorageOverride(const char* nameStr) const
905     {
906         std::string name = nameStr;
907         auto pos = blockBackingOverrides.find(name);
908         if (pos == blockBackingOverrides.end())
909             return EbsNone;
910         else
911             return pos->second;
912     }
913 #ifdef ENABLE_HLSL
914     void setHlslFunctionality1() { hlslFunctionality1 = true; }
915     bool getHlslFunctionality1() const { return hlslFunctionality1; }
916     void setHlslOffsets()
917     {
918         hlslOffsets = true;
919         if (hlslOffsets)
920             processes.addProcess("hlsl-offsets");
921     }
922     bool usingHlslOffsets() const { return hlslOffsets; }
923     void setHlslIoMapping(bool b)
924     {
925         hlslIoMapping = b;
926         if (hlslIoMapping)
927             processes.addProcess("hlsl-iomap");
928     }
929     bool usingHlslIoMapping() { return hlslIoMapping; }
930 #else
931     bool getHlslFunctionality1() const { return false; }
932     bool usingHlslOffsets() const { return false; }
933     bool usingHlslIoMapping() { return false; }
934 #endif
935
936     bool usingScalarBlockLayout() const {
937         for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) {
938             if (*extIt == E_GL_EXT_scalar_block_layout)
939                 return true;
940         }
941         return false;
942     }
943
944     bool IsRequestedExtension(const char* extension) const
945     {
946         return (requestedExtensions.find(extension) != requestedExtensions.end());
947     }
948
949     void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
950     void merge(TInfoSink&, TIntermediate&);
951     void finalCheck(TInfoSink&, bool keepUncalled);
952
953     void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
954     void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
955     void checkStageIO(TInfoSink&, TIntermediate&);
956
957     bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
958     TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
959
960     void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
961     bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
962
963     int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
964     int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
965     int checkLocationRT(int set, int location);
966     int addUsedOffsets(int binding, int offset, int numOffsets);
967     bool addUsedConstantId(int id);
968     static int computeTypeLocationSize(const TType&, EShLanguage);
969     static int computeTypeUniformLocationSize(const TType&);
970
971     static int getBaseAlignmentScalar(const TType&, int& size);
972     static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
973     static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
974     static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
975     static bool improperStraddle(const TType& type, int size, int offset);
976     static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize);
977     static int getOffset(const TType& type, int index);
978     static int getBlockSize(const TType& blockType);
979     static int computeBufferReferenceTypeSize(const TType&);
980     static bool isIoResizeArray(const TType& type, EShLanguage language);
981
982     bool promote(TIntermOperator*);
983     void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
984     bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
985
986     void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; }
987     const std::string& getSourceFile() const { return sourceFile; }
988     void addSourceText(const char* text, size_t len) { sourceText.append(text, len); }
989     const std::string& getSourceText() const { return sourceText; }
990     const std::map<std::string, std::string>& getIncludeText() const { return includeText; }
991     void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); }
992     void addProcesses(const std::vector<std::string>& p)
993     {
994         for (int i = 0; i < (int)p.size(); ++i)
995             processes.addProcess(p[i]);
996     }
997     void addProcess(const std::string& process) { processes.addProcess(process); }
998     void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
999     const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
1000     unsigned long long getUniqueId() const { return uniqueId; }
1001     void setUniqueId(unsigned long long id) { uniqueId = id; }
1002
1003     // Certain explicit conversions are allowed conditionally
1004 #ifdef GLSLANG_WEB
1005     bool getArithemeticInt8Enabled() const { return false; }
1006     bool getArithemeticInt16Enabled() const { return false; }
1007     bool getArithemeticFloat16Enabled() const { return false; }
1008     void updateNumericFeature(TNumericFeatures::feature f, bool on) { }
1009 #else
1010     bool getArithemeticInt8Enabled() const {
1011         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1012                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
1013     }
1014     bool getArithemeticInt16Enabled() const {
1015         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1016                numericFeatures.contains(TNumericFeatures::gpu_shader_int16) ||
1017                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
1018     }
1019
1020     bool getArithemeticFloat16Enabled() const {
1021         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1022                numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
1023                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
1024     }
1025     void updateNumericFeature(TNumericFeatures::feature f, bool on)
1026         { on ? numericFeatures.insert(f) : numericFeatures.erase(f); }
1027 #endif
1028
1029 protected:
1030     TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
1031     void error(TInfoSink& infoSink, const char*);
1032     void warn(TInfoSink& infoSink, const char*);
1033     void mergeCallGraphs(TInfoSink&, TIntermediate&);
1034     void mergeModes(TInfoSink&, TIntermediate&);
1035     void mergeTrees(TInfoSink&, TIntermediate&);
1036     void seedIdMap(TIdMaps& idMaps, long long& IdShift);
1037     void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&);
1038     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
1039     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage);
1040     void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot);
1041     void mergeImplicitArraySizes(TType&, const TType&);
1042     void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage);
1043     void checkCallGraphCycles(TInfoSink&);
1044     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
1045     void inOutLocationCheck(TInfoSink&);
1046     void sharedBlockCheck(TInfoSink&);
1047     bool userOutputUsed() const;
1048     bool isSpecializationOperation(const TIntermOperator&) const;
1049     bool isNonuniformPropagating(TOperator) const;
1050     bool promoteUnary(TIntermUnary&);
1051     bool promoteBinary(TIntermBinary&);
1052     void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
1053     bool promoteAggregate(TIntermAggregate&);
1054     void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
1055     void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
1056     bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
1057     void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
1058     bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
1059     std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const;
1060
1061     static const char* getResourceName(TResourceType);
1062
1063     const EShLanguage language;  // stage, known at construction time
1064     std::string entryPointName;
1065     std::string entryPointMangledName;
1066     typedef std::list<TCall> TGraph;
1067     TGraph callGraph;
1068
1069 #ifdef GLSLANG_ANGLE
1070     const EProfile profile = ECoreProfile;
1071     const int version = 450;
1072 #else
1073     EProfile profile;                           // source profile
1074     int version;                                // source version
1075 #endif
1076     SpvVersion spvVersion;
1077     TIntermNode* treeRoot;
1078     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
1079     MustBeAssigned<TBuiltInResource> resources;
1080     int numEntryPoints;
1081     int numErrors;
1082     int numPushConstants;
1083     bool recursive;
1084     bool invertY;
1085     bool dxPositionW;
1086     bool useStorageBuffer;
1087     bool invariantAll;
1088     bool nanMinMaxClamp;            // true if desiring min/max/clamp to favor non-NaN over NaN
1089     bool depthReplacing;
1090     int localSize[3];
1091     bool localSizeNotDefault[3];
1092     int localSizeSpecId[3];
1093     unsigned long long uniqueId;
1094
1095     std::string globalUniformBlockName;
1096     std::string atomicCounterBlockName;
1097     unsigned int globalUniformBlockSet;
1098     unsigned int globalUniformBlockBinding;
1099     unsigned int atomicCounterBlockSet;
1100
1101 #ifndef GLSLANG_WEB
1102 public:
1103     const char* const implicitThisName;
1104     const char* const implicitCounterName;
1105 protected:
1106     EShSource source;            // source language, known a bit later
1107     bool useVulkanMemoryModel;
1108     int invocations;
1109     int vertices;
1110     TLayoutGeometry inputPrimitive;
1111     TLayoutGeometry outputPrimitive;
1112     bool pixelCenterInteger;
1113     bool originUpperLeft;
1114     TVertexSpacing vertexSpacing;
1115     TVertexOrder vertexOrder;
1116     TInterlockOrdering interlockOrdering;
1117     bool pointMode;
1118     bool earlyFragmentTests;
1119     bool postDepthCoverage;
1120     TLayoutDepth depthLayout;
1121     bool hlslFunctionality1;
1122     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
1123     bool xfbMode;
1124     std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
1125     bool multiStream;
1126     bool layoutOverrideCoverage;
1127     bool geoPassthroughEXT;
1128     int numShaderRecordBlocks;
1129     ComputeDerivativeMode computeDerivativeMode;
1130     int primitives;
1131     int numTaskNVBlocks;
1132     bool layoutPrimitiveCulling;
1133
1134     // Base shift values
1135     std::array<unsigned int, EResCount> shiftBinding;
1136
1137     // Per-descriptor-set shift values
1138     std::array<std::map<int, int>, EResCount> shiftBindingForSet;
1139
1140     std::vector<std::string> resourceSetBinding;
1141     bool autoMapBindings;
1142     bool autoMapLocations;
1143     bool flattenUniformArrays;
1144     bool useUnknownFormat;
1145     bool hlslOffsets;
1146     bool hlslIoMapping;
1147     bool useVariablePointers;
1148
1149     std::set<TString> semanticNameSet;
1150
1151     EShTextureSamplerTransformMode textureSamplerTransformMode;
1152
1153     bool needToLegalize;
1154     bool binaryDoubleOutput;
1155     bool subgroupUniformControlFlow;
1156     bool usePhysicalStorageBuffer;
1157
1158     TSpirvRequirement* spirvRequirement;
1159     TSpirvExecutionMode* spirvExecutionMode;
1160
1161     std::unordered_map<std::string, int> uniformLocationOverrides;
1162     int uniformLocationBase;
1163     TNumericFeatures numericFeatures;
1164 #endif
1165     std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
1166
1167     std::unordered_set<int> usedConstantId; // specialization constant ids used
1168     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
1169     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
1170     std::vector<TRange> usedIoRT[2];        // sets of used location, one for rayPayload/rayPayloadIN and other
1171                                             // for callableData/callableDataIn
1172     // set of names of statically read/written I/O that might need extra checking
1173     std::set<TString> ioAccessed;
1174     // source code of shader, useful as part of debug information
1175     std::string sourceFile;
1176     std::string sourceText;
1177
1178     // Included text. First string is a name, second is the included text
1179     std::map<std::string, std::string> includeText;
1180
1181     // for OpModuleProcessed, or equivalent
1182     TProcesses processes;
1183
1184 private:
1185     void operator=(TIntermediate&); // prevent assignments
1186 };
1187
1188 } // end namespace glslang
1189
1190 #endif // _LOCAL_INTERMEDIATE_INCLUDED_