blob: 73e40d88c41b2ae1477697bf67543de493416bde [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//
Olli Etuaho0f684632017-07-13 12:42:15 +03006// Symbol table for parsing. The design principles and most of the functionality are documented in
7// the header file.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00008//
9
apatrick@chromium.orge057c5d2012-01-26 19:18:24 +000010#if defined(_MSC_VER)
Jamie Madillb980c562018-11-27 11:34:27 -050011# pragma warning(disable : 4718)
apatrick@chromium.orge057c5d2012-01-26 19:18:24 +000012#endif
13
Geoff Lang17732822013-08-29 13:46:49 -040014#include "compiler/translator/SymbolTable.h"
Olli Etuaho01d0ad02017-01-22 14:51:23 -080015
Olli Etuaho29bda812018-01-26 17:37:36 +020016#include "angle_gl.h"
Olli Etuaho2d8e4322018-01-22 14:12:46 +020017#include "compiler/translator/ImmutableString.h"
Olli Etuaho01d0ad02017-01-22 14:51:23 -080018#include "compiler/translator/IntermNode.h"
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020019#include "compiler/translator/StaticType.h"
kbr@chromium.org476541f2011-10-27 21:14:51 +000020
Jamie Madill45bcc782016-11-07 13:58:48 -050021namespace sh
22{
23
Olli Etuahodd21ecf2018-01-10 12:42:09 +020024class TSymbolTable::TSymbolTableLevel
25{
26 public:
Jamie Madill71a151f2018-06-26 16:07:42 -040027 TSymbolTableLevel() = default;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020028
29 bool insert(TSymbol *symbol);
30
31 // Insert a function using its unmangled name as the key.
Olli Etuahob92f92a2018-02-15 19:14:59 +020032 void insertUnmangled(TFunction *function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +020033
Olli Etuahofbb1c792018-01-19 16:26:59 +020034 TSymbol *find(const ImmutableString &name) const;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020035
Olli Etuahodd21ecf2018-01-10 12:42:09 +020036 private:
Olli Etuahofbb1c792018-01-19 16:26:59 +020037 using tLevel = TUnorderedMap<ImmutableString,
38 TSymbol *,
39 ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020040 using tLevelPair = const tLevel::value_type;
41 using tInsertResult = std::pair<tLevel::iterator, bool>;
42
43 tLevel level;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020044};
45
Olli Etuahodd21ecf2018-01-10 12:42:09 +020046bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
Jamie Madillbfa91f42014-06-05 15:45:18 -040047{
Jamie Madillbfa91f42014-06-05 15:45:18 -040048 // returning true means symbol was added to the table
Nicolas Capensadfffe42014-06-17 02:13:36 -040049 tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
Jamie Madillbfa91f42014-06-05 15:45:18 -040050 return result.second;
51}
52
Olli Etuahob92f92a2018-02-15 19:14:59 +020053void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
Olli Etuahob2983c92015-03-18 14:02:46 +020054{
Olli Etuahob92f92a2018-02-15 19:14:59 +020055 level.insert(tLevelPair(function->name(), function));
Olli Etuahob2983c92015-03-18 14:02:46 +020056}
57
Olli Etuahofbb1c792018-01-19 16:26:59 +020058TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const
Jamie Madillbfa91f42014-06-05 15:45:18 -040059{
60 tLevel::const_iterator it = level.find(name);
61 if (it == level.end())
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020062 return nullptr;
Jamie Madillbfa91f42014-06-05 15:45:18 -040063 else
64 return (*it).second;
65}
66
Olli Etuaho94bbed12018-03-20 14:44:53 +020067TSymbolTable::TSymbolTable()
Olli Etuaho76b2c382018-03-19 15:51:29 +020068 : mGlobalInvariant(false),
69 mUniqueIdCounter(0),
70 mShaderType(GL_FRAGMENT_SHADER),
71 mGlInVariableWithArraySize(nullptr)
Jamie Madillb980c562018-11-27 11:34:27 -050072{}
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020073
74TSymbolTable::~TSymbolTable() = default;
75
Olli Etuaho437664b2018-02-28 15:38:14 +020076bool TSymbolTable::isEmpty() const
77{
78 return mTable.empty();
79}
80
81bool TSymbolTable::atGlobalLevel() const
82{
83 return mTable.size() == 1u;
84}
85
Olli Etuahodd21ecf2018-01-10 12:42:09 +020086void TSymbolTable::push()
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +000087{
Jamie Madill71a151f2018-06-26 16:07:42 -040088 mTable.emplace_back(new TSymbolTableLevel);
89 mPrecisionStack.emplace_back(new PrecisionStackLevel);
Olli Etuahodd21ecf2018-01-10 12:42:09 +020090}
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +000091
Olli Etuahodd21ecf2018-01-10 12:42:09 +020092void TSymbolTable::pop()
93{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020094 mTable.pop_back();
95 mPrecisionStack.pop_back();
Olli Etuahodd21ecf2018-01-10 12:42:09 +020096}
97
Olli Etuaho7c8567a2018-02-20 15:44:07 +020098const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration(
Olli Etuahofbb1c792018-01-19 16:26:59 +020099 const ImmutableString &mangledName,
Jamie Madill71a151f2018-06-26 16:07:42 -0400100 bool *hadPrototypeDeclarationOut) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200101{
102 TFunction *function = findUserDefinedFunction(mangledName);
103 *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration();
104 function->setHasPrototypeDeclaration();
105 return function;
106}
107
Olli Etuaho7c8567a2018-02-20 15:44:07 +0200108const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function,
Jamie Madill71a151f2018-06-26 16:07:42 -0400109 bool *wasDefinedOut) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200110{
111 TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName());
112 ASSERT(firstDeclaration);
113 // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as
114 // it would have just been put in the symbol table. Otherwise, we're looking up an earlier
115 // occurance.
116 if (function != firstDeclaration)
117 {
Olli Etuaho029e8ca2018-02-16 14:06:49 +0200118 // The previous declaration should have the same parameters as the function definition
119 // (parameter names may differ).
120 firstDeclaration->shareParameters(*function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200121 }
122
123 *wasDefinedOut = firstDeclaration->isDefined();
124 firstDeclaration->setDefined();
125 return firstDeclaration;
126}
127
Olli Etuaho94bbed12018-03-20 14:44:53 +0200128bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize)
129{
130 if (mGlInVariableWithArraySize)
131 {
132 return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize;
133 }
134 const TInterfaceBlock *glPerVertex = mVar_gl_PerVertex;
135 TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create());
136 glInType->makeArray(inputArraySize);
137 mGlInVariableWithArraySize =
138 new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn,
139 TExtension::EXT_geometry_shader);
140 return true;
141}
142
143TVariable *TSymbolTable::getGlInVariableWithArraySize() const
144{
145 return mGlInVariableWithArraySize;
146}
147
Olli Etuaho59c5b892018-04-03 11:44:50 +0300148const TVariable *TSymbolTable::gl_FragData() const
149{
150 return mVar_gl_FragData;
151}
152
153const TVariable *TSymbolTable::gl_SecondaryFragDataEXT() const
154{
155 return mVar_gl_SecondaryFragDataEXT;
156}
157
Jamie Madillb980c562018-11-27 11:34:27 -0500158TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const TVariable &variable)
159{
160 int id = variable.uniqueId().get();
Olli Etuaho94bbed12018-03-20 14:44:53 +0200161 auto iter = mVariableMetadata.find(id);
162 if (iter == mVariableMetadata.end())
163 {
164 iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
165 }
Olli Etuaho76b2c382018-03-19 15:51:29 +0200166 return &iter->second;
167}
168
169void TSymbolTable::markStaticWrite(const TVariable &variable)
170{
Jamie Madillb980c562018-11-27 11:34:27 -0500171 auto metadata = getOrCreateVariableMetadata(variable);
Olli Etuaho76b2c382018-03-19 15:51:29 +0200172 metadata->staticWrite = true;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200173}
174
175void TSymbolTable::markStaticRead(const TVariable &variable)
176{
Jamie Madillb980c562018-11-27 11:34:27 -0500177 auto metadata = getOrCreateVariableMetadata(variable);
Olli Etuaho76b2c382018-03-19 15:51:29 +0200178 metadata->staticRead = true;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200179}
180
181bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const
182{
183 ASSERT(!variable.getConstPointer());
184 int id = variable.uniqueId().get();
185 auto iter = mVariableMetadata.find(id);
Olli Etuaho76b2c382018-03-19 15:51:29 +0200186 return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite);
187}
188
189void TSymbolTable::addInvariantVarying(const TVariable &variable)
190{
191 ASSERT(atGlobalLevel());
Jamie Madillb980c562018-11-27 11:34:27 -0500192 auto metadata = getOrCreateVariableMetadata(variable);
Olli Etuaho76b2c382018-03-19 15:51:29 +0200193 metadata->invariant = true;
194}
195
196bool TSymbolTable::isVaryingInvariant(const TVariable &variable) const
197{
198 ASSERT(atGlobalLevel());
199 if (mGlobalInvariant)
200 {
201 return true;
202 }
Jamie Madillb980c562018-11-27 11:34:27 -0500203 int id = variable.uniqueId().get();
Olli Etuaho76b2c382018-03-19 15:51:29 +0200204 auto iter = mVariableMetadata.find(id);
205 return iter != mVariableMetadata.end() && iter->second.invariant;
206}
207
208void TSymbolTable::setGlobalInvariant(bool invariant)
209{
210 ASSERT(atGlobalLevel());
211 mGlobalInvariant = invariant;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200212}
213
Olli Etuahofbb1c792018-01-19 16:26:59 +0200214const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200215{
Jamie Madill71a151f2018-06-26 16:07:42 -0400216 const TSymbol *userSymbol = findUserDefined(name);
217 if (userSymbol)
218 {
219 return userSymbol;
220 }
221
222 return findBuiltIn(name, shaderVersion);
223}
224
225const TSymbol *TSymbolTable::findUserDefined(const ImmutableString &name) const
226{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200227 int userDefinedLevel = static_cast<int>(mTable.size()) - 1;
228 while (userDefinedLevel >= 0)
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000229 {
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200230 const TSymbol *symbol = mTable[userDefinedLevel]->find(name);
231 if (symbol)
232 {
233 return symbol;
234 }
235 userDefinedLevel--;
236 }
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000237
Jamie Madill71a151f2018-06-26 16:07:42 -0400238 return nullptr;
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000239}
240
Olli Etuahofbb1c792018-01-19 16:26:59 +0200241TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200242{
243 // User-defined functions are always declared at the global level.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200244 ASSERT(!mTable.empty());
245 return static_cast<TFunction *>(mTable[0]->find(name));
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200246}
247
Olli Etuahofbb1c792018-01-19 16:26:59 +0200248const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const
Zhenyao Mod7490962016-11-09 15:49:51 -0800249{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200250 ASSERT(!mTable.empty());
251 return mTable[0]->find(name);
Zhenyao Mod7490962016-11-09 15:49:51 -0800252}
253
Olli Etuaho437664b2018-02-28 15:38:14 +0200254bool TSymbolTable::declare(TSymbol *symbol)
Olli Etuaho0f684632017-07-13 12:42:15 +0300255{
Olli Etuaho437664b2018-02-28 15:38:14 +0200256 ASSERT(!mTable.empty());
257 ASSERT(symbol->symbolType() == SymbolType::UserDefined);
258 ASSERT(!symbol->isFunction());
259 return mTable.back()->insert(symbol);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800260}
261
Jamie Madill71a151f2018-06-26 16:07:42 -0400262bool TSymbolTable::declareInternal(TSymbol *symbol)
263{
264 ASSERT(!mTable.empty());
265 ASSERT(symbol->symbolType() == SymbolType::AngleInternal);
266 ASSERT(!symbol->isFunction());
267 return mTable.back()->insert(symbol);
268}
269
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200270void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName)
271{
Olli Etuaho437664b2018-02-28 15:38:14 +0200272 ASSERT(!mTable.empty());
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200273 if (insertUnmangledName)
274 {
275 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200276 mTable[0]->insertUnmangled(function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200277 }
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200278 mTable[0]->insert(function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200279}
280
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200281void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec)
282{
283 int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1;
284 // Uses map operator [], overwrites the current value
285 (*mPrecisionStack[indexOfLastElement])[type] = prec;
286}
287
Zhenyao Moe740add2014-07-18 17:01:01 -0700288TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700289{
290 if (!SupportsPrecision(type))
291 return EbpUndefined;
292
293 // unsigned integers use the same precision as signed
294 TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
295
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200296 int level = static_cast<int>(mPrecisionStack.size()) - 1;
297 ASSERT(level >= 0); // Just to be safe. Should not happen.
Olli Etuaho183d7e22015-11-20 15:59:09 +0200298 // If we dont find anything we return this. Some types don't have predefined default precision.
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700299 TPrecision prec = EbpUndefined;
300 while (level >= 0)
301 {
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200302 PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType);
303 if (it != mPrecisionStack[level]->end())
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700304 {
305 prec = (*it).second;
306 break;
307 }
308 level--;
309 }
310 return prec;
311}
Jamie Madill45bcc782016-11-07 13:58:48 -0500312
Olli Etuaho5d69db12017-11-24 16:51:15 +0200313void TSymbolTable::clearCompilationResults()
314{
Olli Etuaho76b2c382018-03-19 15:51:29 +0200315 mGlobalInvariant = false;
Olli Etuaho391bda22018-02-23 11:43:14 +0200316 mUniqueIdCounter = kLastBuiltInId + 1;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200317 mVariableMetadata.clear();
318 mGlInVariableWithArraySize = nullptr;
Olli Etuaho5d69db12017-11-24 16:51:15 +0200319
320 // User-defined scopes should have already been cleared when the compilation finished.
Jamie Madill71a151f2018-06-26 16:07:42 -0400321 ASSERT(mTable.empty());
Olli Etuaho5d69db12017-11-24 16:51:15 +0200322}
323
324int TSymbolTable::nextUniqueIdValue()
325{
326 ASSERT(mUniqueIdCounter < std::numeric_limits<int>::max());
327 return ++mUniqueIdCounter;
328}
329
Olli Etuaho29bda812018-01-26 17:37:36 +0200330void TSymbolTable::initializeBuiltIns(sh::GLenum type,
331 ShShaderSpec spec,
332 const ShBuiltInResources &resources)
333{
Olli Etuaho065aa862018-02-22 15:30:27 +0200334 mShaderType = type;
Olli Etuahob391ec42018-03-12 17:04:59 +0200335 mResources = resources;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200336
337 // We need just one precision stack level for predefined precisions.
Jamie Madill71a151f2018-06-26 16:07:42 -0400338 mPrecisionStack.emplace_back(new PrecisionStackLevel);
Olli Etuaho29bda812018-01-26 17:37:36 +0200339
340 switch (type)
341 {
342 case GL_FRAGMENT_SHADER:
343 setDefaultPrecision(EbtInt, EbpMedium);
344 break;
345 case GL_VERTEX_SHADER:
346 case GL_COMPUTE_SHADER:
347 case GL_GEOMETRY_SHADER_EXT:
348 setDefaultPrecision(EbtInt, EbpHigh);
349 setDefaultPrecision(EbtFloat, EbpHigh);
350 break;
351 default:
352 UNREACHABLE();
353 }
354 // Set defaults for sampler types that have default precision, even those that are
355 // only available if an extension exists.
356 // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
357 initSamplerDefaultPrecision(EbtSampler2D);
358 initSamplerDefaultPrecision(EbtSamplerCube);
359 // SamplerExternalOES is specified in the extension to have default precision.
360 initSamplerDefaultPrecision(EbtSamplerExternalOES);
361 // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
362 initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
363 // It isn't specified whether Sampler2DRect has default precision.
364 initSamplerDefaultPrecision(EbtSampler2DRect);
365
366 setDefaultPrecision(EbtAtomicCounter, EbpHigh);
367
Olli Etuahob391ec42018-03-12 17:04:59 +0200368 initializeBuiltInVariables(type, spec, resources);
Olli Etuaho391bda22018-02-23 11:43:14 +0200369 mUniqueIdCounter = kLastBuiltInId + 1;
Olli Etuaho29bda812018-01-26 17:37:36 +0200370}
371
372void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType)
373{
Olli Etuahoe600c0a2018-03-02 11:23:29 +0200374 ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd);
Olli Etuaho29bda812018-01-26 17:37:36 +0200375 setDefaultPrecision(samplerType, EbpLow);
376}
377
Jamie Madillb980c562018-11-27 11:34:27 -0500378TSymbolTable::VariableMetadata::VariableMetadata()
379 : staticRead(false), staticWrite(false), invariant(false)
380{}
Jamie Madill45bcc782016-11-07 13:58:48 -0500381} // namespace sh