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