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