blob: ffc44874a0c33e27c6a8da9d7db527e57ef7a94a [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),
Jamie Madill98493dd2013-07-08 14:39:03 -040026 interfaceBlock(0), structure(0)
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +000027{
28 if (p.userDef) {
29 structure = p.userDef->getStruct();
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +000030 }
31}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032
33//
34// Recursively generate mangled names.
35//
Jamie Madill98493dd2013-07-08 14:39:03 -040036TString TType::buildMangledName() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000037{
Jamie Madill98493dd2013-07-08 14:39:03 -040038 TString mangledName;
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;
Nicolas Capensda075352013-06-24 16:02:56 -040049 case EbtSampler3D: mangledName += "s3"; break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000050 case EbtSamplerCube: mangledName += "sC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040051 case EbtSampler2DArray: mangledName += "s2a"; break;
Nicolas Capens344e7142013-06-24 15:39:21 -040052 case EbtISampler2D: mangledName += "is2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040053 case EbtISampler3D: mangledName += "is3"; break;
Nicolas Capens344e7142013-06-24 15:39:21 -040054 case EbtISamplerCube: mangledName += "isC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040055 case EbtISampler2DArray: mangledName += "is2a"; break;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -040056 case EbtUSampler2D: mangledName += "us2"; break;
Nicolas Capensda075352013-06-24 16:02:56 -040057 case EbtUSampler3D: mangledName += "us3"; break;
Nicolas Capens2ffe0bb2013-06-24 15:56:19 -040058 case EbtUSamplerCube: mangledName += "usC"; break;
Nicolas Capens8772b582013-06-24 16:14:19 -040059 case EbtUSampler2DArray: mangledName += "us2a"; break;
Jamie Madill98493dd2013-07-08 14:39:03 -040060 case EbtStruct: mangledName += structure->mangledName(); break;
61 case EbtInterfaceBlock: mangledName += interfaceBlock->mangledName(); break;
62 default: break;
daniel@transgaming.com0578f812010-05-17 09:58:39 +000063 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000064
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +000065 if (isMatrix())
66 {
67 mangledName += static_cast<char>('0' + getCols());
68 mangledName += static_cast<char>('x');
69 mangledName += static_cast<char>('0' + getRows());
70 }
71 else
72 {
73 mangledName += static_cast<char>('0' + getNominalSize());
74 }
Jamie Madill98493dd2013-07-08 14:39:03 -040075
daniel@transgaming.com0578f812010-05-17 09:58:39 +000076 if (isArray()) {
77 char buf[20];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +000078 snprintf(buf, sizeof(buf), "%d", arraySize);
daniel@transgaming.com0578f812010-05-17 09:58:39 +000079 mangledName += '[';
80 mangledName += buf;
81 mangledName += ']';
82 }
Jamie Madill98493dd2013-07-08 14:39:03 -040083 return mangledName;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084}
85
Jamie Madill94bf7f22013-07-08 13:31:15 -040086size_t TType::getObjectSize() const
87{
88 size_t totalSize;
89
90 if (getBasicType() == EbtStruct)
Jamie Madill98493dd2013-07-08 14:39:03 -040091 totalSize = structure->objectSize();
Jamie Madill94bf7f22013-07-08 13:31:15 -040092 else
93 totalSize = primarySize * secondarySize;
94
95 if (isArray()) {
Jamie Madill18464b52013-07-08 14:01:55 -040096 size_t arraySize = getArraySize();
Jamie Madill94bf7f22013-07-08 13:31:15 -040097 if (arraySize > INT_MAX / totalSize)
98 totalSize = INT_MAX;
99 else
100 totalSize *= arraySize;
101 }
102
103 return totalSize;
104}
105
Jamie Madill98493dd2013-07-08 14:39:03 -0400106bool TStructure::containsArrays() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107{
Jamie Madill98493dd2013-07-08 14:39:03 -0400108 for (size_t i = 0; i < mFields->size(); ++i) {
109 const TType* fieldType = (*mFields)[i]->type();
110 if (fieldType->isArray() || fieldType->isStructureContainingArrays())
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000111 return true;
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000112 }
daniel@transgaming.com8abd0b72012-09-27 17:46:07 +0000113 return false;
114}
115
Jamie Madill98493dd2013-07-08 14:39:03 -0400116TString TFieldListCollection::buildMangledName() const
117{
118 TString mangledName(mangledNamePrefix());
119 mangledName += *mName;
120 for (size_t i = 0; i < mFields->size(); ++i) {
121 mangledName += '-';
122 mangledName += (*mFields)[i]->type()->getMangledName();
123 }
124 return mangledName;
125}
126
127size_t TFieldListCollection::calculateObjectSize() const
128{
129 size_t size = 0;
130 for (size_t i = 0; i < mFields->size(); ++i) {
131 size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
132 if (fieldSize > INT_MAX - size)
133 size = INT_MAX;
134 else
135 size += fieldSize;
136 }
137 return size;
138}
139
140int TStructure::calculateDeepestNesting() const
141{
142 int maxNesting = 0;
143 for (size_t i = 0; i < mFields->size(); ++i) {
144 maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
145 }
146 return 1 + maxNesting;
147}
148
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150// Functions have buried pointers to delete.
151//
152TFunction::~TFunction()
153{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000154 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
155 delete (*i).type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156}
157
158//
159// Symbol table levels are a map of pointers to symbols that have to be deleted.
160//
161TSymbolTableLevel::~TSymbolTableLevel()
162{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000163 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
164 delete (*it).second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165}
166
167//
168// Change all function entries in the table with the non-mangled name
169// to be related to the provided built-in operation. This is a low
170// performance operation, and only intended for symbol tables that
171// live across a large number of compiles.
172//
173void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
174{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000175 tLevel::iterator it;
176 for (it = level.begin(); it != level.end(); ++it) {
177 if ((*it).second->isFunction()) {
178 TFunction* function = static_cast<TFunction*>((*it).second);
179 if (function->getName() == name)
180 function->relateToOperator(op);
181 }
182 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183}
184
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000185//
186// Change all function entries in the table with the non-mangled name
187// to be related to the provided built-in extension. This is a low
188// performance operation, and only intended for symbol tables that
189// live across a large number of compiles.
190//
191void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
192{
193 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
Jamie Madill2aeb26a2013-07-08 14:02:55 -0400194 TSymbol* symbol = it->second;
195 if (symbol->getName() == name) {
196 symbol->relateToExtension(ext);
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000197 }
198 }
199}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200
201TSymbol::TSymbol(const TSymbol& copyOf)
202{
daniel@transgaming.com0578f812010-05-17 09:58:39 +0000203 name = NewPoolTString(copyOf.name->c_str());
204 uniqueId = copyOf.uniqueId;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205}
206
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000207TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope)
208{
209 int level = currentLevel();
210 TSymbol *symbol;
211
212 do
213 {
214 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
215 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
216
217 symbol = table[level]->find(name);
218 }
219 while (symbol == 0 && --level >= 0);
220
221 if (builtIn)
222 *builtIn = (level <= LAST_BUILTIN_LEVEL);
223 if (sameScope)
224 *sameScope = (level == currentLevel());
225
226 return symbol;
227}
228
229TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion)
230{
231 for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
232 {
233 if (level == ESSL3_BUILTINS && shaderVersion != 300) level--;
234 if (level == ESSL1_BUILTINS && shaderVersion != 100) level--;
235
236 TSymbol *symbol = table[level]->find(name);
237
238 if (symbol)
239 return symbol;
240 }
241
242 return 0;
243}