blob: 9a5363e66ca71e2f0972e23ae1fb7c4de09bde85 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens1fbc2872014-01-03 14:12:09 -05002// Copyright (c) 2002-2014 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
Geoff Lang0a73dd82014-11-19 16:18:08 -05007#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_
8#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009
10//
11// Symbol table for parsing. Has these design characteristics:
12//
13// * Same symbol table can be used to compile many shaders, to preserve
14// effort of creating and loading with the large numbers of built-in
15// symbols.
16//
17// * Name mangling will be used to give each function a unique name
18// so that symbol table lookups are never ambiguous. This allows
19// a simpler symbol table structure.
20//
Jamie Madilld7b1ab52016-12-12 14:42:19 -050021// * Pushing and popping of scope, so symbol table will really be a stack
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022// of symbol tables. Searched from the top, with new inserts going into
23// the top.
24//
25// * Constants: Compile time constant symbols will keep their values
26// in the symbol table. The parser can substitute constants at parse
27// time, including doing constant folding and constant propagation.
28//
29// * No temporaries: Temporaries made from operations (+, --, .xy, etc.)
30// are tracked in the intermediate representation, not the symbol table.
31//
32
Martin Radeve93d24e2016-07-28 12:06:05 +030033#include <array>
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000034#include <assert.h>
Zhenyao Mo94ac7b72014-10-15 18:22:08 -070035#include <set>
alokp@chromium.orge4249f02010-07-26 18:13:52 +000036
Jamie Madill703cdd62013-07-08 15:07:30 -040037#include "common/angleutils.h"
Olli Etuaho2a1e8f92017-07-14 11:49:36 +030038#include "compiler/translator/ExtensionBehavior.h"
Geoff Lang17732822013-08-29 13:46:49 -040039#include "compiler/translator/InfoSink.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040040#include "compiler/translator/IntermNode.h"
Olli Etuahob60d30f2018-01-16 12:31:06 +020041#include "compiler/translator/StaticType.h"
Olli Etuahod4529f32017-12-12 13:06:40 +020042#include "compiler/translator/Symbol.h"
alokp@chromium.org43884872010-03-30 00:08:52 +000043
Jamie Madill45bcc782016-11-07 13:58:48 -050044namespace sh
45{
46
Gus Fernandez964df492014-10-13 11:54:39 -070047// Define ESymbolLevel as int rather than an enum since level can go
48// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
49// compiler optimizes the >= of the last element to ==.
50typedef int ESymbolLevel;
Jamie Madilld7b1ab52016-12-12 14:42:19 -050051const int COMMON_BUILTINS = 0;
52const int ESSL1_BUILTINS = 1;
53const int ESSL3_BUILTINS = 2;
Martin Radeve93d24e2016-07-28 12:06:05 +030054const int ESSL3_1_BUILTINS = 3;
Olli Etuaho977ee7e2017-07-21 11:38:27 +030055// GLSL_BUILTINS are desktop GLSL builtins that don't exist in ESSL but are used to implement
56// features in ANGLE's GLSL backend. They're not visible to the parser.
57const int GLSL_BUILTINS = 4;
58const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS;
59const int GLOBAL_LEVEL = 5;
shannonwoods@chromium.org6e10a0e2013-05-30 00:02:13 +000060
Jamie Madillf0d10f82015-03-31 12:56:52 -040061class TSymbolTable : angle::NonCopyable
Zhenyao Mo9eedea02014-05-12 16:02:35 -070062{
63 public:
Olli Etuaho195be942017-12-04 23:40:14 +020064 TSymbolTable() : mUniqueIdCounter(0), mUserDefinedUniqueIdsStart(-1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066 // The symbol table cannot be used until push() is called, but
67 // the lack of an initial call to push() can be used to detect
68 // that the symbol table has not been preloaded with built-ins.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069 }
70
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -040071 ~TSymbolTable();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000073 // When the symbol table is initialized with the built-ins, there should
74 // 'push' calls, so that built-ins are at level 0 and the shader
75 // globals are at level 1.
Jamie Madilld7b1ab52016-12-12 14:42:19 -050076 bool isEmpty() const { return table.empty(); }
77 bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; }
78 bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079
Olli Etuahodd21ecf2018-01-10 12:42:09 +020080 void push();
81 void pop();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000082
Olli Etuaho0f684632017-07-13 12:42:15 +030083 // The declare* entry points are used when parsing and declare symbols at the current scope.
Olli Etuahodd21ecf2018-01-10 12:42:09 +020084 // They return the created true in case the declaration was successful, and false if the
85 // declaration failed due to redefinition.
Olli Etuaho195be942017-12-04 23:40:14 +020086 bool declareVariable(TVariable *variable);
Olli Etuaho035419f2017-11-28 14:27:15 +020087 bool declareStructType(TStructure *str);
Olli Etuaho378c3a52017-12-04 11:32:13 +020088 bool declareInterfaceBlock(TInterfaceBlock *interfaceBlock);
Olli Etuahodd21ecf2018-01-10 12:42:09 +020089 // Functions are always declared at global scope.
90 void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName);
shannonwoods@chromium.org1c848092013-05-30 00:02:34 +000091
Olli Etuaho0f684632017-07-13 12:42:15 +030092 // The insert* entry points are used when initializing the symbol table with built-ins.
Olli Etuaho035419f2017-11-28 14:27:15 +020093 // They return the created symbol / true in case the declaration was successful, and nullptr /
94 // false if the declaration failed due to redefinition.
Olli Etuahob60d30f2018-01-16 12:31:06 +020095 TVariable *insertVariable(ESymbolLevel level, const char *name, const TType *type);
Olli Etuaho0f684632017-07-13 12:42:15 +030096 TVariable *insertVariableExt(ESymbolLevel level,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +030097 TExtension ext,
Olli Etuaho0f684632017-07-13 12:42:15 +030098 const char *name,
Olli Etuahob60d30f2018-01-16 12:31:06 +020099 const TType *type);
Olli Etuaho195be942017-12-04 23:40:14 +0200100 bool insertVariable(ESymbolLevel level, TVariable *variable);
Olli Etuaho035419f2017-11-28 14:27:15 +0200101 bool insertStructType(ESymbolLevel level, TStructure *str);
Olli Etuaho378c3a52017-12-04 11:32:13 +0200102 bool insertInterfaceBlock(ESymbolLevel level, TInterfaceBlock *interfaceBlock);
Nicolas Capensc9d9b302015-02-20 23:02:15 -0500103
Olli Etuahob60d30f2018-01-16 12:31:06 +0200104 template <TPrecision precision>
105 bool insertConstInt(ESymbolLevel level, const char *name, int value);
Nicolas Capens49a88872013-06-20 09:54:03 -0400106
Olli Etuahob60d30f2018-01-16 12:31:06 +0200107 template <TPrecision precision>
108 bool insertConstIntExt(ESymbolLevel level, TExtension ext, const char *name, int value);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300109
Olli Etuahob60d30f2018-01-16 12:31:06 +0200110 template <TPrecision precision>
111 bool insertConstIvec3(ESymbolLevel level, const char *name, const std::array<int, 3> &values);
Martin Radeve93d24e2016-07-28 12:06:05 +0300112
Olli Etuaho342b83d2018-01-10 13:24:01 +0200113 // Note that for inserted built-in functions the const char *name needs to remain valid for the
114 // lifetime of the SymbolTable. SymbolTable does not allocate a copy of it.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500115 void insertBuiltIn(ESymbolLevel level,
116 TOperator op,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300117 TExtension ext,
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500118 const TType *rvalue,
119 const char *name,
120 const TType *ptype1,
121 const TType *ptype2 = 0,
122 const TType *ptype3 = 0,
123 const TType *ptype4 = 0,
124 const TType *ptype5 = 0);
Nicolas Capens759b9942014-02-14 17:57:14 -0500125
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500126 void insertBuiltIn(ESymbolLevel level,
127 const TType *rvalue,
128 const char *name,
129 const TType *ptype1,
130 const TType *ptype2 = 0,
131 const TType *ptype3 = 0,
132 const TType *ptype4 = 0,
133 const TType *ptype5 = 0)
Nicolas Capens482907e2015-02-23 16:56:33 -0500134 {
Martin Radevda6254b2016-12-14 17:00:36 +0200135 insertUnmangledBuiltInName(name, level);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300136 insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3,
137 ptype4, ptype5);
Nicolas Capensc9d9b302015-02-20 23:02:15 -0500138 }
139
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500140 void insertBuiltIn(ESymbolLevel level,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300141 TExtension ext,
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500142 const TType *rvalue,
143 const char *name,
144 const TType *ptype1,
145 const TType *ptype2 = 0,
146 const TType *ptype3 = 0,
147 const TType *ptype4 = 0,
148 const TType *ptype5 = 0)
Nicolas Capensc9d9b302015-02-20 23:02:15 -0500149 {
Martin Radevda6254b2016-12-14 17:00:36 +0200150 insertUnmangledBuiltInName(name, level);
Nicolas Capensc9d9b302015-02-20 23:02:15 -0500151 insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
152 }
153
Olli Etuaho492cfab2017-01-20 21:18:29 +0000154 void insertBuiltInOp(ESymbolLevel level,
155 TOperator op,
156 const TType *rvalue,
157 const TType *ptype1,
158 const TType *ptype2 = 0,
159 const TType *ptype3 = 0,
160 const TType *ptype4 = 0,
161 const TType *ptype5 = 0);
162
163 void insertBuiltInOp(ESymbolLevel level,
164 TOperator op,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300165 TExtension ext,
Olli Etuaho492cfab2017-01-20 21:18:29 +0000166 const TType *rvalue,
167 const TType *ptype1,
168 const TType *ptype2 = 0,
169 const TType *ptype3 = 0,
170 const TType *ptype4 = 0,
171 const TType *ptype5 = 0);
Nicolas Capens482907e2015-02-23 16:56:33 -0500172
Martin Radevd7c5b0a2016-07-27 14:04:43 +0300173 void insertBuiltInFunctionNoParameters(ESymbolLevel level,
174 TOperator op,
175 const TType *rvalue,
176 const char *name);
177
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800178 void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300179 TExtension ext,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800180 TOperator op,
181 const TType *rvalue,
182 const char *name);
183
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200184 // These return the TFunction pointer to keep using to refer to this function.
185 const TFunction *markUserDefinedFunctionHasPrototypeDeclaration(
186 const TString &mangledName,
187 bool *hadPrototypeDeclarationOut);
188 const TFunction *setUserDefinedFunctionParameterNamesFromDefinition(const TFunction *function,
189 bool *wasDefinedOut);
Zhenyao Mod7490962016-11-09 15:49:51 -0800190
Olli Etuaho37b697e2018-01-29 12:19:27 +0200191 const TSymbol *find(const TString &name, int shaderVersion) const;
Zhenyao Mod7490962016-11-09 15:49:51 -0800192
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200193 const TSymbol *findGlobal(const TString &name) const;
Zhenyao Mod7490962016-11-09 15:49:51 -0800194
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200195 const TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
Olli Etuaho977ee7e2017-07-21 11:38:27 +0300196
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200197 const TSymbol *findBuiltIn(const TString &name,
198 int shaderVersion,
199 bool includeGLSLBuiltins) const;
daniel@transgaming.com5dd6d092012-03-20 20:10:28 +0000200
Olli Etuahocce89652017-06-19 16:04:09 +0300201 void setDefaultPrecision(TBasicType type, TPrecision prec)
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700202 {
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000203 int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700204 // Uses map operator [], overwrites the current value
Olli Etuahocce89652017-06-19 16:04:09 +0300205 (*precisionStack[indexOfLastElement])[type] = prec;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000206 }
207
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700208 // Searches down the precisionStack for a precision qualifier
209 // for the specified TBasicType
Zhenyao Moe740add2014-07-18 17:01:01 -0700210 TPrecision getDefaultPrecision(TBasicType type) const;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000211
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700212 // This records invariant varyings declared through
213 // "invariant varying_name;".
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200214 void addInvariantVarying(const std::string &originalName);
215
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700216 // If this returns false, the varying could still be invariant
217 // if it is set as invariant during the varying variable
218 // declaration - this piece of information is stored in the
219 // variable's type, not here.
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200220 bool isVaryingInvariant(const std::string &originalName) const;
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700221
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200222 void setGlobalInvariant(bool invariant);
Zhenyao Mo94ac7b72014-10-15 18:22:08 -0700223
Olli Etuaho2d88e9b2017-07-21 16:52:03 +0300224 const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
225
Martin Radevda6254b2016-12-14 17:00:36 +0200226 // Checks whether there is a built-in accessible by a shader with the specified version.
227 bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion);
Olli Etuahoc4a96d62015-07-23 17:37:39 +0530228
Olli Etuaho5d69db12017-11-24 16:51:15 +0200229 void markBuiltInInitializationFinished();
230 void clearCompilationResults();
231
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700232 private:
Olli Etuaho2d88e9b2017-07-21 16:52:03 +0300233 friend class TSymbolUniqueId;
Olli Etuaho5d69db12017-11-24 16:51:15 +0200234 int nextUniqueIdValue();
Olli Etuaho2d88e9b2017-07-21 16:52:03 +0300235
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200236 class TSymbolTableLevel;
237
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500238 ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000239
Olli Etuaho9d4d7f02017-12-07 17:11:41 +0100240 TVariable *insertVariable(ESymbolLevel level,
241 const TString *name,
Olli Etuahob60d30f2018-01-16 12:31:06 +0200242 const TType *type,
Olli Etuaho9d4d7f02017-12-07 17:11:41 +0100243 SymbolType symbolType);
Olli Etuaho0f684632017-07-13 12:42:15 +0300244
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200245 bool insert(ESymbolLevel level, TSymbol *symbol);
246
247 TFunction *findUserDefinedFunction(const TString &name) const;
Olli Etuaho0f684632017-07-13 12:42:15 +0300248
Martin Radevda6254b2016-12-14 17:00:36 +0200249 // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and
250 // above.
251 void insertUnmangledBuiltInName(const char *name, ESymbolLevel level);
252
253 bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level);
Olli Etuahoc4a96d62015-07-23 17:37:39 +0530254
Zhenyao Mo9eedea02014-05-12 16:02:35 -0700255 std::vector<TSymbolTableLevel *> table;
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400256 typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500257 std::vector<PrecisionStackLevel *> precisionStack;
Jamie Madillbfa91f42014-06-05 15:45:18 -0400258
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300259 int mUniqueIdCounter;
Olli Etuaho2d88e9b2017-07-21 16:52:03 +0300260
Olli Etuaho5d69db12017-11-24 16:51:15 +0200261 // -1 before built-in init has finished, one past the last built-in id afterwards.
262 // TODO(oetuaho): Make this a compile-time constant once the symbol table is initialized at
263 // compile time. http://anglebug.com/1432
264 int mUserDefinedUniqueIdsStart;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265};
266
Olli Etuahob60d30f2018-01-16 12:31:06 +0200267template <TPrecision precision>
268bool TSymbolTable::insertConstInt(ESymbolLevel level, const char *name, int value)
269{
270 TVariable *constant =
271 new TVariable(this, NewPoolTString(name),
272 StaticType::Get<EbtInt, precision, EvqConst, 1, 1>(), SymbolType::BuiltIn);
273 TConstantUnion *unionArray = new TConstantUnion[1];
274 unionArray[0].setIConst(value);
275 constant->shareConstPointer(unionArray);
276 return insert(level, constant);
277}
278
279template <TPrecision precision>
280bool TSymbolTable::insertConstIntExt(ESymbolLevel level,
281 TExtension ext,
282 const char *name,
283 int value)
284{
285 TVariable *constant = new TVariable(this, NewPoolTString(name),
286 StaticType::Get<EbtInt, precision, EvqConst, 1, 1>(),
287 SymbolType::BuiltIn, ext);
288 TConstantUnion *unionArray = new TConstantUnion[1];
289 unionArray[0].setIConst(value);
290 constant->shareConstPointer(unionArray);
291 return insert(level, constant);
292}
293
294template <TPrecision precision>
295bool TSymbolTable::insertConstIvec3(ESymbolLevel level,
296 const char *name,
297 const std::array<int, 3> &values)
298{
299 TVariable *constantIvec3 =
300 new TVariable(this, NewPoolTString(name),
301 StaticType::Get<EbtInt, precision, EvqConst, 3, 1>(), SymbolType::BuiltIn);
302
303 TConstantUnion *unionArray = new TConstantUnion[3];
304 for (size_t index = 0u; index < 3u; ++index)
305 {
306 unionArray[index].setIConst(values[index]);
307 }
308 constantIvec3->shareConstPointer(unionArray);
309
310 return insert(level, constantIvec3);
311}
312
Jamie Madill45bcc782016-11-07 13:58:48 -0500313} // namespace sh
314
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500315#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_