blob: 263c323135e2669085c98c3f46fd8d9a712dc432 [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>
Jamie Madill94bf7f22013-07-08 13:31:15 -040020#include <climits>
kbr@chromium.org476541f2011-10-27 21:14:51 +000021
Nicolas Capensbd10cf52013-06-20 09:51:51 -040022int TSymbolTableLevel::uniqueId = 0;
23
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +000024TType::TType(const TPublicType &p) :
Jamie Madilla5efff92013-06-06 11:56:47 -040025 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 +000026 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 +000027{
28 if (p.userDef) {
29 structure = p.userDef->getStruct();
30 typeName = NewPoolTString(p.userDef->getTypeName().c_str());
31 computeDeepestStructNesting();
32 }
33}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034
35//
36// Recursively generate mangled names.
37//
38void TType::buildMangledName(TString& mangledName)
39{
daniel@transgaming.com0578f812010-05-17 09:58:39 +000040 if (isMatrix())
41 mangledName += 'm';
42 else if (isVector())
43 mangledName += 'v';
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000044
daniel@transgaming.com0578f812010-05-17 09:58:39 +000045 switch (type) {
46 case EbtFloat: mangledName += 'f'; break;
47 case EbtInt: mangledName += 'i'; break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +000048 case EbtUInt: mangledName += 'u'; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000049 case EbtBool: mangledName += 'b'; break;
50 case EbtSampler2D: mangledName += "s2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040051 case EbtSampler3D: mangledName += "s3"; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000052 case EbtSamplerCube: mangledName += "sC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040053 case EbtSampler2DArray: mangledName += "s2a"; break;
Nicolas Capens344e7142013-06-24 15:39:21 -040054 case EbtISampler2D: mangledName += "is2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040055 case EbtISampler3D: mangledName += "is3"; break;
Nicolas Capens344e7142013-06-24 15:39:21 -040056 case EbtISamplerCube: mangledName += "isC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040057 case EbtISampler2DArray: mangledName += "is2a"; break;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -040058 case EbtUSampler2D: mangledName += "us2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040059 case EbtUSampler3D: mangledName += "us3"; break;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -040060 case EbtUSamplerCube: mangledName += "usC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040061 case EbtUSampler2DArray: mangledName += "us2a"; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000062 case EbtStruct:
63 mangledName += "struct-";
64 if (typeName)
65 mangledName += *typeName;
66 {// support MSVC++6.0
67 for (unsigned int i = 0; i < structure->size(); ++i) {
68 mangledName += '-';
69 (*structure)[i].type->buildMangledName(mangledName);
70 }
71 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000072 break;
73 case EbtInterfaceBlock:
74 {
75 mangledName += "interface-block-";
76 if (typeName)
77 {
78 mangledName += *typeName;
79 }
80 for (unsigned int i = 0; i < structure->size(); ++i)
81 {
82 mangledName += '-';
83 (*structure)[i].type->buildMangledName(mangledName);
84 }
85 }
86 break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000087 default:
88 break;
89 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000090
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +000091 if (isMatrix())
92 {
93 mangledName += static_cast<char>('0' + getCols());
94 mangledName += static_cast<char>('x');
95 mangledName += static_cast<char>('0' + getRows());
96 }
97 else
98 {
99 mangledName += static_cast<char>('0' + getNominalSize());
100 }
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000101 if (isArray()) {
102 char buf[20];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +0000103 snprintf(buf, sizeof(buf), "%d", arraySize);
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000104 mangledName += '[';
105 mangledName += buf;
106 mangledName += ']';
107 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108}
109
Jamie Madill94bf7f22013-07-08 13:31:15 -0400110size_t TType::getObjectSize() const
111{
112 size_t totalSize;
113
114 if (getBasicType() == EbtStruct)
115 totalSize = getStructSize();
116 else
117 totalSize = primarySize * secondarySize;
118
119 if (isArray()) {
120 size_t arraySize = std::max(getArraySize(), getMaxArraySize());
121 if (arraySize > INT_MAX / totalSize)
122 totalSize = INT_MAX;
123 else
124 totalSize *= arraySize;
125 }
126
127 return totalSize;
128}
129
130size_t TType::getStructSize() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000132 if (!getStruct()) {
133 assert(false && "Not a struct");
134 return 0;
135 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136
Jamie Madill94bf7f22013-07-08 13:31:15 -0400137 if (structureSize == 0) {
138 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) {
139 size_t fieldSize = ((*tl).type)->getObjectSize();
140 if (fieldSize > INT_MAX - structureSize)
141 structureSize = INT_MAX;
142 else
143 structureSize += fieldSize;
144 }
145 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000147 return structureSize;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148}
149
kbr@chromium.org476541f2011-10-27 21:14:51 +0000150void TType::computeDeepestStructNesting()
151{
152 if (!getStruct()) {
153 return;
154 }
155
156 int maxNesting = 0;
157 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
158 maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
159 }
160
161 deepestStructNesting = 1 + maxNesting;
162}
163
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000164bool TType::isStructureContainingArrays() const
165{
166 if (!structure)
167 {
168 return false;
169 }
170
171 for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
172 {
173 if (member->type->isArray() ||
174 member->type->isStructureContainingArrays())
175 {
176 return true;
177 }
178 }
179
180 return false;
181}
182
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184// 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
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000242TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope)
243{
244 int level = currentLevel();
245 TSymbol *symbol;
246
247 do
248 {
249 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
250 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
251
252 symbol = table[level]->find(name);
253 }
254 while (symbol == 0 && --level >= 0);
255
256 if (builtIn)
257 *builtIn = (level <= LAST_BUILTIN_LEVEL);
258 if (sameScope)
259 *sameScope = (level == currentLevel());
260
261 return symbol;
262}
263
264TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion)
265{
266 for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
267 {
268 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
269 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
270
271 TSymbol *symbol = table[level]->find(name);
272
273 if (symbol)
274 return symbol;
275 }
276
277 return 0;
278}