Merge pull request #2985 from jeremy-lunarg/hayes-nonsemantic-shader-debuginfo-rebase
[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         enhancedMsgs(false),
295         debugInfo(false),
296         useStorageBuffer(false),
297         invariantAll(false),
298         nanMinMaxClamp(false),
299         depthReplacing(false),
300         stencilReplacing(false),
301         uniqueId(0),
302         globalUniformBlockName(""),
303         atomicCounterBlockName(""),
304         globalUniformBlockSet(TQualifier::layoutSetEnd),
305         globalUniformBlockBinding(TQualifier::layoutBindingEnd),
306         atomicCounterBlockSet(TQualifier::layoutSetEnd)
307 #ifndef GLSLANG_WEB
308         ,
309         implicitThisName("@this"), implicitCounterName("@count"),
310         source(EShSourceNone),
311         useVulkanMemoryModel(false),
312         invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet),
313         inputPrimitive(ElgNone), outputPrimitive(ElgNone),
314         pixelCenterInteger(false), originUpperLeft(false),texCoordBuiltinRedeclared(false),
315         vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
316         postDepthCoverage(false), earlyAndLateFragmentTestsAMD(false), depthLayout(EldNone), stencilLayout(ElsNone),
317         hlslFunctionality1(false),
318         blendEquations(0), xfbMode(false), multiStream(false),
319         layoutOverrideCoverage(false),
320         geoPassthroughEXT(false),
321         numShaderRecordBlocks(0),
322         computeDerivativeMode(LayoutDerivativeNone),
323         primitives(TQualifier::layoutNotSet),
324         numTaskNVBlocks(0),
325         layoutPrimitiveCulling(false),
326         numTaskEXTPayloads(0),
327         autoMapBindings(false),
328         autoMapLocations(false),
329         flattenUniformArrays(false),
330         useUnknownFormat(false),
331         hlslOffsets(false),
332         hlslIoMapping(false),
333         useVariablePointers(false),
334         textureSamplerTransformMode(EShTexSampTransKeep),
335         needToLegalize(false),
336         binaryDoubleOutput(false),
337         subgroupUniformControlFlow(false),
338         usePhysicalStorageBuffer(false),
339         spirvRequirement(nullptr),
340         spirvExecutionMode(nullptr),
341         uniformLocationBase(0)
342 #endif
343     {
344         localSize[0] = 1;
345         localSize[1] = 1;
346         localSize[2] = 1;
347         localSizeNotDefault[0] = false;
348         localSizeNotDefault[1] = false;
349         localSizeNotDefault[2] = false;
350         localSizeSpecId[0] = TQualifier::layoutNotSet;
351         localSizeSpecId[1] = TQualifier::layoutNotSet;
352         localSizeSpecId[2] = TQualifier::layoutNotSet;
353 #ifndef GLSLANG_WEB
354         xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
355         shiftBinding.fill(0);
356 #endif
357     }
358
359     void setVersion(int v)
360     {
361 #ifndef GLSLANG_ANGLE
362         version = v;
363 #endif
364     }
365     void setProfile(EProfile p)
366     {
367 #ifndef GLSLANG_ANGLE
368         profile = p;
369 #endif
370     }
371
372     int getVersion() const { return version; }
373     EProfile getProfile() const { return profile; }
374     void setSpv(const SpvVersion& s)
375     {
376         spvVersion = s;
377
378         // client processes
379         if (spvVersion.vulkan > 0)
380             processes.addProcess("client vulkan100");
381         if (spvVersion.openGl > 0)
382             processes.addProcess("client opengl100");
383
384         // target SPV
385         switch (spvVersion.spv) {
386         case 0:
387             break;
388         case EShTargetSpv_1_0:
389             break;
390         case EShTargetSpv_1_1:
391             processes.addProcess("target-env spirv1.1");
392             break;
393         case EShTargetSpv_1_2:
394             processes.addProcess("target-env spirv1.2");
395             break;
396         case EShTargetSpv_1_3:
397             processes.addProcess("target-env spirv1.3");
398             break;
399         case EShTargetSpv_1_4:
400             processes.addProcess("target-env spirv1.4");
401             break;
402         case EShTargetSpv_1_5:
403             processes.addProcess("target-env spirv1.5");
404             break;
405         case EShTargetSpv_1_6:
406             processes.addProcess("target-env spirv1.6");
407             break;
408         default:
409             processes.addProcess("target-env spirvUnknown");
410             break;
411         }
412
413         // target-environment processes
414         switch (spvVersion.vulkan) {
415         case 0:
416             break;
417         case EShTargetVulkan_1_0:
418             processes.addProcess("target-env vulkan1.0");
419             break;
420         case EShTargetVulkan_1_1:
421             processes.addProcess("target-env vulkan1.1");
422             break;
423         case EShTargetVulkan_1_2:
424             processes.addProcess("target-env vulkan1.2");
425             break;
426         case EShTargetVulkan_1_3:
427             processes.addProcess("target-env vulkan1.3");
428             break;
429         default:
430             processes.addProcess("target-env vulkanUnknown");
431             break;
432         }
433         if (spvVersion.openGl > 0)
434             processes.addProcess("target-env opengl");
435     }
436     const SpvVersion& getSpv() const { return spvVersion; }
437     EShLanguage getStage() const { return language; }
438     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
439     const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
440     bool isRayTracingStage() const {
441         return language >= EShLangRayGen && language <= EShLangCallableNV;
442     }
443
444     void setTreeRoot(TIntermNode* r) { treeRoot = r; }
445     TIntermNode* getTreeRoot() const { return treeRoot; }
446     void incrementEntryPointCount() { ++numEntryPoints; }
447     int getNumEntryPoints() const { return numEntryPoints; }
448     int getNumErrors() const { return numErrors; }
449     void addPushConstantCount() { ++numPushConstants; }
450     void setLimits(const TBuiltInResource& r) { resources = r; }
451     const TBuiltInResource& getLimits() const { return resources; }
452
453     bool postProcess(TIntermNode*, EShLanguage);
454     void removeTree();
455
456     void setEntryPointName(const char* ep)
457     {
458         entryPointName = ep;
459         processes.addProcess("entry-point");
460         processes.addArgument(entryPointName);
461     }
462     void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; }
463     const std::string& getEntryPointName() const { return entryPointName; }
464     const std::string& getEntryPointMangledName() const { return entryPointMangledName; }
465
466     void setDebugInfo(bool debuginfo)
467     {
468         debugInfo = debuginfo;
469     }
470     bool getDebugInfo() const { return debugInfo; }
471
472     void setInvertY(bool invert)
473     {
474         invertY = invert;
475         if (invertY)
476             processes.addProcess("invert-y");
477     }
478     bool getInvertY() const { return invertY; }
479
480     void setDxPositionW(bool dxPosW)
481     {
482         dxPositionW = dxPosW;
483         if (dxPositionW)
484             processes.addProcess("dx-position-w");
485     }
486     bool getDxPositionW() const { return dxPositionW; }
487
488     void setEnhancedMsgs()
489     {
490         enhancedMsgs = true;
491     }
492     bool getEnhancedMsgs() const { return enhancedMsgs && getSource() == EShSourceGlsl; }
493
494 #ifdef ENABLE_HLSL
495     void setSource(EShSource s) { source = s; }
496     EShSource getSource() const { return source; }
497 #else
498     void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; }
499     EShSource getSource() const { return EShSourceGlsl; }
500 #endif
501
502     bool isRecursive() const { return recursive; }
503
504     TIntermSymbol* addSymbol(const TVariable&);
505     TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&);
506     TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
507     TIntermSymbol* addSymbol(const TIntermSymbol&);
508     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
509     std::tuple<TIntermTyped*, TIntermTyped*> addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1);
510     TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
511     TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const;
512     void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
513     TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
514     TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
515     TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
516     TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
517     TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&);
518     TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType);
519     bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const;
520     bool isIntegralPromotion(TBasicType from, TBasicType to) const;
521     bool isFPPromotion(TBasicType from, TBasicType to) const;
522     bool isIntegralConversion(TBasicType from, TBasicType to) const;
523     bool isFPConversion(TBasicType from, TBasicType to) const;
524     bool isFPIntegralConversion(TBasicType from, TBasicType to) const;
525     TOperator mapTypeToConstructorOp(const TType&) const;
526     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
527     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
528     TIntermAggregate* makeAggregate(TIntermNode* node);
529     TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
530     TIntermAggregate* makeAggregate(const TSourceLoc&);
531     TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&);
532     bool areAllChildConst(TIntermAggregate* aggrNode);
533     TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
534     TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
535     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
536     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&);
537     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const;
538     TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const;
539     TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const;
540     TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const;
541     TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
542     TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const;
543     TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
544     TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
545     TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
546     TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
547     TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
548     TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
549     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
550     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
551     TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
552     TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst,
553         const TSourceLoc&, TIntermLoop*&);
554     TIntermBranch* addBranch(TOperator, const TSourceLoc&);
555     TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
556     template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
557
558     // Low level functions to add nodes (no conversions or other higher level transformations)
559     // If a type is provided, the node's type will be set to it.
560     TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const;
561     TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&,
562         const TType&) const;
563     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const;
564     TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const;
565
566     // Constant folding (in Constant.cpp)
567     TIntermTyped* fold(TIntermAggregate* aggrNode);
568     TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
569     TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&);
570     TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& fields, const TSourceLoc&);
571
572     // Tree ops
573     static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay , bool BufferReferenceOk = false);
574
575     // Linkage related
576     void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
577     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
578     TIntermAggregate* findLinkerObjects() const;
579
580     void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); }
581     const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); }
582     void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; }
583     unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; }
584     void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; }
585     unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; }
586
587     void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); }
588     const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); }
589     void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; }
590     unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; }
591
592
593     void setUseStorageBuffer() { useStorageBuffer = true; }
594     bool usingStorageBuffer() const { return useStorageBuffer; }
595     void setInvariantAll() { invariantAll = true; }
596     bool isInvariantAll() const { return invariantAll; }
597     void setDepthReplacing() { depthReplacing = true; }
598     bool isDepthReplacing() const { return depthReplacing; }
599     void setStencilReplacing() { stencilReplacing = true; }
600     bool isStencilReplacing() const { return stencilReplacing; }
601     bool setLocalSize(int dim, int size)
602     {
603         if (localSizeNotDefault[dim])
604             return size == localSize[dim];
605         localSizeNotDefault[dim] = true;
606         localSize[dim] = size;
607         return true;
608     }
609     unsigned int getLocalSize(int dim) const { return localSize[dim]; }
610     bool isLocalSizeSet() const
611     {
612         // Return true if any component has been set (i.e. any component is not default).
613         return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2];
614     }
615     bool setLocalSizeSpecId(int dim, int id)
616     {
617         if (localSizeSpecId[dim] != TQualifier::layoutNotSet)
618             return id == localSizeSpecId[dim];
619         localSizeSpecId[dim] = id;
620         return true;
621     }
622     int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; }
623     bool isLocalSizeSpecialized() const
624     {
625         // Return true if any component has been specialized.
626         return localSizeSpecId[0] != TQualifier::layoutNotSet ||
627                localSizeSpecId[1] != TQualifier::layoutNotSet ||
628                localSizeSpecId[2] != TQualifier::layoutNotSet;
629     }
630 #ifdef GLSLANG_WEB
631     void output(TInfoSink&, bool tree) { }
632
633     bool isEsProfile() const { return false; }
634     bool getXfbMode() const { return false; }
635     bool isMultiStream() const { return false; }
636     TLayoutGeometry getOutputPrimitive() const { return ElgNone; }
637     bool getPostDepthCoverage() const { return false; }
638     bool getEarlyFragmentTests() const { return false; }
639     TLayoutDepth getDepth() const { return EldNone; }
640     bool getPixelCenterInteger() const { return false; }
641     void setOriginUpperLeft() { }
642     bool getOriginUpperLeft() const { return true; }
643     TInterlockOrdering getInterlockOrdering() const { return EioNone; }
644
645     bool getAutoMapBindings() const { return false; }
646     bool getAutoMapLocations() const { return false; }
647     int getNumPushConstants() const { return 0; }
648     void addShaderRecordCount() { }
649     void addTaskNVCount() { }
650     void addTaskPayloadEXTCount() { }
651     void setUseVulkanMemoryModel() { }
652     bool usingVulkanMemoryModel() const { return false; }
653     bool usingPhysicalStorageBuffer() const { return false; }
654     bool usingVariablePointers() const { return false; }
655     unsigned getXfbStride(int buffer) const { return 0; }
656     bool hasLayoutDerivativeModeNone() const { return false; }
657     ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; }
658 #else
659     void output(TInfoSink&, bool tree);
660
661     bool isEsProfile() const { return profile == EEsProfile; }
662
663     void setShiftBinding(TResourceType res, unsigned int shift)
664     {
665         shiftBinding[res] = shift;
666
667         const char* name = getResourceName(res);
668         if (name != nullptr)
669             processes.addIfNonZero(name, shift);
670     }
671
672     unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; }
673
674     void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set)
675     {
676         if (shift == 0) // ignore if there's no shift: it's a no-op.
677             return;
678
679         shiftBindingForSet[res][set] = shift;
680
681         const char* name = getResourceName(res);
682         if (name != nullptr) {
683             processes.addProcess(name);
684             processes.addArgument(shift);
685             processes.addArgument(set);
686         }
687     }
688
689     int getShiftBindingForSet(TResourceType res, unsigned int set) const
690     {
691         const auto shift = shiftBindingForSet[res].find(set);
692         return shift == shiftBindingForSet[res].end() ? -1 : shift->second;
693     }
694     bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); }
695
696     void setResourceSetBinding(const std::vector<std::string>& shift)
697     {
698         resourceSetBinding = shift;
699         if (shift.size() > 0) {
700             processes.addProcess("resource-set-binding");
701             for (int s = 0; s < (int)shift.size(); ++s)
702                 processes.addArgument(shift[s]);
703         }
704     }
705     const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
706     void setAutoMapBindings(bool map)
707     {
708         autoMapBindings = map;
709         if (autoMapBindings)
710             processes.addProcess("auto-map-bindings");
711     }
712     bool getAutoMapBindings() const { return autoMapBindings; }
713     void setAutoMapLocations(bool map)
714     {
715         autoMapLocations = map;
716         if (autoMapLocations)
717             processes.addProcess("auto-map-locations");
718     }
719     bool getAutoMapLocations() const { return autoMapLocations; }
720
721 #ifdef ENABLE_HLSL
722     void setFlattenUniformArrays(bool flatten)
723     {
724         flattenUniformArrays = flatten;
725         if (flattenUniformArrays)
726             processes.addProcess("flatten-uniform-arrays");
727     }
728     bool getFlattenUniformArrays() const { return flattenUniformArrays; }
729 #endif
730     void setNoStorageFormat(bool b)
731     {
732         useUnknownFormat = b;
733         if (useUnknownFormat)
734             processes.addProcess("no-storage-format");
735     }
736     bool getNoStorageFormat() const { return useUnknownFormat; }
737     void setUseVulkanMemoryModel()
738     {
739         useVulkanMemoryModel = true;
740         processes.addProcess("use-vulkan-memory-model");
741     }
742     bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; }
743     void setUsePhysicalStorageBuffer()
744     {
745         usePhysicalStorageBuffer = true;
746     }
747     bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; }
748     void setUseVariablePointers()
749     {
750         useVariablePointers = true;
751         processes.addProcess("use-variable-pointers");
752     }
753     bool usingVariablePointers() const { return useVariablePointers; }
754
755 #ifdef ENABLE_HLSL
756     template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
757     bool hasCounterBufferName(const TString& name) const {
758         size_t len = strlen(implicitCounterName);
759         return name.size() > len &&
760                name.compare(name.size() - len, len, implicitCounterName) == 0;
761     }
762 #endif
763
764     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
765     int getNumPushConstants() const { return numPushConstants; }
766     void addShaderRecordCount() { ++numShaderRecordBlocks; }
767     void addTaskNVCount() { ++numTaskNVBlocks; }
768     void addTaskPayloadEXTCount() { ++numTaskEXTPayloads; }
769
770     bool setInvocations(int i)
771     {
772         if (invocations != TQualifier::layoutNotSet)
773             return invocations == i;
774         invocations = i;
775         return true;
776     }
777     int getInvocations() const { return invocations; }
778     bool setVertices(int m)
779     {
780         if (vertices != TQualifier::layoutNotSet)
781             return vertices == m;
782         vertices = m;
783         return true;
784     }
785     int getVertices() const { return vertices; }
786     bool setInputPrimitive(TLayoutGeometry p)
787     {
788         if (inputPrimitive != ElgNone)
789             return inputPrimitive == p;
790         inputPrimitive = p;
791         return true;
792     }
793     TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
794     bool setVertexSpacing(TVertexSpacing s)
795     {
796         if (vertexSpacing != EvsNone)
797             return vertexSpacing == s;
798         vertexSpacing = s;
799         return true;
800     }
801     TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
802     bool setVertexOrder(TVertexOrder o)
803     {
804         if (vertexOrder != EvoNone)
805             return vertexOrder == o;
806         vertexOrder = o;
807         return true;
808     }
809     TVertexOrder getVertexOrder() const { return vertexOrder; }
810     void setPointMode() { pointMode = true; }
811     bool getPointMode() const { return pointMode; }
812
813     bool setInterlockOrdering(TInterlockOrdering o)
814     {
815         if (interlockOrdering != EioNone)
816             return interlockOrdering == o;
817         interlockOrdering = o;
818         return true;
819     }
820     TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; }
821
822     void setXfbMode() { xfbMode = true; }
823     bool getXfbMode() const { return xfbMode; }
824     void setMultiStream() { multiStream = true; }
825     bool isMultiStream() const { return multiStream; }
826     bool setOutputPrimitive(TLayoutGeometry p)
827     {
828         if (outputPrimitive != ElgNone)
829             return outputPrimitive == p;
830         outputPrimitive = p;
831         return true;
832     }
833     TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
834     void setPostDepthCoverage() { postDepthCoverage = true; }
835     bool getPostDepthCoverage() const { return postDepthCoverage; }
836     void setEarlyFragmentTests() { earlyFragmentTests = true; }
837     void setEarlyAndLateFragmentTestsAMD() { earlyAndLateFragmentTestsAMD = true; }
838     bool getEarlyFragmentTests() const { return earlyFragmentTests; }
839     bool getEarlyAndLateFragmentTestsAMD() const { return earlyAndLateFragmentTestsAMD; }
840     bool setDepth(TLayoutDepth d)
841     {
842         if (depthLayout != EldNone)
843             return depthLayout == d;
844         depthLayout = d;
845         return true;
846     }
847     bool setStencil(TLayoutStencil s)
848     {
849         if (stencilLayout != ElsNone)
850             return stencilLayout == s;
851         stencilLayout = s;
852         return true;
853     }
854     TLayoutDepth getDepth() const { return depthLayout; }
855     TLayoutStencil getStencil() const { return stencilLayout; }
856     void setOriginUpperLeft() { originUpperLeft = true; }
857     bool getOriginUpperLeft() const { return originUpperLeft; }
858     void setPixelCenterInteger() { pixelCenterInteger = true; }
859     bool getPixelCenterInteger() const { return pixelCenterInteger; }
860     void setTexCoordRedeclared() { texCoordBuiltinRedeclared = true; }
861     bool getTexCoordRedeclared() const { return texCoordBuiltinRedeclared; }
862     void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); }
863     unsigned int getBlendEquations() const { return blendEquations; }
864     bool setXfbBufferStride(int buffer, unsigned stride)
865     {
866         if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
867             return xfbBuffers[buffer].stride == stride;
868         xfbBuffers[buffer].stride = stride;
869         return true;
870     }
871     unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; }
872     int addXfbBufferOffset(const TType&);
873     unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const;
874     unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const;
875     void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; }
876     bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
877     void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
878     bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
879     void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
880     bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; }
881     ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
882     void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; }
883     bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; }
884     bool setPrimitives(int m)
885     {
886         if (primitives != TQualifier::layoutNotSet)
887             return primitives == m;
888         primitives = m;
889         return true;
890     }
891     int getPrimitives() const { return primitives; }
892     const char* addSemanticName(const TString& name)
893     {
894         return semanticNameSet.insert(name).first->c_str();
895     }
896     void addUniformLocationOverride(const char* nameStr, int location)
897     {
898         std::string name = nameStr;
899         uniformLocationOverrides[name] = location;
900     }
901
902     int getUniformLocationOverride(const char* nameStr) const
903     {
904         std::string name = nameStr;
905         auto pos = uniformLocationOverrides.find(name);
906         if (pos == uniformLocationOverrides.end())
907             return -1;
908         else
909             return pos->second;
910     }
911
912     void setUniformLocationBase(int base) { uniformLocationBase = base; }
913     int getUniformLocationBase() const { return uniformLocationBase; }
914
915     void setNeedsLegalization() { needToLegalize = true; }
916     bool needsLegalization() const { return needToLegalize; }
917
918     void setBinaryDoubleOutput() { binaryDoubleOutput = true; }
919     bool getBinaryDoubleOutput() { return binaryDoubleOutput; }
920
921     void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; }
922     bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; }
923
924     // GL_EXT_spirv_intrinsics
925     void insertSpirvRequirement(const TSpirvRequirement* spirvReq);
926     bool hasSpirvRequirement() const { return spirvRequirement != nullptr; }
927     const TSpirvRequirement& getSpirvRequirement() const { return *spirvRequirement; }
928     void insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args = nullptr);
929     void insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args);
930     bool hasSpirvExecutionMode() const { return spirvExecutionMode != nullptr; }
931     const TSpirvExecutionMode& getSpirvExecutionMode() const { return *spirvExecutionMode; }
932 #endif // GLSLANG_WEB
933
934     void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing)
935     {
936         std::string name(nameStr);
937         blockBackingOverrides[name] = backing;
938     }
939     TBlockStorageClass getBlockStorageOverride(const char* nameStr) const
940     {
941         std::string name = nameStr;
942         auto pos = blockBackingOverrides.find(name);
943         if (pos == blockBackingOverrides.end())
944             return EbsNone;
945         else
946             return pos->second;
947     }
948 #ifdef ENABLE_HLSL
949     void setHlslFunctionality1() { hlslFunctionality1 = true; }
950     bool getHlslFunctionality1() const { return hlslFunctionality1; }
951     void setHlslOffsets()
952     {
953         hlslOffsets = true;
954         if (hlslOffsets)
955             processes.addProcess("hlsl-offsets");
956     }
957     bool usingHlslOffsets() const { return hlslOffsets; }
958     void setHlslIoMapping(bool b)
959     {
960         hlslIoMapping = b;
961         if (hlslIoMapping)
962             processes.addProcess("hlsl-iomap");
963     }
964     bool usingHlslIoMapping() { return hlslIoMapping; }
965 #else
966     bool getHlslFunctionality1() const { return false; }
967     bool usingHlslOffsets() const { return false; }
968     bool usingHlslIoMapping() { return false; }
969 #endif
970
971     bool usingScalarBlockLayout() const {
972         for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) {
973             if (*extIt == E_GL_EXT_scalar_block_layout)
974                 return true;
975         }
976         return false;
977     }
978
979     bool IsRequestedExtension(const char* extension) const
980     {
981         return (requestedExtensions.find(extension) != requestedExtensions.end());
982     }
983
984     void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
985     void merge(TInfoSink&, TIntermediate&);
986     void finalCheck(TInfoSink&, bool keepUncalled);
987
988     void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
989     void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
990     void checkStageIO(TInfoSink&, TIntermediate&);
991
992     bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const;
993     TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
994
995     void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
996     bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
997
998     int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
999     int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision);
1000     int checkLocationRT(int set, int location);
1001     int addUsedOffsets(int binding, int offset, int numOffsets);
1002     bool addUsedConstantId(int id);
1003     static int computeTypeLocationSize(const TType&, EShLanguage);
1004     static int computeTypeUniformLocationSize(const TType&);
1005
1006     static int getBaseAlignmentScalar(const TType&, int& size);
1007     static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
1008     static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
1009     static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
1010     static bool improperStraddle(const TType& type, int size, int offset);
1011     static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize);
1012     static int getOffset(const TType& type, int index);
1013     static int getBlockSize(const TType& blockType);
1014     static int computeBufferReferenceTypeSize(const TType&);
1015     static bool isIoResizeArray(const TType& type, EShLanguage language);
1016
1017     bool promote(TIntermOperator*);
1018     void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; }
1019     bool getNanMinMaxClamp() const { return nanMinMaxClamp; }
1020
1021     void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; }
1022     const std::string& getSourceFile() const { return sourceFile; }
1023     void addSourceText(const char* text, size_t len) { sourceText.append(text, len); }
1024     const std::string& getSourceText() const { return sourceText; }
1025     const std::map<std::string, std::string>& getIncludeText() const { return includeText; }
1026     void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); }
1027     void addProcesses(const std::vector<std::string>& p)
1028     {
1029         for (int i = 0; i < (int)p.size(); ++i)
1030             processes.addProcess(p[i]);
1031     }
1032     void addProcess(const std::string& process) { processes.addProcess(process); }
1033     void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
1034     const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
1035     unsigned long long getUniqueId() const { return uniqueId; }
1036     void setUniqueId(unsigned long long id) { uniqueId = id; }
1037
1038     // Certain explicit conversions are allowed conditionally
1039 #ifdef GLSLANG_WEB
1040     bool getArithemeticInt8Enabled() const { return false; }
1041     bool getArithemeticInt16Enabled() const { return false; }
1042     bool getArithemeticFloat16Enabled() const { return false; }
1043     void updateNumericFeature(TNumericFeatures::feature f, bool on) { }
1044 #else
1045     bool getArithemeticInt8Enabled() const {
1046         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1047                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8);
1048     }
1049     bool getArithemeticInt16Enabled() const {
1050         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1051                numericFeatures.contains(TNumericFeatures::gpu_shader_int16) ||
1052                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16);
1053     }
1054
1055     bool getArithemeticFloat16Enabled() const {
1056         return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
1057                numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
1058                numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16);
1059     }
1060     void updateNumericFeature(TNumericFeatures::feature f, bool on)
1061         { on ? numericFeatures.insert(f) : numericFeatures.erase(f); }
1062 #endif
1063
1064 protected:
1065     TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
1066     void error(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
1067     void warn(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount);
1068     void mergeCallGraphs(TInfoSink&, TIntermediate&);
1069     void mergeModes(TInfoSink&, TIntermediate&);
1070     void mergeTrees(TInfoSink&, TIntermediate&);
1071     void seedIdMap(TIdMaps& idMaps, long long& IdShift);
1072     void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&);
1073     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
1074     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage);
1075     void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot);
1076     void mergeImplicitArraySizes(TType&, const TType&);
1077     void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage);
1078     void checkCallGraphCycles(TInfoSink&);
1079     void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
1080     void inOutLocationCheck(TInfoSink&);
1081     void sharedBlockCheck(TInfoSink&);
1082     bool userOutputUsed() const;
1083     bool isSpecializationOperation(const TIntermOperator&) const;
1084     bool isNonuniformPropagating(TOperator) const;
1085     bool promoteUnary(TIntermUnary&);
1086     bool promoteBinary(TIntermBinary&);
1087     void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
1088     bool promoteAggregate(TIntermAggregate&);
1089     void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
1090     void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
1091     bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
1092     void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
1093     bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
1094     std::tuple<TBasicType, TBasicType> getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const;
1095
1096     static const char* getResourceName(TResourceType);
1097
1098     const EShLanguage language;  // stage, known at construction time
1099     std::string entryPointName;
1100     std::string entryPointMangledName;
1101     typedef std::list<TCall> TGraph;
1102     TGraph callGraph;
1103
1104 #ifdef GLSLANG_ANGLE
1105     const EProfile profile = ECoreProfile;
1106     const int version = 450;
1107 #else
1108     EProfile profile;                           // source profile
1109     int version;                                // source version
1110 #endif
1111     SpvVersion spvVersion;
1112     TIntermNode* treeRoot;
1113     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
1114     MustBeAssigned<TBuiltInResource> resources;
1115     int numEntryPoints;
1116     int numErrors;
1117     int numPushConstants;
1118     bool recursive;
1119     bool invertY;
1120     bool dxPositionW;
1121     bool enhancedMsgs;
1122     bool debugInfo;
1123     bool useStorageBuffer;
1124     bool invariantAll;
1125     bool nanMinMaxClamp;            // true if desiring min/max/clamp to favor non-NaN over NaN
1126     bool depthReplacing;
1127     bool stencilReplacing;
1128     int localSize[3];
1129     bool localSizeNotDefault[3];
1130     int localSizeSpecId[3];
1131     unsigned long long uniqueId;
1132
1133     std::string globalUniformBlockName;
1134     std::string atomicCounterBlockName;
1135     unsigned int globalUniformBlockSet;
1136     unsigned int globalUniformBlockBinding;
1137     unsigned int atomicCounterBlockSet;
1138
1139 #ifndef GLSLANG_WEB
1140 public:
1141     const char* const implicitThisName;
1142     const char* const implicitCounterName;
1143 protected:
1144     EShSource source;            // source language, known a bit later
1145     bool useVulkanMemoryModel;
1146     int invocations;
1147     int vertices;
1148     TLayoutGeometry inputPrimitive;
1149     TLayoutGeometry outputPrimitive;
1150     bool pixelCenterInteger;
1151     bool originUpperLeft;
1152     bool texCoordBuiltinRedeclared;
1153     TVertexSpacing vertexSpacing;
1154     TVertexOrder vertexOrder;
1155     TInterlockOrdering interlockOrdering;
1156     bool pointMode;
1157     bool earlyFragmentTests;
1158     bool postDepthCoverage;
1159     bool earlyAndLateFragmentTestsAMD;
1160     TLayoutDepth depthLayout;
1161     TLayoutStencil stencilLayout;
1162     bool hlslFunctionality1;
1163     int blendEquations;        // an 'or'ing of masks of shifts of TBlendEquationShift
1164     bool xfbMode;
1165     std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
1166     bool multiStream;
1167     bool layoutOverrideCoverage;
1168     bool geoPassthroughEXT;
1169     int numShaderRecordBlocks;
1170     ComputeDerivativeMode computeDerivativeMode;
1171     int primitives;
1172     int numTaskNVBlocks;
1173     bool layoutPrimitiveCulling;
1174     int numTaskEXTPayloads;
1175
1176     // Base shift values
1177     std::array<unsigned int, EResCount> shiftBinding;
1178
1179     // Per-descriptor-set shift values
1180     std::array<std::map<int, int>, EResCount> shiftBindingForSet;
1181
1182     std::vector<std::string> resourceSetBinding;
1183     bool autoMapBindings;
1184     bool autoMapLocations;
1185     bool flattenUniformArrays;
1186     bool useUnknownFormat;
1187     bool hlslOffsets;
1188     bool hlslIoMapping;
1189     bool useVariablePointers;
1190
1191     std::set<TString> semanticNameSet;
1192
1193     EShTextureSamplerTransformMode textureSamplerTransformMode;
1194
1195     bool needToLegalize;
1196     bool binaryDoubleOutput;
1197     bool subgroupUniformControlFlow;
1198     bool usePhysicalStorageBuffer;
1199
1200     TSpirvRequirement* spirvRequirement;
1201     TSpirvExecutionMode* spirvExecutionMode;
1202
1203     std::unordered_map<std::string, int> uniformLocationOverrides;
1204     int uniformLocationBase;
1205     TNumericFeatures numericFeatures;
1206 #endif
1207     std::unordered_map<std::string, TBlockStorageClass> blockBackingOverrides;
1208
1209     std::unordered_set<int> usedConstantId; // specialization constant ids used
1210     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
1211     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
1212     std::vector<TRange> usedIoRT[2];        // sets of used location, one for rayPayload/rayPayloadIN and other
1213                                             // for callableData/callableDataIn
1214     // set of names of statically read/written I/O that might need extra checking
1215     std::set<TString> ioAccessed;
1216
1217     // source code of shader, useful as part of debug information
1218     std::string sourceFile;
1219     std::string sourceText;
1220
1221     // Included text. First string is a name, second is the included text
1222     std::map<std::string, std::string> includeText;
1223
1224     // for OpModuleProcessed, or equivalent
1225     TProcesses processes;
1226
1227 private:
1228     void operator=(TIntermediate&); // prevent assignments
1229 };
1230
1231 } // end namespace glslang
1232
1233 #endif // _LOCAL_INTERMEDIATE_INCLUDED_