1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//
16// Symbol table for parsing. Most functionaliy and main ideas
17// are documented in the header file.
18//
19
20#if defined(_MSC_VER)
21#pragma warning(disable: 4718)
22#endif
23
24#include "SymbolTable.h"
25
26#include <stdio.h>
27#include <limits.h>
28#include <algorithm>
29
30#if defined(_MSC_VER) && MSC_VER < 1900
31#define snprintf _snprintf
32#endif
33
34int TSymbolTableLevel::uniqueId = 0;
35
36TType::TType(const TPublicType &p) :
37 type(p.type), precision(p.precision), qualifier(p.qualifier),
38 primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), maxArraySize(0),
39 arrayInformationType(0), interfaceBlock(0), layoutQualifier(p.layoutQualifier), structure(0), mangled(0)
40{
41 if (p.userDef)
42 {
43 structure = p.userDef->getStruct();
44 }
45}
46
47//
48// Recursively generate mangled names.
49//
50void TType::buildMangledName(TString& mangledName)
51{
52 if (isMatrix())
53 mangledName += 'm';
54 else if (isVector())
55 mangledName += 'v';
56
57 switch (type) {
58 case EbtFloat: mangledName += 'f'; break;
59 case EbtInt: mangledName += 'i'; break;
60 case EbtUInt: mangledName += 'u'; break;
61 case EbtBool: mangledName += 'b'; break;
62 case EbtSampler2D: mangledName += "s2"; break;
63 case EbtSampler3D: mangledName += "s3"; break;
64 case EbtSamplerCube: mangledName += "sC"; break;
65 case EbtSampler2DArray: mangledName += "s2a"; break;
66 case EbtSampler2DRect: mangledName += "s2r"; break;
67 case EbtSamplerExternalOES: mangledName += "sext"; break;
68 case EbtISampler2D: mangledName += "is2"; break;
69 case EbtISampler3D: mangledName += "is3"; break;
70 case EbtISamplerCube: mangledName += "isC"; break;
71 case EbtISampler2DArray: mangledName += "is2a"; break;
72 case EbtUSampler2D: mangledName += "us2"; break;
73 case EbtUSampler3D: mangledName += "us3"; break;
74 case EbtUSamplerCube: mangledName += "usC"; break;
75 case EbtUSampler2DArray: mangledName += "us2a"; break;
76 case EbtSampler2DShadow: mangledName += "s2s"; break;
77 case EbtSamplerCubeShadow: mangledName += "sCs"; break;
78 case EbtSampler2DArrayShadow: mangledName += "s2as"; break;
79 case EbtStruct: mangledName += structure->mangledName(); break;
80 case EbtInterfaceBlock: mangledName += interfaceBlock->mangledName(); break;
81 default:
82 break;
83 }
84
85 mangledName += static_cast<char>('0' + getNominalSize());
86 if(isMatrix()) {
87 mangledName += static_cast<char>('0' + getSecondarySize());
88 }
89 if (isArray()) {
90 char buf[20];
91 snprintf(buf, sizeof(buf), "%d", arraySize);
92 mangledName += '[';
93 mangledName += buf;
94 mangledName += ']';
95 }
96}
97
98size_t TType::getStructSize() const
99{
100 if (!getStruct()) {
101 assert(false && "Not a struct");
102 return 0;
103 }
104
105 return getStruct()->objectSize();
106}
107
108bool TStructure::containsArrays() const
109{
110 for(const auto& field : *mFields)
111 {
112 const TType *fieldType = field->type();
113 if(fieldType->isArray() || fieldType->isStructureContainingArrays())
114 return true;
115 }
116 return false;
117}
118
119bool TStructure::containsType(TBasicType type) const
120{
121 for(const auto& field : *mFields)
122 {
123 const TType *fieldType = field->type();
124 if(fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
125 return true;
126 }
127 return false;
128}
129
130bool TStructure::containsSamplers() const
131{
132 for(const auto& field : *mFields)
133 {
134 const TType *fieldType = field->type();
135 if(IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
136 return true;
137 }
138 return false;
139}
140
141void TStructure::setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking)
142{
143 for(auto& field : *mFields)
144 {
145 field->type()->setMatrixPackingIfUnspecified(matrixPacking);
146 }
147}
148
149TString TFieldListCollection::buildMangledName() const
150{
151 TString mangledName(mangledNamePrefix());
152 mangledName += *mName;
153 for(const auto& field : *mFields)
154 {
155 mangledName += '-';
156 mangledName += field->type()->getMangledName();
157 }
158 return mangledName;
159}
160
161size_t TFieldListCollection::calculateObjectSize() const
162{
163 size_t size = 0;
164 for(const auto& field : *mFields)
165 {
166 size_t fieldSize = field->type()->getObjectSize();
167 if(fieldSize > INT_MAX - size)
168 size = INT_MAX;
169 else
170 size += fieldSize;
171 }
172 return size;
173}
174
175int TStructure::calculateDeepestNesting() const
176{
177 int maxNesting = 0;
178 for(const auto& field : *mFields)
179 maxNesting = std::max(maxNesting, field->type()->getDeepestStructNesting());
180 return 1 + maxNesting;
181}
182
183//
184// Functions have buried pointers to delete.
185//
186TFunction::~TFunction()
187{
188 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
189 delete (*i).type;
190}
191
192//
193// Symbol table levels are a map of pointers to symbols that have to be deleted.
194//
195TSymbolTableLevel::~TSymbolTableLevel()
196{
197 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
198 delete (*it).second;
199}
200
201bool TSymbolTableLevel::insert(TSymbol *symbol)
202{
203 symbol->setUniqueId(nextUniqueId());
204
205 // returning true means symbol was added to the table
206 tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
207
208 return result.second;
209}
210
211bool TSymbolTableLevel::insertUnmangled(TFunction *function)
212{
213 function->setUniqueId(nextUniqueId());
214
215 // returning true means symbol was added to the table
216 tInsertResult result = level.insert(tLevelPair(function->getName(), function));
217
218 return result.second;
219}
220
221TSymbol *TSymbolTableLevel::find(const TString &name) const
222{
223 tLevel::const_iterator it = level.find(name);
224 if (it == level.end())
225 return 0;
226 else
227 return (*it).second;
228}
229
230TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) const
231{
232 int level = currentLevel();
233 TSymbol *symbol = nullptr;
234
235 do
236 {
237 while((level == ESSL3_BUILTINS && shaderVersion != 300) ||
238 (level == ESSL1_BUILTINS && shaderVersion != 100)) // Skip version specific levels
239 {
240 --level;
241 }
242
243 symbol = table[level]->find(name);
244 }
245 while(!symbol && --level >= 0); // Doesn't decrement level when a symbol was found
246
247 if(builtIn)
248 {
249 *builtIn = (level <= LAST_BUILTIN_LEVEL);
250 }
251
252 if(sameScope)
253 {
254 *sameScope = (level == currentLevel());
255 }
256
257 return symbol;
258}
259
260TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
261{
262 for(int level = LAST_BUILTIN_LEVEL; level >= 0; --level)
263 {
264 while((level == ESSL3_BUILTINS && shaderVersion != 300) ||
265 (level == ESSL1_BUILTINS && shaderVersion != 100)) // Skip version specific levels
266 {
267 --level;
268 }
269
270 TSymbol *symbol = table[level]->find(name);
271
272 if(symbol)
273 {
274 return symbol;
275 }
276 }
277
278 return 0;
279}
280
281TSymbol::TSymbol(const TSymbol& copyOf)
282{
283 name = NewPoolTString(copyOf.name->c_str());
284}
285