/src/glslang/glslang/MachineIndependent/SymbolTable.cpp
Line | Count | Source |
1 | | // |
2 | | // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. |
3 | | // Copyright (C) 2012-2013 LunarG, Inc. |
4 | | // Copyright (C) 2017 ARM Limited. |
5 | | // Copyright (C) 2015-2018 Google, Inc. |
6 | | // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. |
7 | | // |
8 | | // All rights reserved. |
9 | | // |
10 | | // Redistribution and use in source and binary forms, with or without |
11 | | // modification, are permitted provided that the following conditions |
12 | | // are met: |
13 | | // |
14 | | // Redistributions of source code must retain the above copyright |
15 | | // notice, this list of conditions and the following disclaimer. |
16 | | // |
17 | | // Redistributions in binary form must reproduce the above |
18 | | // copyright notice, this list of conditions and the following |
19 | | // disclaimer in the documentation and/or other materials provided |
20 | | // with the distribution. |
21 | | // |
22 | | // Neither the name of 3Dlabs Inc. Ltd. nor the names of its |
23 | | // contributors may be used to endorse or promote products derived |
24 | | // from this software without specific prior written permission. |
25 | | // |
26 | | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
27 | | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
28 | | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
29 | | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
30 | | // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
31 | | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
32 | | // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
33 | | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
34 | | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
35 | | // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
36 | | // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
37 | | // POSSIBILITY OF SUCH DAMAGE. |
38 | | // |
39 | | |
40 | | // |
41 | | // Symbol table for parsing. Most functionality and main ideas |
42 | | // are documented in the header file. |
43 | | // |
44 | | |
45 | | #include "SymbolTable.h" |
46 | | |
47 | | namespace glslang { |
48 | | |
49 | | // |
50 | | // TType helper function needs a place to live. |
51 | | // |
52 | | |
53 | | // |
54 | | // Recursively generate mangled names. |
55 | | // |
56 | | void TType::buildMangledName(TString& mangledName) const |
57 | 2.00M | { |
58 | 2.00M | if (isTensorARM()) |
59 | 1.64k | mangledName += 'T'; |
60 | 2.00M | else if (isMatrix()) |
61 | 417k | mangledName += 'm'; |
62 | 1.58M | else if (isVector()) |
63 | 677k | mangledName += 'v'; |
64 | | |
65 | 2.00M | if (isCoopVecNV()) |
66 | 21.2k | mangledName += "coopvec"; |
67 | | |
68 | 2.00M | switch (basicType) { |
69 | 594k | case EbtFloat: mangledName += 'f'; break; |
70 | 483k | case EbtInt: mangledName += 'i'; break; |
71 | 316k | case EbtUint: mangledName += 'u'; break; |
72 | 28.2k | case EbtBool: mangledName += 'b'; break; |
73 | 48.4k | case EbtDouble: mangledName += 'd'; break; |
74 | 77.8k | case EbtFloat16: mangledName += "f16"; break; |
75 | 864 | case EbtBFloat16: mangledName += "bf16"; break; |
76 | 648 | case EbtFloatE5M2: mangledName += "fe5m2"; break; |
77 | 648 | case EbtFloatE4M3: mangledName += "fe4m3"; break; |
78 | 14.7k | case EbtInt8: mangledName += "i8"; break; |
79 | 14.2k | case EbtUint8: mangledName += "u8"; break; |
80 | 19.1k | case EbtInt16: mangledName += "i16"; break; |
81 | 17.9k | case EbtUint16: mangledName += "u16"; break; |
82 | 24.1k | case EbtInt64: mangledName += "i64"; break; |
83 | 36.1k | case EbtUint64: mangledName += "u64"; break; |
84 | 144 | case EbtAtomicUint: mangledName += "au"; break; |
85 | 0 | case EbtAccStruct: mangledName += "as"; break; |
86 | 0 | case EbtRayQuery: mangledName += "rq"; break; |
87 | 0 | case EbtSpirvType: mangledName += "spv-t"; break; |
88 | 0 | case EbtHitObjectNV: mangledName += "ho"; break; |
89 | 0 | case EbtHitObjectEXT: mangledName += "ho"; break; |
90 | 999 | case EbtTensorLayoutNV: mangledName += "tl"; break; |
91 | 513 | case EbtTensorViewNV: mangledName += "tv"; break; |
92 | 289k | case EbtSampler: |
93 | 289k | switch (sampler.type) { |
94 | 44.2k | case EbtFloat16: mangledName += "f16"; break; |
95 | 51.1k | case EbtInt: mangledName += "i"; break; |
96 | 51.1k | case EbtUint: mangledName += "u"; break; |
97 | 7.02k | case EbtInt64: mangledName += "i64"; break; |
98 | 7.02k | case EbtUint64: mangledName += "u64"; break; |
99 | 128k | default: break; // some compilers want this |
100 | 289k | } |
101 | 289k | if (sampler.isImageClass()) |
102 | 50.7k | mangledName += "I"; // a normal image or subpass |
103 | 238k | else if (sampler.isPureSampler()) |
104 | 68.6k | mangledName += "p"; // a "pure" sampler |
105 | 169k | else if (!sampler.isCombined()) |
106 | 83.9k | mangledName += "t"; // a "pure" texture |
107 | 85.7k | else |
108 | 85.7k | mangledName += "s"; // traditional combined sampler |
109 | 289k | if (sampler.isArrayed()) |
110 | 84.3k | mangledName += "A"; |
111 | 289k | if (sampler.isShadow()) |
112 | 43.5k | mangledName += "S"; |
113 | 289k | if (sampler.isExternal()) |
114 | 106 | mangledName += "E"; |
115 | 289k | if (sampler.isYuv()) |
116 | 256 | mangledName += "Y"; |
117 | 289k | switch (sampler.dim) { |
118 | 104k | case Esd2D: mangledName += "2"; break; |
119 | 19.3k | case Esd3D: mangledName += "3"; break; |
120 | 36.8k | case EsdCube: mangledName += "C"; break; |
121 | 38.4k | case Esd1D: mangledName += "1"; break; |
122 | 13.3k | case EsdRect: mangledName += "R2"; break; |
123 | 5.10k | case EsdBuffer: mangledName += "B"; break; |
124 | 2.64k | case EsdSubpass: mangledName += "P"; break; |
125 | 68.6k | default: break; // some compilers want this |
126 | 289k | } |
127 | | |
128 | 289k | #ifdef ENABLE_HLSL |
129 | 289k | if (sampler.hasReturnStruct()) { |
130 | | // Name mangle for sampler return struct uses struct table index. |
131 | 0 | mangledName += "-tx-struct"; |
132 | |
|
133 | 0 | char text[16]; // plenty enough space for the small integers. |
134 | 0 | snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex()); |
135 | 0 | mangledName += text; |
136 | 289k | } else { |
137 | 289k | switch (sampler.getVectorSize()) { |
138 | 17.1k | case 1: mangledName += "1"; break; |
139 | 50.1k | case 2: mangledName += "2"; break; |
140 | 6.93k | case 3: mangledName += "3"; break; |
141 | 214k | case 4: break; // default to prior name mangle behavior |
142 | 289k | } |
143 | 289k | } |
144 | 289k | #endif |
145 | | |
146 | 289k | if (sampler.isMultiSample()) |
147 | 13.9k | mangledName += "M"; |
148 | 289k | break; |
149 | 324 | case EbtStruct: |
150 | 324 | case EbtBlock: |
151 | 324 | if (basicType == EbtStruct) |
152 | 324 | mangledName += "struct-"; |
153 | 0 | else |
154 | 0 | mangledName += "block-"; |
155 | 324 | if (typeName) |
156 | 324 | mangledName += *typeName; |
157 | 1.94k | for (unsigned int i = 0; i < structure->size(); ++i) { |
158 | 1.62k | if ((*structure)[i].type->getBasicType() == EbtVoid) |
159 | 0 | continue; |
160 | 1.62k | mangledName += '-'; |
161 | 1.62k | (*structure)[i].type->buildMangledName(mangledName); |
162 | 1.62k | } |
163 | 324 | break; |
164 | 38.3k | default: |
165 | 38.3k | break; |
166 | 2.00M | } |
167 | | |
168 | 2.00M | if (getVectorSize() > 0) |
169 | 1.59M | mangledName += static_cast<char>('0' + getVectorSize()); |
170 | 417k | else { |
171 | 417k | mangledName += static_cast<char>('0' + getMatrixCols()); |
172 | 417k | mangledName += static_cast<char>('0' + getMatrixRows()); |
173 | 417k | } |
174 | | |
175 | 2.00M | if (typeParameters) { |
176 | 0 | const int maxSize = 11; |
177 | 0 | char buf[maxSize]; |
178 | 0 | for (int i = 0; i < typeParameters->arraySizes->getNumDims(); ++i) { |
179 | 0 | if (typeParameters->arraySizes->getDimNode(i)) { |
180 | 0 | if (typeParameters->arraySizes->getDimNode(i)->getAsSymbolNode()) |
181 | 0 | snprintf(buf, maxSize, "s%lld", typeParameters->arraySizes->getDimNode(i)->getAsSymbolNode()->getId()); |
182 | 0 | else |
183 | 0 | snprintf(buf, maxSize, "s%p", typeParameters->arraySizes->getDimNode(i)); |
184 | 0 | } else |
185 | 0 | snprintf(buf, maxSize, "%d", typeParameters->arraySizes->getDimSize(i)); |
186 | 0 | mangledName += '<'; |
187 | 0 | mangledName += buf; |
188 | 0 | mangledName += '>'; |
189 | 0 | } |
190 | 0 | } |
191 | | |
192 | 2.00M | if (arraySizes) { |
193 | 37.2k | const int maxSize = 11; |
194 | 37.2k | char buf[maxSize]; |
195 | 74.5k | for (int i = 0; i < arraySizes->getNumDims(); ++i) { |
196 | 37.2k | if (arraySizes->getDimNode(i)) { |
197 | 0 | if (arraySizes->getDimNode(i)->getAsSymbolNode()) |
198 | 0 | snprintf(buf, maxSize, "s%lld", arraySizes->getDimNode(i)->getAsSymbolNode()->getId()); |
199 | 0 | else |
200 | 0 | snprintf(buf, maxSize, "s%p", (void*)(arraySizes->getDimNode(i))); |
201 | 0 | } else |
202 | 37.2k | snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i)); |
203 | 37.2k | mangledName += '['; |
204 | 37.2k | mangledName += buf; |
205 | 37.2k | mangledName += ']'; |
206 | 37.2k | } |
207 | 37.2k | } |
208 | 2.00M | } |
209 | | |
210 | | // |
211 | | // Dump functions. |
212 | | // |
213 | | |
214 | | void TSymbol::dumpExtensions(TInfoSink& infoSink) const |
215 | 404k | { |
216 | 404k | int numExtensions = getNumExtensions(); |
217 | 404k | if (numExtensions) { |
218 | 45.1k | infoSink.debug << " <"; |
219 | | |
220 | 90.3k | for (int i = 0; i < numExtensions; i++) |
221 | 45.1k | infoSink.debug << getExtensions()[i] << ","; |
222 | | |
223 | 45.1k | infoSink.debug << ">"; |
224 | 45.1k | } |
225 | 404k | } |
226 | | |
227 | | void TVariable::dump(TInfoSink& infoSink, bool complete) const |
228 | 1.60k | { |
229 | 1.60k | if (complete) { |
230 | 1.60k | infoSink.debug << getName().c_str() << ": " << type.getCompleteString(); |
231 | 1.60k | dumpExtensions(infoSink); |
232 | 1.60k | } else { |
233 | 0 | infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " " |
234 | 0 | << type.getBasicTypeString(); |
235 | |
|
236 | 0 | if (type.isArray()) |
237 | 0 | infoSink.debug << "[0]"; |
238 | 0 | } |
239 | | |
240 | 1.60k | infoSink.debug << "\n"; |
241 | 1.60k | } |
242 | | |
243 | | void TFunction::dump(TInfoSink& infoSink, bool complete) const |
244 | 402k | { |
245 | 402k | if (complete) { |
246 | 402k | infoSink.debug << getName().c_str() << ": " << returnType.getCompleteString() << " " << getName().c_str() |
247 | 402k | << "("; |
248 | | |
249 | 402k | int numParams = getParamCount(); |
250 | 1.36M | for (int i = 0; i < numParams; i++) { |
251 | 957k | const TParameter ¶m = parameters[i]; |
252 | 957k | infoSink.debug << param.type->getCompleteString() << " " |
253 | 957k | << (param.type->isStruct() ? "of " + param.type->getTypeName() + " " : "") |
254 | 957k | << (param.name ? *param.name : "") << (i < numParams - 1 ? "," : ""); |
255 | 957k | } |
256 | | |
257 | 402k | infoSink.debug << ")"; |
258 | 402k | dumpExtensions(infoSink); |
259 | 402k | } else { |
260 | 0 | infoSink.debug << getName().c_str() << ": " << returnType.getBasicTypeString() << " " |
261 | 0 | << getMangledName().c_str() << "n"; |
262 | 0 | } |
263 | | |
264 | 402k | infoSink.debug << "\n"; |
265 | 402k | } |
266 | | |
267 | | void TAnonMember::dump(TInfoSink& TInfoSink, bool) const |
268 | 32 | { |
269 | 32 | TInfoSink.debug << "anonymous member " << getMemberNumber() << " of " << getAnonContainer().getName().c_str() |
270 | 32 | << "\n"; |
271 | 32 | } |
272 | | |
273 | | void TSymbolTableLevel::dump(TInfoSink& infoSink, bool complete) const |
274 | 291 | { |
275 | 291 | tLevel::const_iterator it; |
276 | 404k | for (it = level.begin(); it != level.end(); ++it) |
277 | 404k | (*it).second->dump(infoSink, complete); |
278 | 291 | } |
279 | | |
280 | | void TSymbolTable::dump(TInfoSink& infoSink, bool complete) const |
281 | 97 | { |
282 | 388 | for (int level = currentLevel(); level >= 0; --level) { |
283 | 291 | infoSink.debug << "LEVEL " << level << "\n"; |
284 | 291 | table[level]->dump(infoSink, complete); |
285 | 291 | } |
286 | 97 | } |
287 | | |
288 | | // |
289 | | // Functions have buried pointers to delete. |
290 | | // |
291 | | TFunction::~TFunction() |
292 | 1.38M | { |
293 | 4.80M | for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) |
294 | 3.41M | delete (*i).type; |
295 | 1.38M | } |
296 | | |
297 | | // |
298 | | // Symbol table levels are a map of pointers to symbols that have to be deleted. |
299 | | // |
300 | | TSymbolTableLevel::~TSymbolTableLevel() |
301 | 4.54k | { |
302 | 1.41M | for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { |
303 | 1.40M | const TString& name = it->first; |
304 | 1.40M | auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(), |
305 | 1.40M | [&name](const std::pair<TString, TString>& i) { return i.first == name; }); |
306 | 1.40M | if (retargetIter == retargetedSymbols.end()) |
307 | 1.40M | delete (*it).second; |
308 | 1.40M | } |
309 | | |
310 | | |
311 | 4.54k | delete [] defaultPrecision; |
312 | 4.54k | } |
313 | | |
314 | | // |
315 | | // Change all function entries in the table with the non-mangled name |
316 | | // to be related to the provided built-in operation. |
317 | | // |
318 | | void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) |
319 | 941k | { |
320 | 941k | tLevel::const_iterator candidate = level.lower_bound(name); |
321 | 10.8M | while (candidate != level.end()) { |
322 | 10.4M | const TString& candidateName = (*candidate).first; |
323 | 10.4M | TString::size_type parenAt = candidateName.find_first_of('('); |
324 | 10.4M | if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) { |
325 | 9.87M | TFunction* function = (*candidate).second->getAsFunction(); |
326 | 9.87M | function->relateToOperator(op); |
327 | 9.87M | } else |
328 | 554k | break; |
329 | 9.87M | ++candidate; |
330 | 9.87M | } |
331 | 941k | } |
332 | | |
333 | | // Make all function overloads of the given name require an extension(s). |
334 | | // Should only be used for a version/profile that actually needs the extension(s). |
335 | | void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[]) |
336 | 15.5k | { |
337 | 15.5k | tLevel::const_iterator candidate = level.lower_bound(name); |
338 | 104k | while (candidate != level.end()) { |
339 | 101k | const TString& candidateName = (*candidate).first; |
340 | 101k | TString::size_type parenAt = candidateName.find_first_of('('); |
341 | 101k | if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) { |
342 | 88.5k | TSymbol* symbol = candidate->second; |
343 | 88.5k | symbol->setExtensions(num, extensions); |
344 | 88.5k | } else |
345 | 13.3k | break; |
346 | 88.5k | ++candidate; |
347 | 88.5k | } |
348 | 15.5k | } |
349 | | |
350 | | // Call the callback function to determine the required extensions |
351 | | void TSymbolTableLevel::setFunctionExtensionsCallback(const char* name, std::function<std::vector<const char *>(const char *)> const &func) |
352 | 540 | { |
353 | 540 | tLevel::const_iterator candidate = level.lower_bound(name); |
354 | 18.5k | while (candidate != level.end()) { |
355 | 18.5k | const TString& candidateName = (*candidate).first; |
356 | 18.5k | TString::size_type parenAt = candidateName.find_first_of('('); |
357 | 18.5k | if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) { |
358 | 18.0k | TSymbol* symbol = candidate->second; |
359 | | |
360 | 18.0k | auto exts = func(candidateName.c_str()); |
361 | 18.0k | symbol->setExtensions(exts.size(), exts.data()); |
362 | 18.0k | } else |
363 | 540 | break; |
364 | 18.0k | ++candidate; |
365 | 18.0k | } |
366 | 540 | } |
367 | | |
368 | | // Make a single function require an extension(s). i.e., this will only set the extensions for the symbol that matches 'name' exactly. |
369 | | // This is different from setFunctionExtensions, which uses std::map::lower_bound to effectively set all symbols that start with 'name'. |
370 | | // Should only be used for a version/profile that actually needs the extension(s). |
371 | | void TSymbolTableLevel::setSingleFunctionExtensions(const char* name, int num, const char* const extensions[]) |
372 | 0 | { |
373 | 0 | if (auto candidate = level.find(name); candidate != level.end()) { |
374 | 0 | candidate->second->setExtensions(num, extensions); |
375 | 0 | } |
376 | 0 | } |
377 | | |
378 | | // |
379 | | // Make all symbols in this table level read only. |
380 | | // |
381 | | void TSymbolTableLevel::readOnly() |
382 | 3.62k | { |
383 | 8.39M | for (tLevel::iterator it = level.begin(); it != level.end(); ++it) |
384 | 8.38M | (*it).second->makeReadOnly(); |
385 | 3.62k | } |
386 | | |
387 | | // |
388 | | // Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired. |
389 | | // |
390 | | TSymbol::TSymbol(const TSymbol& copyOf) |
391 | 597k | { |
392 | 597k | name = NewPoolTString(copyOf.name->c_str()); |
393 | 597k | mangledName = NewPoolTString(copyOf.mangledName->c_str()); |
394 | 597k | uniqueId = copyOf.uniqueId; |
395 | 597k | writable = true; |
396 | 597k | } |
397 | | |
398 | 7.22k | TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf) |
399 | 7.22k | { |
400 | 7.22k | type.deepCopy(copyOf.type); |
401 | 7.22k | userType = copyOf.userType; |
402 | | |
403 | | // we don't support specialization-constant subtrees in cloned tables, only extensions |
404 | 7.22k | constSubtree = nullptr; |
405 | 7.22k | extensions = nullptr; |
406 | 7.22k | memberExtensions = nullptr; |
407 | 7.22k | if (copyOf.getNumExtensions() > 0) |
408 | 3.65k | setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions()); |
409 | 7.22k | if (copyOf.hasMemberExtensions()) { |
410 | 516 | for (int m = 0; m < (int)copyOf.type.getStruct()->size(); ++m) { |
411 | 444 | if (copyOf.getNumMemberExtensions(m) > 0) |
412 | 348 | setMemberExtensions(m, copyOf.getNumMemberExtensions(m), copyOf.getMemberExtensions(m)); |
413 | 444 | } |
414 | 72 | } |
415 | | |
416 | 7.22k | if (! copyOf.constArray.empty()) { |
417 | 1.35k | assert(! copyOf.type.isStruct()); |
418 | 1.35k | TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size()); |
419 | 1.35k | constArray = newArray; |
420 | 1.35k | } |
421 | 7.22k | } |
422 | | |
423 | | TVariable* TVariable::clone() const |
424 | 7.22k | { |
425 | 7.22k | TVariable *variable = new TVariable(*this); |
426 | | |
427 | 7.22k | return variable; |
428 | 7.22k | } |
429 | | |
430 | 590k | TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf) |
431 | 590k | { |
432 | 2.02M | for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) { |
433 | 1.43M | TParameter param{}; |
434 | 1.43M | parameters.push_back(param); |
435 | 1.43M | (void)parameters.back().copyParam(copyOf.parameters[i]); |
436 | 1.43M | } |
437 | | |
438 | 590k | extensions = nullptr; |
439 | 590k | if (copyOf.getNumExtensions() > 0) |
440 | 74.9k | setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions()); |
441 | 590k | returnType.deepCopy(copyOf.returnType); |
442 | 590k | mangledName = copyOf.mangledName; |
443 | 590k | op = copyOf.op; |
444 | 590k | defined = copyOf.defined; |
445 | 590k | prototyped = copyOf.prototyped; |
446 | 590k | implicitThis = copyOf.implicitThis; |
447 | 590k | variadic = copyOf.variadic; |
448 | 590k | illegalImplicitThis = copyOf.illegalImplicitThis; |
449 | 590k | defaultParamCount = copyOf.defaultParamCount; |
450 | 590k | spirvInst = copyOf.spirvInst; |
451 | 590k | } |
452 | | |
453 | | TFunction* TFunction::clone() const |
454 | 590k | { |
455 | 590k | TFunction *function = new TFunction(*this); |
456 | | |
457 | 590k | return function; |
458 | 590k | } |
459 | | |
460 | | TAnonMember* TAnonMember::clone() const |
461 | 0 | { |
462 | | // Anonymous members of a given block should be cloned at a higher level, |
463 | | // where they can all be assured to still end up pointing to a single |
464 | | // copy of the original container. |
465 | 0 | assert(0); |
466 | |
|
467 | 0 | return nullptr; |
468 | 0 | } |
469 | | |
470 | | TSymbolTableLevel* TSymbolTableLevel::clone() const |
471 | 1.89k | { |
472 | 1.89k | TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); |
473 | 1.89k | symTableLevel->anonId = anonId; |
474 | 1.89k | symTableLevel->thisLevel = thisLevel; |
475 | 1.89k | symTableLevel->retargetedSymbols.clear(); |
476 | 1.89k | for (auto &s : retargetedSymbols) { |
477 | 0 | symTableLevel->retargetedSymbols.push_back({s.first, s.second}); |
478 | 0 | } |
479 | 1.89k | std::vector<bool> containerCopied(anonId, false); |
480 | 1.89k | tLevel::const_iterator iter; |
481 | 599k | for (iter = level.begin(); iter != level.end(); ++iter) { |
482 | 597k | const TAnonMember* anon = iter->second->getAsAnonMember(); |
483 | 597k | if (anon) { |
484 | | // Insert all the anonymous members of this same container at once, |
485 | | // avoid inserting the remaining members in the future, once this has been done, |
486 | | // allowing them to all be part of the same new container. |
487 | 144 | if (! containerCopied[anon->getAnonId()]) { |
488 | 36 | TVariable* container = anon->getAnonContainer().clone(); |
489 | 36 | container->changeName(NewPoolTString("")); |
490 | | // insert the container and all its members |
491 | 36 | symTableLevel->insert(*container, false); |
492 | 36 | containerCopied[anon->getAnonId()] = true; |
493 | 36 | } |
494 | 597k | } else { |
495 | 597k | const TString& name = iter->first; |
496 | 597k | auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(), |
497 | 597k | [&name](const std::pair<TString, TString>& i) { return i.first == name; }); |
498 | 597k | if (retargetIter != retargetedSymbols.end()) |
499 | 0 | continue; |
500 | 597k | symTableLevel->insert(*iter->second->clone(), false); |
501 | 597k | } |
502 | 597k | } |
503 | | // Now point retargeted symbols to the newly created versions of them |
504 | 1.89k | for (auto &s : retargetedSymbols) { |
505 | 0 | TSymbol* sym = symTableLevel->find(s.second); |
506 | 0 | if (!sym) |
507 | 0 | continue; |
508 | 0 | symTableLevel->insert(s.first, sym); |
509 | 0 | } |
510 | | |
511 | 1.89k | return symTableLevel; |
512 | 1.89k | } |
513 | | |
514 | | void TSymbolTable::copyTable(const TSymbolTable& copyOf) |
515 | 1.89k | { |
516 | 1.89k | assert(adoptedLevels == copyOf.adoptedLevels); |
517 | | |
518 | 1.89k | uniqueId = copyOf.uniqueId; |
519 | 1.89k | noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations; |
520 | 1.89k | separateNameSpaces = copyOf.separateNameSpaces; |
521 | 3.78k | for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i) |
522 | 1.89k | table.push_back(copyOf.table[i]->clone()); |
523 | 1.89k | } |
524 | | |
525 | | } // end namespace glslang |