blob: 3d479fbd119dcde642b1c20ac7a5f2d492f30a66 [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 Etuaho2d8e4322018-01-22 14:12:46 +020020#include "compiler/translator/ImmutableString.h"
Olli Etuaho01d0ad02017-01-22 14:51:23 -080021#include "compiler/translator/IntermNode.h"
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020022#include "compiler/translator/StaticType.h"
kbr@chromium.org476541f2011-10-27 21:14:51 +000023
Jamie Madill45bcc782016-11-07 13:58:48 -050024namespace sh
25{
26
Olli Etuahodd21ecf2018-01-10 12:42:09 +020027class TSymbolTable::TSymbolTableLevel
28{
29 public:
30 TSymbolTableLevel() : mGlobalInvariant(false) {}
Olli Etuahodd21ecf2018-01-10 12:42:09 +020031
32 bool insert(TSymbol *symbol);
33
34 // Insert a function using its unmangled name as the key.
Olli Etuahob92f92a2018-02-15 19:14:59 +020035 void insertUnmangled(TFunction *function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +020036
Olli Etuahofbb1c792018-01-19 16:26:59 +020037 TSymbol *find(const ImmutableString &name) const;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020038
Olli Etuahodefe3932018-02-13 11:56:09 +020039 void addInvariantVarying(const ImmutableString &name) { mInvariantVaryings.insert(name); }
Olli Etuahodd21ecf2018-01-10 12:42:09 +020040
Olli Etuahodefe3932018-02-13 11:56:09 +020041 bool isVaryingInvariant(const ImmutableString &name)
Olli Etuahodd21ecf2018-01-10 12:42:09 +020042 {
43 return (mGlobalInvariant || mInvariantVaryings.count(name) > 0);
44 }
45
46 void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
47
Olli Etuahodd21ecf2018-01-10 12:42:09 +020048 private:
Olli Etuahofbb1c792018-01-19 16:26:59 +020049 using tLevel = TUnorderedMap<ImmutableString,
50 TSymbol *,
51 ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020052 using tLevelPair = const tLevel::value_type;
53 using tInsertResult = std::pair<tLevel::iterator, bool>;
54
55 tLevel level;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020056
Olli Etuahodefe3932018-02-13 11:56:09 +020057 std::set<ImmutableString> mInvariantVaryings;
Olli Etuahodd21ecf2018-01-10 12:42:09 +020058 bool mGlobalInvariant;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020059};
60
Olli Etuahodd21ecf2018-01-10 12:42:09 +020061bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
Jamie Madillbfa91f42014-06-05 15:45:18 -040062{
Jamie Madillbfa91f42014-06-05 15:45:18 -040063 // returning true means symbol was added to the table
Nicolas Capensadfffe42014-06-17 02:13:36 -040064 tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
Jamie Madillbfa91f42014-06-05 15:45:18 -040065 return result.second;
66}
67
Olli Etuahob92f92a2018-02-15 19:14:59 +020068void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
Olli Etuahob2983c92015-03-18 14:02:46 +020069{
Olli Etuahob92f92a2018-02-15 19:14:59 +020070 level.insert(tLevelPair(function->name(), function));
Olli Etuahob2983c92015-03-18 14:02:46 +020071}
72
Olli Etuahofbb1c792018-01-19 16:26:59 +020073TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const
Jamie Madillbfa91f42014-06-05 15:45:18 -040074{
75 tLevel::const_iterator it = level.find(name);
76 if (it == level.end())
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020077 return nullptr;
Jamie Madillbfa91f42014-06-05 15:45:18 -040078 else
79 return (*it).second;
80}
81
Olli Etuaho94bbed12018-03-20 14:44:53 +020082TSymbolTable::TSymbolTable()
83 : mUniqueIdCounter(0), mShaderType(GL_FRAGMENT_SHADER), mGlInVariableWithArraySize(nullptr)
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020084{
85}
86
87TSymbolTable::~TSymbolTable() = default;
88
Olli Etuaho437664b2018-02-28 15:38:14 +020089bool TSymbolTable::isEmpty() const
90{
91 return mTable.empty();
92}
93
94bool TSymbolTable::atGlobalLevel() const
95{
96 return mTable.size() == 1u;
97}
98
Olli Etuahodd21ecf2018-01-10 12:42:09 +020099void TSymbolTable::push()
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000100{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200101 mTable.push_back(std::unique_ptr<TSymbolTableLevel>(new TSymbolTableLevel));
102 mPrecisionStack.push_back(std::unique_ptr<PrecisionStackLevel>(new PrecisionStackLevel));
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200103}
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000104
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200105void TSymbolTable::pop()
106{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200107 mTable.pop_back();
108 mPrecisionStack.pop_back();
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200109}
110
Olli Etuaho7c8567a2018-02-20 15:44:07 +0200111const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration(
Olli Etuahofbb1c792018-01-19 16:26:59 +0200112 const ImmutableString &mangledName,
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200113 bool *hadPrototypeDeclarationOut)
114{
115 TFunction *function = findUserDefinedFunction(mangledName);
116 *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration();
117 function->setHasPrototypeDeclaration();
118 return function;
119}
120
Olli Etuaho7c8567a2018-02-20 15:44:07 +0200121const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function,
122 bool *wasDefinedOut)
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200123{
124 TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName());
125 ASSERT(firstDeclaration);
126 // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as
127 // it would have just been put in the symbol table. Otherwise, we're looking up an earlier
128 // occurance.
129 if (function != firstDeclaration)
130 {
Olli Etuaho029e8ca2018-02-16 14:06:49 +0200131 // The previous declaration should have the same parameters as the function definition
132 // (parameter names may differ).
133 firstDeclaration->shareParameters(*function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200134 }
135
136 *wasDefinedOut = firstDeclaration->isDefined();
137 firstDeclaration->setDefined();
138 return firstDeclaration;
139}
140
Olli Etuaho94bbed12018-03-20 14:44:53 +0200141bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize)
142{
143 if (mGlInVariableWithArraySize)
144 {
145 return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize;
146 }
147 const TInterfaceBlock *glPerVertex = mVar_gl_PerVertex;
148 TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create());
149 glInType->makeArray(inputArraySize);
150 mGlInVariableWithArraySize =
151 new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn,
152 TExtension::EXT_geometry_shader);
153 return true;
154}
155
156TVariable *TSymbolTable::getGlInVariableWithArraySize() const
157{
158 return mGlInVariableWithArraySize;
159}
160
Olli Etuaho59c5b892018-04-03 11:44:50 +0300161const TVariable *TSymbolTable::gl_FragData() const
162{
163 return mVar_gl_FragData;
164}
165
166const TVariable *TSymbolTable::gl_SecondaryFragDataEXT() const
167{
168 return mVar_gl_SecondaryFragDataEXT;
169}
170
Olli Etuaho94bbed12018-03-20 14:44:53 +0200171void TSymbolTable::markStaticWrite(const TVariable &variable)
172{
173 int id = variable.uniqueId().get();
174 auto iter = mVariableMetadata.find(id);
175 if (iter == mVariableMetadata.end())
176 {
177 iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
178 }
179 iter->second.staticWrite = true;
180}
181
182void TSymbolTable::markStaticRead(const TVariable &variable)
183{
184 int id = variable.uniqueId().get();
185 auto iter = mVariableMetadata.find(id);
186 if (iter == mVariableMetadata.end())
187 {
188 iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
189 }
190 iter->second.staticRead = true;
191}
192
193bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const
194{
195 ASSERT(!variable.getConstPointer());
196 int id = variable.uniqueId().get();
197 auto iter = mVariableMetadata.find(id);
198 return iter != mVariableMetadata.end();
199}
200
Olli Etuahofbb1c792018-01-19 16:26:59 +0200201const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200202{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200203 int userDefinedLevel = static_cast<int>(mTable.size()) - 1;
204 while (userDefinedLevel >= 0)
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000205 {
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200206 const TSymbol *symbol = mTable[userDefinedLevel]->find(name);
207 if (symbol)
208 {
209 return symbol;
210 }
211 userDefinedLevel--;
212 }
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000213
Olli Etuaho115b2c42018-03-15 17:46:29 +0200214 return findBuiltIn(name, shaderVersion);
shannonwoods@chromium.org96e7ba12013-05-30 00:02:41 +0000215}
216
Olli Etuahofbb1c792018-01-19 16:26:59 +0200217TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200218{
219 // User-defined functions are always declared at the global level.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200220 ASSERT(!mTable.empty());
221 return static_cast<TFunction *>(mTable[0]->find(name));
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200222}
223
Olli Etuahofbb1c792018-01-19 16:26:59 +0200224const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const
Zhenyao Mod7490962016-11-09 15:49:51 -0800225{
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200226 ASSERT(!mTable.empty());
227 return mTable[0]->find(name);
Zhenyao Mod7490962016-11-09 15:49:51 -0800228}
229
Olli Etuaho437664b2018-02-28 15:38:14 +0200230bool TSymbolTable::declare(TSymbol *symbol)
Olli Etuaho0f684632017-07-13 12:42:15 +0300231{
Olli Etuaho437664b2018-02-28 15:38:14 +0200232 ASSERT(!mTable.empty());
233 ASSERT(symbol->symbolType() == SymbolType::UserDefined);
234 ASSERT(!symbol->isFunction());
235 return mTable.back()->insert(symbol);
Jiawei Shaod8105a02017-08-08 09:54:36 +0800236}
237
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200238void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName)
239{
Olli Etuaho437664b2018-02-28 15:38:14 +0200240 ASSERT(!mTable.empty());
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200241 if (insertUnmangledName)
242 {
243 // Insert the unmangled name to detect potential future redefinition as a variable.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200244 mTable[0]->insertUnmangled(function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200245 }
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200246 mTable[0]->insert(function);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200247}
248
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200249void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec)
250{
251 int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1;
252 // Uses map operator [], overwrites the current value
253 (*mPrecisionStack[indexOfLastElement])[type] = prec;
254}
255
Zhenyao Moe740add2014-07-18 17:01:01 -0700256TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700257{
258 if (!SupportsPrecision(type))
259 return EbpUndefined;
260
261 // unsigned integers use the same precision as signed
262 TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
263
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200264 int level = static_cast<int>(mPrecisionStack.size()) - 1;
265 ASSERT(level >= 0); // Just to be safe. Should not happen.
Olli Etuaho183d7e22015-11-20 15:59:09 +0200266 // If we dont find anything we return this. Some types don't have predefined default precision.
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700267 TPrecision prec = EbpUndefined;
268 while (level >= 0)
269 {
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200270 PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType);
271 if (it != mPrecisionStack[level]->end())
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700272 {
273 prec = (*it).second;
274 break;
275 }
276 level--;
277 }
278 return prec;
279}
Jamie Madill45bcc782016-11-07 13:58:48 -0500280
Olli Etuahodefe3932018-02-13 11:56:09 +0200281void TSymbolTable::addInvariantVarying(const ImmutableString &originalName)
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200282{
283 ASSERT(atGlobalLevel());
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200284 mTable.back()->addInvariantVarying(originalName);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200285}
286
Olli Etuahodefe3932018-02-13 11:56:09 +0200287bool TSymbolTable::isVaryingInvariant(const ImmutableString &originalName) const
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200288{
289 ASSERT(atGlobalLevel());
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200290 return mTable.back()->isVaryingInvariant(originalName);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200291}
292
293void TSymbolTable::setGlobalInvariant(bool invariant)
294{
295 ASSERT(atGlobalLevel());
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200296 mTable.back()->setGlobalInvariant(invariant);
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200297}
298
Olli Etuaho5d69db12017-11-24 16:51:15 +0200299void TSymbolTable::clearCompilationResults()
300{
Olli Etuaho391bda22018-02-23 11:43:14 +0200301 mUniqueIdCounter = kLastBuiltInId + 1;
Olli Etuaho94bbed12018-03-20 14:44:53 +0200302 mVariableMetadata.clear();
303 mGlInVariableWithArraySize = nullptr;
Olli Etuaho5d69db12017-11-24 16:51:15 +0200304
305 // User-defined scopes should have already been cleared when the compilation finished.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200306 ASSERT(mTable.size() == 0u);
Olli Etuaho5d69db12017-11-24 16:51:15 +0200307}
308
309int TSymbolTable::nextUniqueIdValue()
310{
311 ASSERT(mUniqueIdCounter < std::numeric_limits<int>::max());
312 return ++mUniqueIdCounter;
313}
314
Olli Etuaho29bda812018-01-26 17:37:36 +0200315void TSymbolTable::initializeBuiltIns(sh::GLenum type,
316 ShShaderSpec spec,
317 const ShBuiltInResources &resources)
318{
Olli Etuaho065aa862018-02-22 15:30:27 +0200319 mShaderType = type;
Olli Etuahob391ec42018-03-12 17:04:59 +0200320 mResources = resources;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200321
322 // We need just one precision stack level for predefined precisions.
323 mPrecisionStack.push_back(std::unique_ptr<PrecisionStackLevel>(new PrecisionStackLevel));
Olli Etuaho29bda812018-01-26 17:37:36 +0200324
325 switch (type)
326 {
327 case GL_FRAGMENT_SHADER:
328 setDefaultPrecision(EbtInt, EbpMedium);
329 break;
330 case GL_VERTEX_SHADER:
331 case GL_COMPUTE_SHADER:
332 case GL_GEOMETRY_SHADER_EXT:
333 setDefaultPrecision(EbtInt, EbpHigh);
334 setDefaultPrecision(EbtFloat, EbpHigh);
335 break;
336 default:
337 UNREACHABLE();
338 }
339 // Set defaults for sampler types that have default precision, even those that are
340 // only available if an extension exists.
341 // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
342 initSamplerDefaultPrecision(EbtSampler2D);
343 initSamplerDefaultPrecision(EbtSamplerCube);
344 // SamplerExternalOES is specified in the extension to have default precision.
345 initSamplerDefaultPrecision(EbtSamplerExternalOES);
346 // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
347 initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
348 // It isn't specified whether Sampler2DRect has default precision.
349 initSamplerDefaultPrecision(EbtSampler2DRect);
350
351 setDefaultPrecision(EbtAtomicCounter, EbpHigh);
352
Olli Etuahob391ec42018-03-12 17:04:59 +0200353 initializeBuiltInVariables(type, spec, resources);
Olli Etuaho391bda22018-02-23 11:43:14 +0200354 mUniqueIdCounter = kLastBuiltInId + 1;
Olli Etuaho29bda812018-01-26 17:37:36 +0200355}
356
357void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType)
358{
Olli Etuahoe600c0a2018-03-02 11:23:29 +0200359 ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd);
Olli Etuaho29bda812018-01-26 17:37:36 +0200360 setDefaultPrecision(samplerType, EbpLow);
361}
362
Olli Etuaho94bbed12018-03-20 14:44:53 +0200363TSymbolTable::VariableMetadata::VariableMetadata() : staticRead(false), staticWrite(false)
364{
365}
366
Jamie Madill45bcc782016-11-07 13:58:48 -0500367} // namespace sh