blob: 2af12090bf71646b1c35090a753c5eab7bd27950 [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;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +000047 case EbtUInt: mangledName += 'u'; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000048 case EbtBool: mangledName += 'b'; break;
49 case EbtSampler2D: mangledName += "s2"; break;
50 case EbtSamplerCube: mangledName += "sC"; break;
51 case EbtStruct:
52 mangledName += "struct-";
53 if (typeName)
54 mangledName += *typeName;
55 {// support MSVC++6.0
56 for (unsigned int i = 0; i < structure->size(); ++i) {
57 mangledName += '-';
58 (*structure)[i].type->buildMangledName(mangledName);
59 }
60 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000061 break;
62 case EbtInterfaceBlock:
63 {
64 mangledName += "interface-block-";
65 if (typeName)
66 {
67 mangledName += *typeName;
68 }
69 for (unsigned int i = 0; i < structure->size(); ++i)
70 {
71 mangledName += '-';
72 (*structure)[i].type->buildMangledName(mangledName);
73 }
74 }
75 break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000076 default:
77 break;
78 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +000080 if (isMatrix())
81 {
82 mangledName += static_cast<char>('0' + getCols());
83 mangledName += static_cast<char>('x');
84 mangledName += static_cast<char>('0' + getRows());
85 }
86 else
87 {
88 mangledName += static_cast<char>('0' + getNominalSize());
89 }
daniel@transgaming.com0578f812010-05-17 09:58:39 +000090 if (isArray()) {
91 char buf[20];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +000092 snprintf(buf, sizeof(buf), "%d", arraySize);
daniel@transgaming.com0578f812010-05-17 09:58:39 +000093 mangledName += '[';
94 mangledName += buf;
95 mangledName += ']';
96 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097}
98
99int TType::getStructSize() const
100{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000101 if (!getStruct()) {
102 assert(false && "Not a struct");
103 return 0;
104 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000106 if (structureSize == 0)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000107 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000108 structureSize += ((*tl).type)->getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000110 return structureSize;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111}
112
kbr@chromium.org476541f2011-10-27 21:14:51 +0000113void TType::computeDeepestStructNesting()
114{
115 if (!getStruct()) {
116 return;
117 }
118
119 int maxNesting = 0;
120 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
121 maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
122 }
123
124 deepestStructNesting = 1 + maxNesting;
125}
126
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000127bool TType::isStructureContainingArrays() const
128{
129 if (!structure)
130 {
131 return false;
132 }
133
134 for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
135 {
136 if (member->type->isArray() ||
137 member->type->isStructureContainingArrays())
138 {
139 return true;
140 }
141 }
142
143 return false;
144}
145
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146//
147// Dump functions.
148//
149
150void TVariable::dump(TInfoSink& infoSink) const
151{
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000152 infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000153 if (type.isArray()) {
154 infoSink.debug << "[0]";
155 }
156 infoSink.debug << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157}
158
159void TFunction::dump(TInfoSink &infoSink) const
160{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000161 infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162}
163
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +0000164void TInterfaceBlockName::dump(TInfoSink &infoSink) const
165{
166 infoSink.debug << "interface block " << getName().c_str() << "\n";
167}
168
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169void TSymbolTableLevel::dump(TInfoSink &infoSink) const
170{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000171 tLevel::const_iterator it;
172 for (it = level.begin(); it != level.end(); ++it)
173 (*it).second->dump(infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174}
175
176void TSymbolTable::dump(TInfoSink &infoSink) const
177{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000178 for (int level = currentLevel(); level >= 0; --level) {
179 infoSink.debug << "LEVEL " << level << "\n";
180 table[level]->dump(infoSink);
181 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182}
183
184//
185// Functions have buried pointers to delete.
186//
187TFunction::~TFunction()
188{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000189 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
190 delete (*i).type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191}
192
193//
194// Symbol table levels are a map of pointers to symbols that have to be deleted.
195//
196TSymbolTableLevel::~TSymbolTableLevel()
197{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000198 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
199 delete (*it).second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200}
201
202//
203// Change all function entries in the table with the non-mangled name
204// to be related to the provided built-in operation. This is a low
205// performance operation, and only intended for symbol tables that
206// live across a large number of compiles.
207//
208void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
209{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000210 tLevel::iterator it;
211 for (it = level.begin(); it != level.end(); ++it) {
212 if ((*it).second->isFunction()) {
213 TFunction* function = static_cast<TFunction*>((*it).second);
214 if (function->getName() == name)
215 function->relateToOperator(op);
216 }
217 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218}
219
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000220//
221// Change all function entries in the table with the non-mangled name
222// to be related to the provided built-in extension. This is a low
223// performance operation, and only intended for symbol tables that
224// live across a large number of compiles.
225//
226void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
227{
228 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
229 if (it->second->isFunction()) {
230 TFunction* function = static_cast<TFunction*>(it->second);
231 if (function->getName() == name)
232 function->relateToExtension(ext);
233 }
234 }
235}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236
237TSymbol::TSymbol(const TSymbol& copyOf)
238{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000239 name = NewPoolTString(copyOf.name->c_str());
240 uniqueId = copyOf.uniqueId;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241}
242
243TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
244{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000245 type.copyType(copyOf.type, remapper);
246 userType = copyOf.userType;
247 // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
248 assert(copyOf.arrayInformationType == 0);
249 arrayInformationType = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000251 if (copyOf.unionArray) {
252 assert(!copyOf.type.getStruct());
253 assert(copyOf.type.getObjectSize() == 1);
254 unionArray = new ConstantUnion[1];
255 unionArray[0] = copyOf.unionArray[0];
256 } else
257 unionArray = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258}
259
260TVariable* TVariable::clone(TStructureMap& remapper)
261{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000262 TVariable *variable = new TVariable(*this, remapper);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000264 return variable;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265}
266
267TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
268{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000269 for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
270 TParameter param;
271 parameters.push_back(param);
272 parameters.back().copyParam(copyOf.parameters[i], remapper);
273 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000275 returnType.copyType(copyOf.returnType, remapper);
276 mangledName = copyOf.mangledName;
277 op = copyOf.op;
278 defined = copyOf.defined;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279}
280
281TFunction* TFunction::clone(TStructureMap& remapper)
282{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000283 TFunction *function = new TFunction(*this, remapper);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000285 return function;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286}
287
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +0000288TInterfaceBlockName* TInterfaceBlockName::clone(TStructureMap& remapper)
289{
290 return new TInterfaceBlockName(this->name);
291}
292
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
294{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000295 TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
296 tLevel::iterator iter;
297 for (iter = level.begin(); iter != level.end(); ++iter) {
298 symTableLevel->insert(*iter->second->clone(remapper));
299 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000301 return symTableLevel;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302}
303
304void TSymbolTable::copyTable(const TSymbolTable& copyOf)
305{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000306 TStructureMap remapper;
307 uniqueId = copyOf.uniqueId;
308 for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
309 table.push_back(copyOf.table[i]->clone(remapper));
310 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000311 for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
312 precisionStack.push_back( copyOf.precisionStack[i] );
313 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314}
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000315
316TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope)
317{
318 int level = currentLevel();
319 TSymbol *symbol;
320
321 do
322 {
323 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
324 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
325
326 symbol = table[level]->find(name);
327 }
328 while (symbol == 0 && --level >= 0);
329
330 if (builtIn)
331 *builtIn = (level <= LAST_BUILTIN_LEVEL);
332 if (sameScope)
333 *sameScope = (level == currentLevel());
334
335 return symbol;
336}
337
338TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion)
339{
340 for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
341 {
342 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
343 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
344
345 TSymbol *symbol = table[level]->find(name);
346
347 if (symbol)
348 return symbol;
349 }
350
351 return 0;
352}