blob: 275dd8cc1630b424939e5d436ab2e908c3ce59df [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
Nicolas Capensbd10cf52013-06-20 09:51:51 -040021int TSymbolTableLevel::uniqueId = 0;
22
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +000023TType::TType(const TPublicType &p) :
Jamie Madilla5efff92013-06-06 11:56:47 -040024 type(p.type), precision(p.precision), qualifier(p.qualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), layoutQualifier(p.layoutQualifier), 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;
Nicolas Capensda075352013-06-24 16:02:56 -040050 case EbtSampler3D: mangledName += "s3"; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000051 case EbtSamplerCube: mangledName += "sC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040052 case EbtSampler2DArray: mangledName += "s2a"; break;
Nicolas Capens344e7142013-06-24 15:39:21 -040053 case EbtISampler2D: mangledName += "is2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040054 case EbtISampler3D: mangledName += "is3"; break;
Nicolas Capens344e7142013-06-24 15:39:21 -040055 case EbtISamplerCube: mangledName += "isC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040056 case EbtISampler2DArray: mangledName += "is2a"; break;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -040057 case EbtUSampler2D: mangledName += "us2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040058 case EbtUSampler3D: mangledName += "us3"; break;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -040059 case EbtUSamplerCube: mangledName += "usC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040060 case EbtUSampler2DArray: mangledName += "us2a"; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000061 case EbtStruct:
62 mangledName += "struct-";
63 if (typeName)
64 mangledName += *typeName;
65 {// support MSVC++6.0
66 for (unsigned int i = 0; i < structure->size(); ++i) {
67 mangledName += '-';
68 (*structure)[i].type->buildMangledName(mangledName);
69 }
70 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000071 break;
72 case EbtInterfaceBlock:
73 {
74 mangledName += "interface-block-";
75 if (typeName)
76 {
77 mangledName += *typeName;
78 }
79 for (unsigned int i = 0; i < structure->size(); ++i)
80 {
81 mangledName += '-';
82 (*structure)[i].type->buildMangledName(mangledName);
83 }
84 }
85 break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000086 default:
87 break;
88 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +000090 if (isMatrix())
91 {
92 mangledName += static_cast<char>('0' + getCols());
93 mangledName += static_cast<char>('x');
94 mangledName += static_cast<char>('0' + getRows());
95 }
96 else
97 {
98 mangledName += static_cast<char>('0' + getNominalSize());
99 }
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000100 if (isArray()) {
101 char buf[20];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +0000102 snprintf(buf, sizeof(buf), "%d", arraySize);
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000103 mangledName += '[';
104 mangledName += buf;
105 mangledName += ']';
106 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107}
108
109int TType::getStructSize() const
110{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000111 if (!getStruct()) {
112 assert(false && "Not a struct");
113 return 0;
114 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000116 if (structureSize == 0)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000117 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000118 structureSize += ((*tl).type)->getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000120 return structureSize;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121}
122
kbr@chromium.org476541f2011-10-27 21:14:51 +0000123void TType::computeDeepestStructNesting()
124{
125 if (!getStruct()) {
126 return;
127 }
128
129 int maxNesting = 0;
130 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
131 maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
132 }
133
134 deepestStructNesting = 1 + maxNesting;
135}
136
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000137bool TType::isStructureContainingArrays() const
138{
139 if (!structure)
140 {
141 return false;
142 }
143
144 for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
145 {
146 if (member->type->isArray() ||
147 member->type->isStructureContainingArrays())
148 {
149 return true;
150 }
151 }
152
153 return false;
154}
155
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157// Functions have buried pointers to delete.
158//
159TFunction::~TFunction()
160{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000161 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
162 delete (*i).type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163}
164
165//
166// Symbol table levels are a map of pointers to symbols that have to be deleted.
167//
168TSymbolTableLevel::~TSymbolTableLevel()
169{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000170 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
171 delete (*it).second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172}
173
174//
175// Change all function entries in the table with the non-mangled name
176// to be related to the provided built-in operation. This is a low
177// performance operation, and only intended for symbol tables that
178// live across a large number of compiles.
179//
180void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
181{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000182 tLevel::iterator it;
183 for (it = level.begin(); it != level.end(); ++it) {
184 if ((*it).second->isFunction()) {
185 TFunction* function = static_cast<TFunction*>((*it).second);
186 if (function->getName() == name)
187 function->relateToOperator(op);
188 }
189 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190}
191
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000192//
193// Change all function entries in the table with the non-mangled name
194// to be related to the provided built-in extension. This is a low
195// performance operation, and only intended for symbol tables that
196// live across a large number of compiles.
197//
198void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
199{
200 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
201 if (it->second->isFunction()) {
202 TFunction* function = static_cast<TFunction*>(it->second);
203 if (function->getName() == name)
204 function->relateToExtension(ext);
205 }
206 }
207}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208
209TSymbol::TSymbol(const TSymbol& copyOf)
210{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000211 name = NewPoolTString(copyOf.name->c_str());
212 uniqueId = copyOf.uniqueId;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213}
214
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000215TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope)
216{
217 int level = currentLevel();
218 TSymbol *symbol;
219
220 do
221 {
222 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
223 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
224
225 symbol = table[level]->find(name);
226 }
227 while (symbol == 0 && --level >= 0);
228
229 if (builtIn)
230 *builtIn = (level <= LAST_BUILTIN_LEVEL);
231 if (sameScope)
232 *sameScope = (level == currentLevel());
233
234 return symbol;
235}
236
237TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion)
238{
239 for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
240 {
241 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
242 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
243
244 TSymbol *symbol = table[level]->find(name);
245
246 if (symbol)
247 return symbol;
248 }
249
250 return 0;
251}