blob: 5b8371b193a2dc54c7a7e5bac65fcb181c7681ae [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"
Tobin Ehlise9421b22019-04-08 15:16:56 -060020#include "compiler/translator/util.h"
kbr@chromium.org476541f2011-10-27 21:14:51 +000021
Jamie Madill45bcc782016-11-07 13:58:48 -050022namespace sh
23{
24
Olli Etuahodd21ecf2018-01-10 12:42:09 +020025class TSymbolTable::TSymbolTableLevel
26{
27 public:
Jamie Madill71a151f2018-06-26 16:07:42 -040028 TSymbolTableLevel() = default;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020029
30 bool insert(TSymbol *symbol);
31
32 // Insert a function using its unmangled name as the key.
Olli Etuahob92f92a2018-02-15 19:14:59 +020033 void insertUnmangled(TFunction *function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +020034
Olli Etuahofbb1c792018-01-19 16:26:59 +020035 TSymbol *find(const ImmutableString &name) const;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020036
Olli Etuahodd21ecf2018-01-10 12:42:09 +020037 private:
Olli Etuahofbb1c792018-01-19 16:26:59 +020038 using tLevel = TUnorderedMap<ImmutableString,
39 TSymbol *,
40 ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020041 using tLevelPair = const tLevel::value_type;
42 using tInsertResult = std::pair<tLevel::iterator, bool>;
43
44 tLevel level;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020045};
46
Olli Etuahodd21ecf2018-01-10 12:42:09 +020047bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
Jamie Madillbfa91f42014-06-05 15:45:18 -040048{
Jamie Madillbfa91f42014-06-05 15:45:18 -040049 // returning true means symbol was added to the table
Nicolas Capensadfffe42014-06-17 02:13:36 -040050 tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
Jamie Madillbfa91f42014-06-05 15:45:18 -040051 return result.second;
52}
53
Olli Etuahob92f92a2018-02-15 19:14:59 +020054void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
Olli Etuahob2983c92015-03-18 14:02:46 +020055{
Olli Etuahob92f92a2018-02-15 19:14:59 +020056 level.insert(tLevelPair(function->name(), function));
Olli Etuahob2983c92015-03-18 14:02:46 +020057}
58
Olli Etuahofbb1c792018-01-19 16:26:59 +020059TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const
Jamie Madillbfa91f42014-06-05 15:45:18 -040060{
61 tLevel::const_iterator it = level.find(name);
62 if (it == level.end())
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020063 return nullptr;
Jamie Madillbfa91f42014-06-05 15:45:18 -040064 else
65 return (*it).second;
66}
67
Olli Etuaho94bbed12018-03-20 14:44:53 +020068TSymbolTable::TSymbolTable()
Olli Etuaho76b2c382018-03-19 15:51:29 +020069 : mGlobalInvariant(false),
70 mUniqueIdCounter(0),
71 mShaderType(GL_FRAGMENT_SHADER),
72 mGlInVariableWithArraySize(nullptr)
Jamie Madillb980c562018-11-27 11:34:27 -050073{}
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020074
75TSymbolTable::~TSymbolTable() = default;
76
Olli Etuaho437664b2018-02-28 15:38:14 +020077bool TSymbolTable::isEmpty() const
78{
79 return mTable.empty();
80}
81
82bool TSymbolTable::atGlobalLevel() const
83{
84 return mTable.size() == 1u;
85}
86
Olli Etuahodd21ecf2018-01-10 12:42:09 +020087void TSymbolTable::push()
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +000088{
Jamie Madill71a151f2018-06-26 16:07:42 -040089 mTable.emplace_back(new TSymbolTableLevel);
90 mPrecisionStack.emplace_back(new PrecisionStackLevel);
Olli Etuahodd21ecf2018-01-10 12:42:09 +020091}
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +000092
Olli Etuahodd21ecf2018-01-10 12:42:09 +020093void TSymbolTable::pop()
94{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020095 mTable.pop_back();
96 mPrecisionStack.pop_back();
Olli Etuahodd21ecf2018-01-10 12:42:09 +020097}
98
Olli Etuaho7c8567a2018-02-20 15:44:07 +020099const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration(
Olli Etuahofbb1c792018-01-19 16:26:59 +0200100 const ImmutableString &mangledName,
Jamie Madill71a151f2018-06-26 16:07:42 -0400101 bool *hadPrototypeDeclarationOut) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200102{
103 TFunction *function = findUserDefinedFunction(mangledName);
104 *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration();
105 function->setHasPrototypeDeclaration();
106 return function;
107}
108
Olli Etuaho7c8567a2018-02-20 15:44:07 +0200109const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function,
Jamie Madill71a151f2018-06-26 16:07:42 -0400110 bool *wasDefinedOut) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200111{
112 TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName());
113 ASSERT(firstDeclaration);
114 // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as
115 // it would have just been put in the symbol table. Otherwise, we're looking up an earlier
116 // occurance.
117 if (function != firstDeclaration)
118 {
Olli Etuaho029e8ca2018-02-16 14:06:49 +0200119 // The previous declaration should have the same parameters as the function definition
120 // (parameter names may differ).
121 firstDeclaration->shareParameters(*function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200122 }
123
124 *wasDefinedOut = firstDeclaration->isDefined();
125 firstDeclaration->setDefined();
126 return firstDeclaration;
127}
128
Olli Etuaho94bbed12018-03-20 14:44:53 +0200129bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize)
130{
131 if (mGlInVariableWithArraySize)
132 {
133 return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize;
134 }
135 const TInterfaceBlock *glPerVertex = mVar_gl_PerVertex;
136 TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create());
137 glInType->makeArray(inputArraySize);
138 mGlInVariableWithArraySize =
139 new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn,
140 TExtension::EXT_geometry_shader);
141 return true;
142}
143
144TVariable *TSymbolTable::getGlInVariableWithArraySize() const
145{
146 return mGlInVariableWithArraySize;
147}
148
Olli Etuaho59c5b892018-04-03 11:44:50 +0300149const TVariable *TSymbolTable::gl_FragData() const
150{
151 return mVar_gl_FragData;
152}
153
154const TVariable *TSymbolTable::gl_SecondaryFragDataEXT() const
155{
156 return mVar_gl_SecondaryFragDataEXT;
157}
158
Jamie Madillb980c562018-11-27 11:34:27 -0500159TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const TVariable &variable)
160{
161 int id = variable.uniqueId().get();
Olli Etuaho94bbed12018-03-20 14:44:53 +0200162 auto iter = mVariableMetadata.find(id);
163 if (iter == mVariableMetadata.end())
164 {
165 iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
166 }
Olli Etuaho76b2c382018-03-19 15:51:29 +0200167 return &iter->second;
168}
169
170void TSymbolTable::markStaticWrite(const TVariable &variable)
171{
Jamie Madillb980c562018-11-27 11:34:27 -0500172 auto metadata = getOrCreateVariableMetadata(variable);
Olli Etuaho76b2c382018-03-19 15:51:29 +0200173 metadata->staticWrite = true;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200174}
175
176void TSymbolTable::markStaticRead(const TVariable &variable)
177{
Jamie Madillb980c562018-11-27 11:34:27 -0500178 auto metadata = getOrCreateVariableMetadata(variable);
Olli Etuaho76b2c382018-03-19 15:51:29 +0200179 metadata->staticRead = true;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200180}
181
182bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const
183{
184 ASSERT(!variable.getConstPointer());
185 int id = variable.uniqueId().get();
186 auto iter = mVariableMetadata.find(id);
Olli Etuaho76b2c382018-03-19 15:51:29 +0200187 return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite);
188}
189
190void TSymbolTable::addInvariantVarying(const TVariable &variable)
191{
192 ASSERT(atGlobalLevel());
Jamie Madillb980c562018-11-27 11:34:27 -0500193 auto metadata = getOrCreateVariableMetadata(variable);
Olli Etuaho76b2c382018-03-19 15:51:29 +0200194 metadata->invariant = true;
195}
196
197bool TSymbolTable::isVaryingInvariant(const TVariable &variable) const
198{
199 ASSERT(atGlobalLevel());
Tobin Ehlise9421b22019-04-08 15:16:56 -0600200 if (mGlobalInvariant && (IsShaderOutput(variable.getType().getQualifier())))
Olli Etuaho76b2c382018-03-19 15:51:29 +0200201 {
202 return true;
203 }
Jamie Madillb980c562018-11-27 11:34:27 -0500204 int id = variable.uniqueId().get();
Olli Etuaho76b2c382018-03-19 15:51:29 +0200205 auto iter = mVariableMetadata.find(id);
206 return iter != mVariableMetadata.end() && iter->second.invariant;
207}
208
209void TSymbolTable::setGlobalInvariant(bool invariant)
210{
211 ASSERT(atGlobalLevel());
212 mGlobalInvariant = invariant;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200213}
214
Olli Etuahofbb1c792018-01-19 16:26:59 +0200215const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200216{
Jamie Madill71a151f2018-06-26 16:07:42 -0400217 const TSymbol *userSymbol = findUserDefined(name);
218 if (userSymbol)
219 {
220 return userSymbol;
221 }
222
223 return findBuiltIn(name, shaderVersion);
224}
225
226const TSymbol *TSymbolTable::findUserDefined(const ImmutableString &name) const
227{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200228 int userDefinedLevel = static_cast<int>(mTable.size()) - 1;
229 while (userDefinedLevel >= 0)
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000230 {
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200231 const TSymbol *symbol = mTable[userDefinedLevel]->find(name);
232 if (symbol)
233 {
234 return symbol;
235 }
236 userDefinedLevel--;
237 }
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000238
Jamie Madill71a151f2018-06-26 16:07:42 -0400239 return nullptr;
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000240}
241
Olli Etuahofbb1c792018-01-19 16:26:59 +0200242TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200243{
244 // User-defined functions are always declared at the global level.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200245 ASSERT(!mTable.empty());
246 return static_cast<TFunction *>(mTable[0]->find(name));
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200247}
248
Olli Etuahofbb1c792018-01-19 16:26:59 +0200249const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const
Zhenyao Mod7490962016-11-09 15:49:51 -0800250{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200251 ASSERT(!mTable.empty());
252 return mTable[0]->find(name);
Zhenyao Mod7490962016-11-09 15:49:51 -0800253}
254
Olli Etuaho437664b2018-02-28 15:38:14 +0200255bool TSymbolTable::declare(TSymbol *symbol)
Olli Etuaho0f684632017-07-13 12:42:15 +0300256{
Olli Etuaho437664b2018-02-28 15:38:14 +0200257 ASSERT(!mTable.empty());
258 ASSERT(symbol->symbolType() == SymbolType::UserDefined);
259 ASSERT(!symbol->isFunction());
260 return mTable.back()->insert(symbol);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800261}
262
Jamie Madill71a151f2018-06-26 16:07:42 -0400263bool TSymbolTable::declareInternal(TSymbol *symbol)
264{
265 ASSERT(!mTable.empty());
266 ASSERT(symbol->symbolType() == SymbolType::AngleInternal);
267 ASSERT(!symbol->isFunction());
268 return mTable.back()->insert(symbol);
269}
270
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200271void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName)
272{
Olli Etuaho437664b2018-02-28 15:38:14 +0200273 ASSERT(!mTable.empty());
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200274 if (insertUnmangledName)
275 {
276 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200277 mTable[0]->insertUnmangled(function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200278 }
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200279 mTable[0]->insert(function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200280}
281
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200282void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec)
283{
284 int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1;
285 // Uses map operator [], overwrites the current value
286 (*mPrecisionStack[indexOfLastElement])[type] = prec;
287}
288
Zhenyao Moe740add2014-07-18 17:01:01 -0700289TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700290{
291 if (!SupportsPrecision(type))
292 return EbpUndefined;
293
294 // unsigned integers use the same precision as signed
295 TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
296
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200297 int level = static_cast<int>(mPrecisionStack.size()) - 1;
298 ASSERT(level >= 0); // Just to be safe. Should not happen.
Olli Etuaho183d7e22015-11-20 15:59:09 +0200299 // If we dont find anything we return this. Some types don't have predefined default precision.
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700300 TPrecision prec = EbpUndefined;
301 while (level >= 0)
302 {
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200303 PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType);
304 if (it != mPrecisionStack[level]->end())
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700305 {
306 prec = (*it).second;
307 break;
308 }
309 level--;
310 }
311 return prec;
312}
Jamie Madill45bcc782016-11-07 13:58:48 -0500313
Olli Etuaho5d69db12017-11-24 16:51:15 +0200314void TSymbolTable::clearCompilationResults()
315{
Olli Etuaho76b2c382018-03-19 15:51:29 +0200316 mGlobalInvariant = false;
Olli Etuaho391bda22018-02-23 11:43:14 +0200317 mUniqueIdCounter = kLastBuiltInId + 1;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200318 mVariableMetadata.clear();
319 mGlInVariableWithArraySize = nullptr;
Olli Etuaho5d69db12017-11-24 16:51:15 +0200320
321 // User-defined scopes should have already been cleared when the compilation finished.
Jamie Madill71a151f2018-06-26 16:07:42 -0400322 ASSERT(mTable.empty());
Olli Etuaho5d69db12017-11-24 16:51:15 +0200323}
324
325int TSymbolTable::nextUniqueIdValue()
326{
327 ASSERT(mUniqueIdCounter < std::numeric_limits<int>::max());
328 return ++mUniqueIdCounter;
329}
330
Olli Etuaho29bda812018-01-26 17:37:36 +0200331void TSymbolTable::initializeBuiltIns(sh::GLenum type,
332 ShShaderSpec spec,
333 const ShBuiltInResources &resources)
334{
Olli Etuaho065aa862018-02-22 15:30:27 +0200335 mShaderType = type;
Olli Etuahob391ec42018-03-12 17:04:59 +0200336 mResources = resources;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200337
338 // We need just one precision stack level for predefined precisions.
Jamie Madill71a151f2018-06-26 16:07:42 -0400339 mPrecisionStack.emplace_back(new PrecisionStackLevel);
Olli Etuaho29bda812018-01-26 17:37:36 +0200340
341 switch (type)
342 {
343 case GL_FRAGMENT_SHADER:
344 setDefaultPrecision(EbtInt, EbpMedium);
345 break;
346 case GL_VERTEX_SHADER:
347 case GL_COMPUTE_SHADER:
348 case GL_GEOMETRY_SHADER_EXT:
349 setDefaultPrecision(EbtInt, EbpHigh);
350 setDefaultPrecision(EbtFloat, EbpHigh);
351 break;
352 default:
353 UNREACHABLE();
354 }
355 // Set defaults for sampler types that have default precision, even those that are
356 // only available if an extension exists.
357 // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
358 initSamplerDefaultPrecision(EbtSampler2D);
359 initSamplerDefaultPrecision(EbtSamplerCube);
360 // SamplerExternalOES is specified in the extension to have default precision.
361 initSamplerDefaultPrecision(EbtSamplerExternalOES);
362 // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
363 initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
364 // It isn't specified whether Sampler2DRect has default precision.
365 initSamplerDefaultPrecision(EbtSampler2DRect);
366
367 setDefaultPrecision(EbtAtomicCounter, EbpHigh);
368
Olli Etuahob391ec42018-03-12 17:04:59 +0200369 initializeBuiltInVariables(type, spec, resources);
Olli Etuaho391bda22018-02-23 11:43:14 +0200370 mUniqueIdCounter = kLastBuiltInId + 1;
Olli Etuaho29bda812018-01-26 17:37:36 +0200371}
372
373void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType)
374{
Olli Etuahoe600c0a2018-03-02 11:23:29 +0200375 ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd);
Olli Etuaho29bda812018-01-26 17:37:36 +0200376 setDefaultPrecision(samplerType, EbpLow);
377}
378
Jamie Madillb980c562018-11-27 11:34:27 -0500379TSymbolTable::VariableMetadata::VariableMetadata()
380 : staticRead(false), staticWrite(false), invariant(false)
381{}
Jamie Madill45bcc782016-11-07 13:58:48 -0500382} // namespace sh