blob: c6e9fcb05ecca3d04258f87c4097a11ccfb41a08 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Symbol table for parsing. Most functionaliy and main ideas
9// are documented in the header file.
10//
11
apatrick@chromium.orge057c5d2012-01-26 19:18:24 +000012#if defined(_MSC_VER)
13#pragma warning(disable: 4718)
14#endif
15
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000016#include "compiler/SymbolTable.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000017
apatrick@chromium.org8187fa82010-06-15 22:09:28 +000018#include <stdio.h>
kbr@chromium.org476541f2011-10-27 21:14:51 +000019#include <algorithm>
20
alokp@chromium.org79fb1012012-04-26 21:07:39 +000021#include "common/angleutils.h"
22
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +000023TType::TType(const TPublicType &p) :
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +000024 type(p.type), precision(p.precision), qualifier(p.qualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize),
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000025 maxArraySize(0), arrayInformationType(0), interfaceBlockType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +000026{
27 if (p.userDef) {
28 structure = p.userDef->getStruct();
29 typeName = NewPoolTString(p.userDef->getTypeName().c_str());
30 computeDeepestStructNesting();
31 }
32}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033
34//
35// Recursively generate mangled names.
36//
37void TType::buildMangledName(TString& mangledName)
38{
daniel@transgaming.com0578f812010-05-17 09:58:39 +000039 if (isMatrix())
40 mangledName += 'm';
41 else if (isVector())
42 mangledName += 'v';
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
daniel@transgaming.com0578f812010-05-17 09:58:39 +000044 switch (type) {
45 case EbtFloat: mangledName += 'f'; break;
46 case EbtInt: mangledName += 'i'; break;
47 case EbtBool: mangledName += 'b'; break;
48 case EbtSampler2D: mangledName += "s2"; break;
49 case EbtSamplerCube: mangledName += "sC"; break;
50 case EbtStruct:
51 mangledName += "struct-";
52 if (typeName)
53 mangledName += *typeName;
54 {// support MSVC++6.0
55 for (unsigned int i = 0; i < structure->size(); ++i) {
56 mangledName += '-';
57 (*structure)[i].type->buildMangledName(mangledName);
58 }
59 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000060 break;
61 case EbtInterfaceBlock:
62 {
63 mangledName += "interface-block-";
64 if (typeName)
65 {
66 mangledName += *typeName;
67 }
68 for (unsigned int i = 0; i < structure->size(); ++i)
69 {
70 mangledName += '-';
71 (*structure)[i].type->buildMangledName(mangledName);
72 }
73 }
74 break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000075 default:
76 break;
77 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000078
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +000079 if (isMatrix())
80 {
81 mangledName += static_cast<char>('0' + getCols());
82 mangledName += static_cast<char>('x');
83 mangledName += static_cast<char>('0' + getRows());
84 }
85 else
86 {
87 mangledName += static_cast<char>('0' + getNominalSize());
88 }
daniel@transgaming.com0578f812010-05-17 09:58:39 +000089 if (isArray()) {
90 char buf[20];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +000091 snprintf(buf, sizeof(buf), "%d", arraySize);
daniel@transgaming.com0578f812010-05-17 09:58:39 +000092 mangledName += '[';
93 mangledName += buf;
94 mangledName += ']';
95 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096}
97
98int TType::getStructSize() const
99{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000100 if (!getStruct()) {
101 assert(false && "Not a struct");
102 return 0;
103 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000105 if (structureSize == 0)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000106 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000107 structureSize += ((*tl).type)->getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000109 return structureSize;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110}
111
kbr@chromium.org476541f2011-10-27 21:14:51 +0000112void TType::computeDeepestStructNesting()
113{
114 if (!getStruct()) {
115 return;
116 }
117
118 int maxNesting = 0;
119 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
120 maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
121 }
122
123 deepestStructNesting = 1 + maxNesting;
124}
125
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000126bool TType::isStructureContainingArrays() const
127{
128 if (!structure)
129 {
130 return false;
131 }
132
133 for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
134 {
135 if (member->type->isArray() ||
136 member->type->isStructureContainingArrays())
137 {
138 return true;
139 }
140 }
141
142 return false;
143}
144
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145//
146// Dump functions.
147//
148
149void TVariable::dump(TInfoSink& infoSink) const
150{
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000151 infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000152 if (type.isArray()) {
153 infoSink.debug << "[0]";
154 }
155 infoSink.debug << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
158void TFunction::dump(TInfoSink &infoSink) const
159{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000160 infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161}
162
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +0000163void TInterfaceBlockName::dump(TInfoSink &infoSink) const
164{
165 infoSink.debug << "interface block " << getName().c_str() << "\n";
166}
167
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168void TSymbolTableLevel::dump(TInfoSink &infoSink) const
169{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000170 tLevel::const_iterator it;
171 for (it = level.begin(); it != level.end(); ++it)
172 (*it).second->dump(infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173}
174
175void TSymbolTable::dump(TInfoSink &infoSink) const
176{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000177 for (int level = currentLevel(); level >= 0; --level) {
178 infoSink.debug << "LEVEL " << level << "\n";
179 table[level]->dump(infoSink);
180 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181}
182
183//
184// Functions have buried pointers to delete.
185//
186TFunction::~TFunction()
187{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000188 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
189 delete (*i).type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190}
191
192//
193// Symbol table levels are a map of pointers to symbols that have to be deleted.
194//
195TSymbolTableLevel::~TSymbolTableLevel()
196{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000197 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
198 delete (*it).second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199}
200
201//
202// Change all function entries in the table with the non-mangled name
203// to be related to the provided built-in operation. This is a low
204// performance operation, and only intended for symbol tables that
205// live across a large number of compiles.
206//
207void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
208{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000209 tLevel::iterator it;
210 for (it = level.begin(); it != level.end(); ++it) {
211 if ((*it).second->isFunction()) {
212 TFunction* function = static_cast<TFunction*>((*it).second);
213 if (function->getName() == name)
214 function->relateToOperator(op);
215 }
216 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217}
218
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000219//
220// Change all function entries in the table with the non-mangled name
221// to be related to the provided built-in extension. This is a low
222// performance operation, and only intended for symbol tables that
223// live across a large number of compiles.
224//
225void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
226{
227 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
228 if (it->second->isFunction()) {
229 TFunction* function = static_cast<TFunction*>(it->second);
230 if (function->getName() == name)
231 function->relateToExtension(ext);
232 }
233 }
234}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235
236TSymbol::TSymbol(const TSymbol& copyOf)
237{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000238 name = NewPoolTString(copyOf.name->c_str());
239 uniqueId = copyOf.uniqueId;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240}
241
242TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
243{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000244 type.copyType(copyOf.type, remapper);
245 userType = copyOf.userType;
246 // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
247 assert(copyOf.arrayInformationType == 0);
248 arrayInformationType = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000250 if (copyOf.unionArray) {
251 assert(!copyOf.type.getStruct());
252 assert(copyOf.type.getObjectSize() == 1);
253 unionArray = new ConstantUnion[1];
254 unionArray[0] = copyOf.unionArray[0];
255 } else
256 unionArray = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257}
258
259TVariable* TVariable::clone(TStructureMap& remapper)
260{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000261 TVariable *variable = new TVariable(*this, remapper);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000263 return variable;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264}
265
266TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
267{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000268 for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
269 TParameter param;
270 parameters.push_back(param);
271 parameters.back().copyParam(copyOf.parameters[i], remapper);
272 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000274 returnType.copyType(copyOf.returnType, remapper);
275 mangledName = copyOf.mangledName;
276 op = copyOf.op;
277 defined = copyOf.defined;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278}
279
280TFunction* TFunction::clone(TStructureMap& remapper)
281{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000282 TFunction *function = new TFunction(*this, remapper);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000284 return function;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285}
286
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +0000287TInterfaceBlockName* TInterfaceBlockName::clone(TStructureMap& remapper)
288{
289 return new TInterfaceBlockName(this->name);
290}
291
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
293{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000294 TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
295 tLevel::iterator iter;
296 for (iter = level.begin(); iter != level.end(); ++iter) {
297 symTableLevel->insert(*iter->second->clone(remapper));
298 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000300 return symTableLevel;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301}
302
303void TSymbolTable::copyTable(const TSymbolTable& copyOf)
304{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000305 TStructureMap remapper;
306 uniqueId = copyOf.uniqueId;
307 for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
308 table.push_back(copyOf.table[i]->clone(remapper));
309 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000310 for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
311 precisionStack.push_back( copyOf.precisionStack[i] );
312 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313}
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000314
315TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope)
316{
317 int level = currentLevel();
318 TSymbol *symbol;
319
320 do
321 {
322 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
323 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
324
325 symbol = table[level]->find(name);
326 }
327 while (symbol == 0 && --level >= 0);
328
329 if (builtIn)
330 *builtIn = (level <= LAST_BUILTIN_LEVEL);
331 if (sameScope)
332 *sameScope = (level == currentLevel());
333
334 return symbol;
335}
336
337TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion)
338{
339 for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
340 {
341 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
342 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
343
344 TSymbol *symbol = table[level]->find(name);
345
346 if (symbol)
347 return symbol;
348 }
349
350 return 0;
351}