glslang: Fix over 100 warnings from MSVC warning level 4.
[platform/upstream/glslang.git] / glslang / MachineIndependent / localintermediate.h
1 //
2 //Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 //All rights reserved.
4 //
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
7 //are met:
8 //
9 //    Redistributions of source code must retain the above copyright
10 //    notice, this list of conditions and the following disclaimer.
11 //
12 //    Redistributions in binary form must reproduce the above
13 //    copyright notice, this list of conditions and the following
14 //    disclaimer in the documentation and/or other materials provided
15 //    with the distribution.
16 //
17 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
18 //    contributors may be used to endorse or promote products derived
19 //    from this software without specific prior written permission.
20 //
21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //POSSIBILITY OF SUCH DAMAGE.
33 //
34
35 #ifndef _LOCAL_INTERMEDIATE_INCLUDED_
36 #define _LOCAL_INTERMEDIATE_INCLUDED_
37
38 #include "../Include/intermediate.h"
39 #include "../Public/ShaderLang.h"
40 #include "Versions.h"
41
42 #include <algorithm>
43 #include <set>
44
45 class TInfoSink;
46
47 namespace glslang {
48
49 struct TVectorFields {
50     int offsets[4];
51     int num;
52 };
53
54 //
55 // Some helper structures for TIntermediate.  Their contents are encapsulated
56 // by TIntermediate.
57 //
58
59 // Used for detecting recursion:  A "call" is a pair: <caller, callee>.
60 struct TCall {
61     TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { }
62     TString caller;
63     TString callee;
64     bool visited;
65     bool currentPath;
66     bool errorGiven;
67 };
68
69 // A generic 1-D range.
70 struct TRange {
71     TRange(int start, int last) : start(start), last(last) { }
72     bool overlap(const TRange& rhs) const 
73     {
74         return last >= rhs.start && start <= rhs.last;
75     }
76     int start;
77     int last;
78 };
79
80 // An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying
81 // within the same location range, component range, and index value.  Locations don't alias unless
82 // all other dimensions of their range overlap.
83 struct TIoRange {
84     TIoRange(TRange location, TRange component, TBasicType basicType, int index)
85         : location(location), component(component), basicType(basicType), index(index) { }
86     bool overlap(const TIoRange& rhs) const
87     {
88         return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index;
89     }
90     TRange location;
91     TRange component;
92     TBasicType basicType;
93     int index;
94 };
95
96 // An IO range is a 2-D rectangle; the set of (binding, offset) pairs all lying
97 // within the same binding and offset range.
98 struct TOffsetRange {
99     TOffsetRange(TRange binding, TRange offset)
100         : binding(binding), offset(offset) { }
101     bool overlap(const TOffsetRange& rhs) const
102     {
103         return binding.overlap(rhs.binding) && offset.overlap(rhs.offset);
104     }
105     TRange binding;
106     TRange offset;
107 };
108
109 // Things that need to be tracked per xfb buffer.
110 struct TXfbBuffer {
111     TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), containsDouble(false) { }
112     std::vector<TRange> ranges;  // byte offsets that have already been assigned
113     unsigned int stride;
114     unsigned int implicitStride;
115     bool containsDouble;
116 };
117
118 class TSymbolTable;
119 class TSymbol;
120 class TVariable;
121
122 //
123 // Set of helper functions to help parse and build the tree.
124 //
125 class TIntermediate {
126 public:
127     explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), 
128         numMains(0), numErrors(0), recursive(false),
129         invocations(0), vertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false),
130         vertexSpacing(EvsNone), vertexOrder(EvoNone), pointMode(false), earlyFragmentTests(false), depthLayout(EldNone), xfbMode(false)
131     {
132         localSize[0] = 1;
133         localSize[1] = 1;
134         localSize[2] = 1;
135         xfbBuffers.resize(TQualifier::layoutXfbBufferEnd);
136     }
137     void setLimits(const TBuiltInResource& r) { resources = r; }
138
139     bool postProcess(TIntermNode*, EShLanguage);
140     void output(TInfoSink&, bool tree);
141         void removeTree();
142
143     void setVersion(int v) { version = v; }
144     int getVersion() const { return version; }
145     void setProfile(EProfile p) { profile = p; }
146     EProfile getProfile() const { return profile; }
147     EShLanguage getStage() const { return language; }
148     void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); }
149     const std::set<std::string>& getRequestedExtensions() const { return requestedExtensions; }
150
151     void setTreeRoot(TIntermNode* r) { treeRoot = r; }
152     TIntermNode* getTreeRoot() const { return treeRoot; }
153     void addMainCount() { ++numMains; }
154     int getNumMains() const { return numMains; }
155     int getNumErrors() const { return numErrors; }
156     bool isRecursive() const { return recursive; }
157     
158     TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
159     TIntermSymbol* addSymbol(const TVariable&, TSourceLoc);
160     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
161     TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
162     TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
163     TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
164     TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
165     TIntermTyped* addBuiltInFunctionCall(TSourceLoc line, TOperator, bool unary, TIntermNode*, const TType& returnType);
166     bool canImplicitlyPromote(TBasicType from, TBasicType to) const;
167     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
168     TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
169     TIntermAggregate* makeAggregate(TIntermNode* node);
170     TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
171     TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc);
172     bool areAllChildConst(TIntermAggregate* aggrNode);
173     TIntermNode*  addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc);
174     TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
175     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
176     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc);
177     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc, bool literal = false) const;
178     TIntermConstantUnion* addConstantUnion(int, TSourceLoc, bool literal = false) const;
179     TIntermConstantUnion* addConstantUnion(unsigned int, TSourceLoc, bool literal = false) const;
180     TIntermConstantUnion* addConstantUnion(bool, TSourceLoc, bool literal = false) const;
181     TIntermConstantUnion* addConstantUnion(double, TBasicType, TSourceLoc, bool literal = false) const;
182     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
183     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
184     TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
185     TIntermBranch* addBranch(TOperator, TSourceLoc);
186     TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
187     TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
188
189     // Constant folding (in Constant.cpp)
190     TIntermTyped* fold(TIntermAggregate* aggrNode);
191     TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
192     TIntermTyped* foldDereference(TIntermTyped* node, int index, TSourceLoc);
193     TIntermTyped* foldSwizzle(TIntermTyped* node, TVectorFields& fields, TSourceLoc);
194
195     // Linkage related
196     void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&);
197     void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&);
198     void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&);
199
200     bool setInvocations(int i) 
201     {
202         if (invocations > 0)
203             return invocations == i;
204         invocations = i;
205         return true;
206     }
207     int getInvocations() const { return invocations; }
208     bool setVertices(int m)
209     {
210         if (vertices > 0)
211             return vertices == m;
212         vertices = m;
213         return true;
214     }
215     int getVertices() const { return vertices; }
216     bool setInputPrimitive(TLayoutGeometry p)
217     {
218         if (inputPrimitive != ElgNone)
219             return inputPrimitive == p;
220         inputPrimitive = p;
221         return true;
222     }
223     TLayoutGeometry getInputPrimitive() const { return inputPrimitive; }
224     bool setVertexSpacing(TVertexSpacing s)
225     {
226         if (vertexSpacing != EvsNone)
227             return vertexSpacing == s;
228         vertexSpacing = s;
229         return true;
230     }
231     TVertexSpacing getVertexSpacing() const { return vertexSpacing; }
232     bool setVertexOrder(TVertexOrder o)
233     {
234         if (vertexOrder != EvoNone)
235             return vertexOrder == o;
236         vertexOrder = o;
237         return true;
238     }
239     TVertexOrder getVertexOrder() const { return vertexOrder; }
240     void setPointMode() { pointMode = true; }
241     bool getPointMode() const { return pointMode; }
242     
243     bool setLocalSize(int dim, int size)
244     {
245         if (localSize[dim] > 1)
246             return size == localSize[dim];
247         localSize[dim] = size;
248         return true;
249     }
250     unsigned int getLocalSize(int dim) const { return localSize[dim]; }
251
252     void setXfbMode() { xfbMode = true; }
253     bool getXfbMode() const { return xfbMode; }
254     bool setOutputPrimitive(TLayoutGeometry p)
255     {
256         if (outputPrimitive != ElgNone)
257             return outputPrimitive == p;
258         outputPrimitive = p;
259         return true;
260     }
261     TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; }
262     void setOriginUpperLeft() { originUpperLeft = true; }
263     bool getOriginUpperLeft() const { return originUpperLeft; }
264     void setPixelCenterInteger() { pixelCenterInteger = true; }
265     bool getPixelCenterInteger() const { return pixelCenterInteger; }
266     void setEarlyFragmentTests() { earlyFragmentTests = true; }
267     bool getEarlyFragmentTests() const { return earlyFragmentTests; }
268     bool setDepth(TLayoutDepth d)
269     {
270         if (depthLayout != EldNone)
271             return depthLayout == d;
272         depthLayout = d;
273         return true;
274     }
275     TLayoutDepth getDepth() const { return depthLayout; }
276
277     void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee);
278     void merge(TInfoSink&, TIntermediate&);
279     void finalCheck(TInfoSink&);
280
281     void addIoAccessed(const TString& name) { ioAccessed.insert(name); }
282     bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); }
283
284     int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision);
285     int addUsedOffsets(int binding, int offset, int numOffsets);
286     int computeTypeLocationSize(const TType&) const;
287
288     bool setXfbBufferStride(int buffer, unsigned stride)
289     {
290         if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd)
291             return xfbBuffers[buffer].stride == stride;
292         xfbBuffers[buffer].stride = stride;
293         return true;
294     }
295     int addXfbBufferOffset(const TType&);
296     unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
297     static int getBaseAlignment(const TType&, int& size, bool std140);
298
299 protected:
300     void error(TInfoSink& infoSink, const char*);
301     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
302     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
303     void mergeImplicitArraySizes(TType&, const TType&);
304     void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage);
305     void checkCallGraphCycles(TInfoSink&);
306     void inOutLocationCheck(TInfoSink&);
307     TIntermSequence& findLinkerObjects() const;
308     bool userOutputUsed() const;
309     static int getBaseAlignmentScalar(const TType&, int& size);
310
311     const EShLanguage language;
312     TIntermNode* treeRoot;
313     EProfile profile;
314     int version;
315     std::set<std::string> requestedExtensions;  // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
316     TBuiltInResource resources;
317     int numMains;
318     int numErrors;
319     bool recursive;
320     int invocations;
321     int vertices;
322     TLayoutGeometry inputPrimitive;
323     TLayoutGeometry outputPrimitive;
324     bool pixelCenterInteger;
325     bool originUpperLeft;
326     TVertexSpacing vertexSpacing;
327     TVertexOrder vertexOrder;
328     bool pointMode;
329     int localSize[3];
330     bool earlyFragmentTests;
331     TLayoutDepth depthLayout;
332     bool xfbMode;
333
334     typedef std::list<TCall> TGraph;
335     TGraph callGraph;
336
337     std::set<TString> ioAccessed;           // set of names of statically read/written I/O that might need extra checking
338     std::vector<TIoRange> usedIo[4];        // sets of used locations, one for each of in, out, uniform, and buffers
339     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
340     std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
341
342 private:
343     void operator=(TIntermediate&); // prevent assignments
344 };
345
346 } // end namespace glslang
347
348 #endif // _LOCAL_INTERMEDIATE_INCLUDED_