blob: 028da21151401b5f6245fbf188a3ea6a267873f8 [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
Geoff Lang17732822013-08-29 13:46:49 -040016#include "compiler/translator/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
Jamie Madillbfa91f42014-06-05 15:45:18 -040021int TSymbolTable::uniqueIdCounter = 0;
Nicolas Capensbd10cf52013-06-20 09:51:51 -040022
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024// Functions have buried pointers to delete.
25//
26TFunction::~TFunction()
27{
daniel@transgaming.com0578f812010-05-17 09:58:39 +000028 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
29 delete (*i).type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030}
31
32//
33// Symbol table levels are a map of pointers to symbols that have to be deleted.
34//
35TSymbolTableLevel::~TSymbolTableLevel()
36{
daniel@transgaming.com0578f812010-05-17 09:58:39 +000037 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
38 delete (*it).second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000039}
40
Nicolas Capensadfffe42014-06-17 02:13:36 -040041bool TSymbolTableLevel::insert(TSymbol *symbol)
Jamie Madillbfa91f42014-06-05 15:45:18 -040042{
Nicolas Capensadfffe42014-06-17 02:13:36 -040043 symbol->setUniqueId(TSymbolTable::nextUniqueId());
Jamie Madillbfa91f42014-06-05 15:45:18 -040044
45 // returning true means symbol was added to the table
Nicolas Capensadfffe42014-06-17 02:13:36 -040046 tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
Jamie Madillbfa91f42014-06-05 15:45:18 -040047
48 return result.second;
49}
50
Jamie Madillbfa91f42014-06-05 15:45:18 -040051TSymbol *TSymbolTableLevel::find(const TString &name) const
52{
53 tLevel::const_iterator it = level.find(name);
54 if (it == level.end())
55 return 0;
56 else
57 return (*it).second;
58}
59
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000060//
61// Change all function entries in the table with the non-mangled name
62// to be related to the provided built-in operation. This is a low
63// performance operation, and only intended for symbol tables that
64// live across a large number of compiles.
65//
Zhenyao Mo9eedea02014-05-12 16:02:35 -070066void TSymbolTableLevel::relateToOperator(const char *name, TOperator op)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000067{
Zhenyao Mo9eedea02014-05-12 16:02:35 -070068 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
69 {
70 if ((*it).second->isFunction())
71 {
72 TFunction *function = static_cast<TFunction*>((*it).second);
daniel@transgaming.com0578f812010-05-17 09:58:39 +000073 if (function->getName() == name)
74 function->relateToOperator(op);
75 }
76 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077}
78
alokp@chromium.org8815d7f2010-09-09 17:30:03 +000079//
80// Change all function entries in the table with the non-mangled name
81// to be related to the provided built-in extension. This is a low
82// performance operation, and only intended for symbol tables that
83// live across a large number of compiles.
84//
Zhenyao Mo9eedea02014-05-12 16:02:35 -070085void TSymbolTableLevel::relateToExtension(const char *name, const TString &ext)
alokp@chromium.org8815d7f2010-09-09 17:30:03 +000086{
Zhenyao Mo9eedea02014-05-12 16:02:35 -070087 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
88 {
89 TSymbol *symbol = it->second;
90 if (symbol->getName() == name)
Jamie Madill2aeb26a2013-07-08 14:02:55 -040091 symbol->relateToExtension(ext);
alokp@chromium.org8815d7f2010-09-09 17:30:03 +000092 }
93}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094
Zhenyao Mo9eedea02014-05-12 16:02:35 -070095TSymbol::TSymbol(const TSymbol &copyOf)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096{
daniel@transgaming.com0578f812010-05-17 09:58:39 +000097 name = NewPoolTString(copyOf.name->c_str());
98 uniqueId = copyOf.uniqueId;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099}
100
Zhenyao Moe740add2014-07-18 17:01:01 -0700101TSymbol *TSymbolTable::find(const TString &name, int shaderVersion,
102 bool *builtIn, bool *sameScope) const
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000103{
104 int level = currentLevel();
105 TSymbol *symbol;
106
107 do
108 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700109 if (level == ESSL3_BUILTINS && shaderVersion != 300)
110 level--;
111 if (level == ESSL1_BUILTINS && shaderVersion != 100)
112 level--;
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000113
114 symbol = table[level]->find(name);
115 }
116 while (symbol == 0 && --level >= 0);
117
118 if (builtIn)
119 *builtIn = (level <= LAST_BUILTIN_LEVEL);
120 if (sameScope)
121 *sameScope = (level == currentLevel());
122
123 return symbol;
124}
125
Zhenyao Moe740add2014-07-18 17:01:01 -0700126TSymbol *TSymbolTable::findBuiltIn(
127 const TString &name, int shaderVersion) const
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000128{
129 for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
130 {
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700131 if (level == ESSL3_BUILTINS && shaderVersion != 300)
132 level--;
133 if (level == ESSL1_BUILTINS && shaderVersion != 100)
134 level--;
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000135
136 TSymbol *symbol = table[level]->find(name);
137
138 if (symbol)
139 return symbol;
140 }
141
142 return 0;
143}
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400144
145TSymbolTable::~TSymbolTable()
146{
147 while (table.size() > 0)
148 pop();
149}
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700150
151void TSymbolTable::insertBuiltIn(
152 ESymbolLevel level, TType *rvalue, const char *name,
153 TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5)
154{
155 if (ptype1->getBasicType() == EbtGSampler2D)
156 {
157 bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
158 insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
159 new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
160 insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
161 new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
162 insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
163 new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
164 return;
165 }
166 if (ptype1->getBasicType() == EbtGSampler3D)
167 {
168 bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
169 insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
170 new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
171 insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
172 new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
173 insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
174 new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
175 return;
176 }
177 if (ptype1->getBasicType() == EbtGSamplerCube)
178 {
179 bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
180 insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
181 new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
182 insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
183 new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
184 insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
185 new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
186 return;
187 }
188 if (ptype1->getBasicType() == EbtGSampler2DArray)
189 {
190 bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
191 insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
192 new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
193 insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
194 new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
195 insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
196 new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
197 return;
198 }
199
200 TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
201
202 TType *types[] = {ptype1, ptype2, ptype3, ptype4, ptype5};
203 for (size_t ii = 0; ii < sizeof(types) / sizeof(types[0]); ++ii)
204 {
205 if (types[ii])
206 {
207 TParameter param = {NULL, types[ii]};
208 function->addParameter(param);
209 }
210 }
211
Nicolas Capensadfffe42014-06-17 02:13:36 -0400212 insert(level, function);
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700213}
214
Zhenyao Moe740add2014-07-18 17:01:01 -0700215TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700216{
217 if (!SupportsPrecision(type))
218 return EbpUndefined;
219
220 // unsigned integers use the same precision as signed
221 TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
222
223 int level = static_cast<int>(precisionStack.size()) - 1;
224 assert(level >= 0); // Just to be safe. Should not happen.
225 // If we dont find anything we return this. Should we error check this?
226 TPrecision prec = EbpUndefined;
227 while (level >= 0)
228 {
229 PrecisionStackLevel::iterator it = precisionStack[level]->find(baseType);
230 if (it != precisionStack[level]->end())
231 {
232 prec = (*it).second;
233 break;
234 }
235 level--;
236 }
237 return prec;
238}