blob: 74fae23de0f71a1cef18798c151dea8c7b93e2fe [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 Madilld7b1ab52016-12-12 14:42:19 -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 Etuahoe5fe7aa2018-01-29 12:06:11 +020016#include <algorithm>
17#include <set>
18
Olli Etuaho29bda812018-01-26 17:37:36 +020019#include "angle_gl.h"
Olli Etuaho391bda22018-02-23 11:43:14 +020020#include "compiler/translator/BuiltIn_autogen.h"
Olli Etuaho2d8e4322018-01-22 14:12:46 +020021#include "compiler/translator/ImmutableString.h"
Olli Etuaho01d0ad02017-01-22 14:51:23 -080022#include "compiler/translator/IntermNode.h"
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020023#include "compiler/translator/StaticType.h"
kbr@chromium.org476541f2011-10-27 21:14:51 +000024
Jamie Madill45bcc782016-11-07 13:58:48 -050025namespace sh
26{
27
Olli Etuahodd21ecf2018-01-10 12:42:09 +020028class TSymbolTable::TSymbolTableLevel
29{
30 public:
31 TSymbolTableLevel() : mGlobalInvariant(false) {}
Olli Etuahodd21ecf2018-01-10 12:42:09 +020032
33 bool insert(TSymbol *symbol);
34
35 // Insert a function using its unmangled name as the key.
Olli Etuahob92f92a2018-02-15 19:14:59 +020036 void insertUnmangled(TFunction *function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +020037
Olli Etuahofbb1c792018-01-19 16:26:59 +020038 TSymbol *find(const ImmutableString &name) const;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020039
Olli Etuahodefe3932018-02-13 11:56:09 +020040 void addInvariantVarying(const ImmutableString &name) { mInvariantVaryings.insert(name); }
Olli Etuahodd21ecf2018-01-10 12:42:09 +020041
Olli Etuahodefe3932018-02-13 11:56:09 +020042 bool isVaryingInvariant(const ImmutableString &name)
Olli Etuahodd21ecf2018-01-10 12:42:09 +020043 {
44 return (mGlobalInvariant || mInvariantVaryings.count(name) > 0);
45 }
46
47 void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
48
Olli Etuahodd21ecf2018-01-10 12:42:09 +020049 private:
Olli Etuahofbb1c792018-01-19 16:26:59 +020050 using tLevel = TUnorderedMap<ImmutableString,
51 TSymbol *,
52 ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020053 using tLevelPair = const tLevel::value_type;
54 using tInsertResult = std::pair<tLevel::iterator, bool>;
55
56 tLevel level;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020057
Olli Etuahodefe3932018-02-13 11:56:09 +020058 std::set<ImmutableString> mInvariantVaryings;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020059 bool mGlobalInvariant;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020060};
61
62class TSymbolTable::TSymbolTableBuiltInLevel
63{
64 public:
65 TSymbolTableBuiltInLevel() = default;
66
Olli Etuaho065aa862018-02-22 15:30:27 +020067 void insert(const TSymbol *symbol);
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020068 const TSymbol *find(const ImmutableString &name) const;
69
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020070 private:
71 using tLevel = TUnorderedMap<ImmutableString,
72 const TSymbol *,
73 ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
74 using tLevelPair = const tLevel::value_type;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020075 tLevel mLevel;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020076};
77
Olli Etuahodd21ecf2018-01-10 12:42:09 +020078bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
Jamie Madillbfa91f42014-06-05 15:45:18 -040079{
Jamie Madillbfa91f42014-06-05 15:45:18 -040080 // returning true means symbol was added to the table
Nicolas Capensadfffe42014-06-17 02:13:36 -040081 tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
Jamie Madillbfa91f42014-06-05 15:45:18 -040082 return result.second;
83}
84
Olli Etuahob92f92a2018-02-15 19:14:59 +020085void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
Olli Etuahob2983c92015-03-18 14:02:46 +020086{
Olli Etuahob92f92a2018-02-15 19:14:59 +020087 level.insert(tLevelPair(function->name(), function));
Olli Etuahob2983c92015-03-18 14:02:46 +020088}
89
Olli Etuahofbb1c792018-01-19 16:26:59 +020090TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const
Jamie Madillbfa91f42014-06-05 15:45:18 -040091{
92 tLevel::const_iterator it = level.find(name);
93 if (it == level.end())
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020094 return nullptr;
Jamie Madillbfa91f42014-06-05 15:45:18 -040095 else
96 return (*it).second;
97}
98
Olli Etuaho065aa862018-02-22 15:30:27 +020099void TSymbolTable::TSymbolTableBuiltInLevel::insert(const TSymbol *symbol)
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200100{
Olli Etuaho065aa862018-02-22 15:30:27 +0200101 mLevel.insert(tLevelPair(symbol->getMangledName(), symbol));
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200102}
103
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200104const TSymbol *TSymbolTable::TSymbolTableBuiltInLevel::find(const ImmutableString &name) const
105{
106 tLevel::const_iterator it = mLevel.find(name);
107 if (it == mLevel.end())
108 return nullptr;
109 else
110 return (*it).second;
111}
112
Olli Etuaho391bda22018-02-23 11:43:14 +0200113TSymbolTable::TSymbolTable() : mUniqueIdCounter(0), mShaderType(GL_FRAGMENT_SHADER)
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200114{
115}
116
117TSymbolTable::~TSymbolTable() = default;
118
Olli Etuaho437664b2018-02-28 15:38:14 +0200119bool TSymbolTable::isEmpty() const
120{
121 return mTable.empty();
122}
123
124bool TSymbolTable::atGlobalLevel() const
125{
126 return mTable.size() == 1u;
127}
128
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200129void TSymbolTable::pushBuiltInLevel()
130{
131 mBuiltInTable.push_back(
132 std::unique_ptr<TSymbolTableBuiltInLevel>(new TSymbolTableBuiltInLevel));
133}
134
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200135void TSymbolTable::push()
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000136{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200137 mTable.push_back(std::unique_ptr<TSymbolTableLevel>(new TSymbolTableLevel));
138 mPrecisionStack.push_back(std::unique_ptr<PrecisionStackLevel>(new PrecisionStackLevel));
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200139}
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000140
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200141void TSymbolTable::pop()
142{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200143 mTable.pop_back();
144 mPrecisionStack.pop_back();
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200145}
146
Olli Etuaho7c8567a2018-02-20 15:44:07 +0200147const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration(
Olli Etuahofbb1c792018-01-19 16:26:59 +0200148 const ImmutableString &mangledName,
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200149 bool *hadPrototypeDeclarationOut)
150{
151 TFunction *function = findUserDefinedFunction(mangledName);
152 *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration();
153 function->setHasPrototypeDeclaration();
154 return function;
155}
156
Olli Etuaho7c8567a2018-02-20 15:44:07 +0200157const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function,
158 bool *wasDefinedOut)
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200159{
160 TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName());
161 ASSERT(firstDeclaration);
162 // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as
163 // it would have just been put in the symbol table. Otherwise, we're looking up an earlier
164 // occurance.
165 if (function != firstDeclaration)
166 {
Olli Etuaho029e8ca2018-02-16 14:06:49 +0200167 // The previous declaration should have the same parameters as the function definition
168 // (parameter names may differ).
169 firstDeclaration->shareParameters(*function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200170 }
171
172 *wasDefinedOut = firstDeclaration->isDefined();
173 firstDeclaration->setDefined();
174 return firstDeclaration;
175}
176
Olli Etuahofbb1c792018-01-19 16:26:59 +0200177const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200178{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200179 int userDefinedLevel = static_cast<int>(mTable.size()) - 1;
180 while (userDefinedLevel >= 0)
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000181 {
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200182 const TSymbol *symbol = mTable[userDefinedLevel]->find(name);
183 if (symbol)
184 {
185 return symbol;
186 }
187 userDefinedLevel--;
188 }
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000189
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200190 return findBuiltIn(name, shaderVersion, false);
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000191}
192
Olli Etuahofbb1c792018-01-19 16:26:59 +0200193TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200194{
195 // User-defined functions are always declared at the global level.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200196 ASSERT(!mTable.empty());
197 return static_cast<TFunction *>(mTable[0]->find(name));
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200198}
199
Olli Etuahofbb1c792018-01-19 16:26:59 +0200200const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const
Zhenyao Mod7490962016-11-09 15:49:51 -0800201{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200202 ASSERT(!mTable.empty());
203 return mTable[0]->find(name);
Zhenyao Mod7490962016-11-09 15:49:51 -0800204}
205
Olli Etuahofbb1c792018-01-19 16:26:59 +0200206const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name, int shaderVersion) const
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000207{
Olli Etuaho977ee7e2017-07-21 11:38:27 +0300208 return findBuiltIn(name, shaderVersion, false);
209}
210
Olli Etuahofbb1c792018-01-19 16:26:59 +0200211const TSymbol *TSymbolTable::findBuiltIn(const ImmutableString &name,
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200212 int shaderVersion,
213 bool includeGLSLBuiltins) const
Olli Etuaho977ee7e2017-07-21 11:38:27 +0300214{
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000215 for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
216 {
Olli Etuaho977ee7e2017-07-21 11:38:27 +0300217 if (level == GLSL_BUILTINS && !includeGLSLBuiltins)
218 level--;
Martin Radeve93d24e2016-07-28 12:06:05 +0300219 if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
220 level--;
221 if (level == ESSL3_BUILTINS && shaderVersion < 300)
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700222 level--;
223 if (level == ESSL1_BUILTINS && shaderVersion != 100)
224 level--;
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000225
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200226 const TSymbol *symbol = mBuiltInTable[level]->find(name);
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000227
228 if (symbol)
229 return symbol;
230 }
231
Olli Etuaho977ee7e2017-07-21 11:38:27 +0300232 return nullptr;
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000233}
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400234
Nicolas Capensf3cc4ae2015-02-23 13:51:25 -0500235
Olli Etuaho437664b2018-02-28 15:38:14 +0200236bool TSymbolTable::declare(TSymbol *symbol)
Olli Etuaho0f684632017-07-13 12:42:15 +0300237{
Olli Etuaho437664b2018-02-28 15:38:14 +0200238 ASSERT(!mTable.empty());
239 ASSERT(symbol->symbolType() == SymbolType::UserDefined);
240 ASSERT(!symbol->isFunction());
241 return mTable.back()->insert(symbol);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800242}
243
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200244void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName)
245{
Olli Etuaho437664b2018-02-28 15:38:14 +0200246 ASSERT(!mTable.empty());
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200247 if (insertUnmangledName)
248 {
249 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200250 mTable[0]->insertUnmangled(function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200251 }
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200252 mTable[0]->insert(function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200253}
254
Olli Etuaho437664b2018-02-28 15:38:14 +0200255void TSymbolTable::insertBuiltIn(ESymbolLevel level, const TSymbol *symbol)
Olli Etuaho195be942017-12-04 23:40:14 +0200256{
Olli Etuaho437664b2018-02-28 15:38:14 +0200257 ASSERT(symbol);
258 ASSERT(level <= LAST_BUILTIN_LEVEL);
Olli Etuaho195be942017-12-04 23:40:14 +0200259
Olli Etuaho437664b2018-02-28 15:38:14 +0200260 mBuiltInTable[level]->insert(symbol);
Olli Etuaho0f684632017-07-13 12:42:15 +0300261}
262
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200263void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec)
264{
265 int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1;
266 // Uses map operator [], overwrites the current value
267 (*mPrecisionStack[indexOfLastElement])[type] = prec;
268}
269
Zhenyao Moe740add2014-07-18 17:01:01 -0700270TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700271{
272 if (!SupportsPrecision(type))
273 return EbpUndefined;
274
275 // unsigned integers use the same precision as signed
276 TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
277
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200278 int level = static_cast<int>(mPrecisionStack.size()) - 1;
279 ASSERT(level >= 0); // Just to be safe. Should not happen.
Olli Etuaho183d7e22015-11-20 15:59:09 +0200280 // If we dont find anything we return this. Some types don't have predefined default precision.
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700281 TPrecision prec = EbpUndefined;
282 while (level >= 0)
283 {
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200284 PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType);
285 if (it != mPrecisionStack[level]->end())
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700286 {
287 prec = (*it).second;
288 break;
289 }
290 level--;
291 }
292 return prec;
293}
Jamie Madill45bcc782016-11-07 13:58:48 -0500294
Olli Etuahodefe3932018-02-13 11:56:09 +0200295void TSymbolTable::addInvariantVarying(const ImmutableString &originalName)
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200296{
297 ASSERT(atGlobalLevel());
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200298 mTable.back()->addInvariantVarying(originalName);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200299}
300
Olli Etuahodefe3932018-02-13 11:56:09 +0200301bool TSymbolTable::isVaryingInvariant(const ImmutableString &originalName) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200302{
303 ASSERT(atGlobalLevel());
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200304 return mTable.back()->isVaryingInvariant(originalName);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200305}
306
307void TSymbolTable::setGlobalInvariant(bool invariant)
308{
309 ASSERT(atGlobalLevel());
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200310 mTable.back()->setGlobalInvariant(invariant);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200311}
312
Olli Etuaho5d69db12017-11-24 16:51:15 +0200313void TSymbolTable::clearCompilationResults()
314{
Olli Etuaho391bda22018-02-23 11:43:14 +0200315 mUniqueIdCounter = kLastBuiltInId + 1;
Olli Etuaho5d69db12017-11-24 16:51:15 +0200316
317 // User-defined scopes should have already been cleared when the compilation finished.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200318 ASSERT(mTable.size() == 0u);
Olli Etuaho5d69db12017-11-24 16:51:15 +0200319}
320
321int TSymbolTable::nextUniqueIdValue()
322{
323 ASSERT(mUniqueIdCounter < std::numeric_limits<int>::max());
324 return ++mUniqueIdCounter;
325}
326
Olli Etuaho29bda812018-01-26 17:37:36 +0200327void TSymbolTable::initializeBuiltIns(sh::GLenum type,
328 ShShaderSpec spec,
329 const ShBuiltInResources &resources)
330{
Olli Etuaho065aa862018-02-22 15:30:27 +0200331 mShaderType = type;
332
Olli Etuaho29bda812018-01-26 17:37:36 +0200333 ASSERT(isEmpty());
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200334 pushBuiltInLevel(); // COMMON_BUILTINS
335 pushBuiltInLevel(); // ESSL1_BUILTINS
336 pushBuiltInLevel(); // ESSL3_BUILTINS
337 pushBuiltInLevel(); // ESSL3_1_BUILTINS
338 pushBuiltInLevel(); // GLSL_BUILTINS
339
340 // We need just one precision stack level for predefined precisions.
341 mPrecisionStack.push_back(std::unique_ptr<PrecisionStackLevel>(new PrecisionStackLevel));
Olli Etuaho29bda812018-01-26 17:37:36 +0200342
343 switch (type)
344 {
345 case GL_FRAGMENT_SHADER:
346 setDefaultPrecision(EbtInt, EbpMedium);
347 break;
348 case GL_VERTEX_SHADER:
349 case GL_COMPUTE_SHADER:
350 case GL_GEOMETRY_SHADER_EXT:
351 setDefaultPrecision(EbtInt, EbpHigh);
352 setDefaultPrecision(EbtFloat, EbpHigh);
353 break;
354 default:
355 UNREACHABLE();
356 }
357 // Set defaults for sampler types that have default precision, even those that are
358 // only available if an extension exists.
359 // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
360 initSamplerDefaultPrecision(EbtSampler2D);
361 initSamplerDefaultPrecision(EbtSamplerCube);
362 // SamplerExternalOES is specified in the extension to have default precision.
363 initSamplerDefaultPrecision(EbtSamplerExternalOES);
364 // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
365 initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
366 // It isn't specified whether Sampler2DRect has default precision.
367 initSamplerDefaultPrecision(EbtSampler2DRect);
368
369 setDefaultPrecision(EbtAtomicCounter, EbpHigh);
370
Olli Etuaho140152e2018-02-08 14:46:44 +0200371 insertBuiltInFunctions(type);
Olli Etuaho391bda22018-02-23 11:43:14 +0200372 insertBuiltInVariables(type, spec, resources);
373 mUniqueIdCounter = kLastBuiltInId + 1;
Olli Etuaho29bda812018-01-26 17:37:36 +0200374}
375
376void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType)
377{
Olli Etuahoe600c0a2018-03-02 11:23:29 +0200378 ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd);
Olli Etuaho29bda812018-01-26 17:37:36 +0200379 setDefaultPrecision(samplerType, EbpLow);
380}
381
Jamie Madill45bcc782016-11-07 13:58:48 -0500382} // namespace sh