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