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 | |
34 | int TSymbolTableLevel::uniqueId = 0; |
35 | |
36 | TType::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 | // |
50 | void 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 | |
98 | size_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 | |
108 | bool 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 | |
119 | bool 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 | |
130 | bool 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 | |
141 | void TStructure::setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking) |
142 | { |
143 | for(auto& field : *mFields) |
144 | { |
145 | field->type()->setMatrixPackingIfUnspecified(matrixPacking); |
146 | } |
147 | } |
148 | |
149 | TString 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 | |
161 | size_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 | |
175 | int 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 | // |
186 | TFunction::~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 | // |
195 | TSymbolTableLevel::~TSymbolTableLevel() |
196 | { |
197 | for (tLevel::iterator it = level.begin(); it != level.end(); ++it) |
198 | delete (*it).second; |
199 | } |
200 | |
201 | bool 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 | |
211 | bool 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 | |
221 | TSymbol *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 | |
230 | TSymbol *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 | |
260 | TSymbol *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 | |
281 | TSymbol::TSymbol(const TSymbol& copyOf) |
282 | { |
283 | name = NewPoolTString(copyOf.name->c_str()); |
284 | } |
285 | |