blob: 8e4636d24fc2d22ac17790ba0f023268d0418643 [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
Nicolas Capensbd10cf52013-06-20 09:51:51 -040023int TSymbolTableLevel::uniqueId = 0;
24
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +000025TType::TType(const TPublicType &p) :
Jamie Madilla5efff92013-06-06 11:56:47 -040026 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 +000027 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 +000028{
29 if (p.userDef) {
30 structure = p.userDef->getStruct();
31 typeName = NewPoolTString(p.userDef->getTypeName().c_str());
32 computeDeepestStructNesting();
33 }
34}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035
36//
37// Recursively generate mangled names.
38//
39void TType::buildMangledName(TString& mangledName)
40{
daniel@transgaming.com0578f812010-05-17 09:58:39 +000041 if (isMatrix())
42 mangledName += 'm';
43 else if (isVector())
44 mangledName += 'v';
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000045
daniel@transgaming.com0578f812010-05-17 09:58:39 +000046 switch (type) {
47 case EbtFloat: mangledName += 'f'; break;
48 case EbtInt: mangledName += 'i'; break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +000049 case EbtUInt: mangledName += 'u'; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000050 case EbtBool: mangledName += 'b'; break;
51 case EbtSampler2D: mangledName += "s2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040052 case EbtSampler3D: mangledName += "s3"; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000053 case EbtSamplerCube: mangledName += "sC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040054 case EbtSampler2DArray: mangledName += "s2a"; break;
Nicolas Capens344e7142013-06-24 15:39:21 -040055 case EbtISampler2D: mangledName += "is2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040056 case EbtISampler3D: mangledName += "is3"; break;
Nicolas Capens344e7142013-06-24 15:39:21 -040057 case EbtISamplerCube: mangledName += "isC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040058 case EbtISampler2DArray: mangledName += "is2a"; break;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -040059 case EbtUSampler2D: mangledName += "us2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040060 case EbtUSampler3D: mangledName += "us3"; break;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -040061 case EbtUSamplerCube: mangledName += "usC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040062 case EbtUSampler2DArray: mangledName += "us2a"; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000063 case EbtStruct:
64 mangledName += "struct-";
65 if (typeName)
66 mangledName += *typeName;
67 {// support MSVC++6.0
68 for (unsigned int i = 0; i < structure->size(); ++i) {
69 mangledName += '-';
70 (*structure)[i].type->buildMangledName(mangledName);
71 }
72 }
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000073 break;
74 case EbtInterfaceBlock:
75 {
76 mangledName += "interface-block-";
77 if (typeName)
78 {
79 mangledName += *typeName;
80 }
81 for (unsigned int i = 0; i < structure->size(); ++i)
82 {
83 mangledName += '-';
84 (*structure)[i].type->buildMangledName(mangledName);
85 }
86 }
87 break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000088 default:
89 break;
90 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +000092 if (isMatrix())
93 {
94 mangledName += static_cast<char>('0' + getCols());
95 mangledName += static_cast<char>('x');
96 mangledName += static_cast<char>('0' + getRows());
97 }
98 else
99 {
100 mangledName += static_cast<char>('0' + getNominalSize());
101 }
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000102 if (isArray()) {
103 char buf[20];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +0000104 snprintf(buf, sizeof(buf), "%d", arraySize);
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000105 mangledName += '[';
106 mangledName += buf;
107 mangledName += ']';
108 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109}
110
111int TType::getStructSize() const
112{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000113 if (!getStruct()) {
114 assert(false && "Not a struct");
115 return 0;
116 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000118 if (structureSize == 0)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000119 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000120 structureSize += ((*tl).type)->getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000122 return structureSize;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123}
124
kbr@chromium.org476541f2011-10-27 21:14:51 +0000125void TType::computeDeepestStructNesting()
126{
127 if (!getStruct()) {
128 return;
129 }
130
131 int maxNesting = 0;
132 for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
133 maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
134 }
135
136 deepestStructNesting = 1 + maxNesting;
137}
138
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000139bool TType::isStructureContainingArrays() const
140{
141 if (!structure)
142 {
143 return false;
144 }
145
146 for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
147 {
148 if (member->type->isArray() ||
149 member->type->isStructureContainingArrays())
150 {
151 return true;
152 }
153 }
154
155 return false;
156}
157
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000158//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159// Functions have buried pointers to delete.
160//
161TFunction::~TFunction()
162{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000163 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
164 delete (*i).type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165}
166
167//
168// Symbol table levels are a map of pointers to symbols that have to be deleted.
169//
170TSymbolTableLevel::~TSymbolTableLevel()
171{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000172 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
173 delete (*it).second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174}
175
176//
177// Change all function entries in the table with the non-mangled name
178// to be related to the provided built-in operation. This is a low
179// performance operation, and only intended for symbol tables that
180// live across a large number of compiles.
181//
182void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
183{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000184 tLevel::iterator it;
185 for (it = level.begin(); it != level.end(); ++it) {
186 if ((*it).second->isFunction()) {
187 TFunction* function = static_cast<TFunction*>((*it).second);
188 if (function->getName() == name)
189 function->relateToOperator(op);
190 }
191 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192}
193
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000194//
195// Change all function entries in the table with the non-mangled name
196// to be related to the provided built-in extension. This is a low
197// performance operation, and only intended for symbol tables that
198// live across a large number of compiles.
199//
200void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
201{
202 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
203 if (it->second->isFunction()) {
204 TFunction* function = static_cast<TFunction*>(it->second);
205 if (function->getName() == name)
206 function->relateToExtension(ext);
207 }
208 }
209}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210
211TSymbol::TSymbol(const TSymbol& copyOf)
212{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000213 name = NewPoolTString(copyOf.name->c_str());
214 uniqueId = copyOf.uniqueId;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215}
216
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000217TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope)
218{
219 int level = currentLevel();
220 TSymbol *symbol;
221
222 do
223 {
224 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
225 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
226
227 symbol = table[level]->find(name);
228 }
229 while (symbol == 0 && --level >= 0);
230
231 if (builtIn)
232 *builtIn = (level <= LAST_BUILTIN_LEVEL);
233 if (sameScope)
234 *sameScope = (level == currentLevel());
235
236 return symbol;
237}
238
239TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion)
240{
241 for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
242 {
243 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
244 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
245
246 TSymbol *symbol = table[level]->find(name);
247
248 if (symbol)
249 return symbol;
250 }
251
252 return 0;
253}