blob: f3c5270332ea3630e3fdef0fa4bf04151f2ff50a [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>
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020034#include <memory>
alokp@chromium.orge4249f02010-07-26 18:13:52 +000035
Jamie Madill703cdd62013-07-08 15:07:30 -040036#include "common/angleutils.h"
Olli Etuaho2a1e8f92017-07-14 11:49:36 +030037#include "compiler/translator/ExtensionBehavior.h"
Olli Etuahofbb1c792018-01-19 16:26:59 +020038#include "compiler/translator/ImmutableString.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 Etuahod4529f32017-12-12 13:06:40 +020041#include "compiler/translator/Symbol.h"
alokp@chromium.org43884872010-03-30 00:08:52 +000042
Jamie Madill45bcc782016-11-07 13:58:48 -050043namespace sh
44{
45
Gus Fernandez964df492014-10-13 11:54:39 -070046// Define ESymbolLevel as int rather than an enum since level can go
47// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
48// compiler optimizes the >= of the last element to ==.
49typedef int ESymbolLevel;
Jamie Madilld7b1ab52016-12-12 14:42:19 -050050const int COMMON_BUILTINS = 0;
51const int ESSL1_BUILTINS = 1;
52const int ESSL3_BUILTINS = 2;
Martin Radeve93d24e2016-07-28 12:06:05 +030053const int ESSL3_1_BUILTINS = 3;
Olli Etuaho977ee7e2017-07-21 11:38:27 +030054// GLSL_BUILTINS are desktop GLSL builtins that don't exist in ESSL but are used to implement
55// features in ANGLE's GLSL backend. They're not visible to the parser.
56const int GLSL_BUILTINS = 4;
57const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS;
58const int GLOBAL_LEVEL = 5;
shannonwoods@chromium.org6e10a0e2013-05-30 00:02:13 +000059
Jamie Madillf0d10f82015-03-31 12:56:52 -040060class TSymbolTable : angle::NonCopyable
Zhenyao Mo9eedea02014-05-12 16:02:35 -070061{
62 public:
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020063 TSymbolTable();
64 // To start using the symbol table after construction:
65 // * initializeBuiltIns() needs to be called.
66 // * push() needs to be called to push the global level.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000067
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -040068 ~TSymbolTable();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070 // When the symbol table is initialized with the built-ins, there should
71 // 'push' calls, so that built-ins are at level 0 and the shader
72 // globals are at level 1.
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +020073 bool isEmpty() const { return mTable.empty(); }
Jamie Madilld7b1ab52016-12-12 14:42:19 -050074 bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; }
75 bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000076
Olli Etuahodd21ecf2018-01-10 12:42:09 +020077 void push();
78 void pop();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079
Olli Etuaho0f684632017-07-13 12:42:15 +030080 // The declare* entry points are used when parsing and declare symbols at the current scope.
Olli Etuahodd21ecf2018-01-10 12:42:09 +020081 // They return the created true in case the declaration was successful, and false if the
82 // declaration failed due to redefinition.
Olli Etuaho195be942017-12-04 23:40:14 +020083 bool declareVariable(TVariable *variable);
Olli Etuaho035419f2017-11-28 14:27:15 +020084 bool declareStructType(TStructure *str);
Olli Etuaho378c3a52017-12-04 11:32:13 +020085 bool declareInterfaceBlock(TInterfaceBlock *interfaceBlock);
Olli Etuahodd21ecf2018-01-10 12:42:09 +020086 // Functions are always declared at global scope.
87 void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName);
shannonwoods@chromium.org1c848092013-05-30 00:02:34 +000088
Olli Etuaho29bda812018-01-26 17:37:36 +020089 // These return the TFunction pointer to keep using to refer to this function.
90 const TFunction *markUserDefinedFunctionHasPrototypeDeclaration(
91 const ImmutableString &mangledName,
92 bool *hadPrototypeDeclarationOut);
93 const TFunction *setUserDefinedFunctionParameterNamesFromDefinition(const TFunction *function,
94 bool *wasDefinedOut);
95
96 // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString
97 // with a reference to a short-lived char * is fine to pass here.
98 const TSymbol *find(const ImmutableString &name, int shaderVersion) const;
99
100 const TSymbol *findGlobal(const ImmutableString &name) const;
101
102 const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const;
103
104 const TSymbol *findBuiltIn(const ImmutableString &name,
105 int shaderVersion,
106 bool includeGLSLBuiltins) const;
107
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200108 void setDefaultPrecision(TBasicType type, TPrecision prec);
Olli Etuaho29bda812018-01-26 17:37:36 +0200109
110 // Searches down the precisionStack for a precision qualifier
111 // for the specified TBasicType
112 TPrecision getDefaultPrecision(TBasicType type) const;
113
114 // This records invariant varyings declared through
115 // "invariant varying_name;".
Olli Etuahodefe3932018-02-13 11:56:09 +0200116 void addInvariantVarying(const ImmutableString &originalName);
Olli Etuaho29bda812018-01-26 17:37:36 +0200117
118 // If this returns false, the varying could still be invariant
119 // if it is set as invariant during the varying variable
120 // declaration - this piece of information is stored in the
121 // variable's type, not here.
Olli Etuahodefe3932018-02-13 11:56:09 +0200122 bool isVaryingInvariant(const ImmutableString &originalName) const;
Olli Etuaho29bda812018-01-26 17:37:36 +0200123
124 void setGlobalInvariant(bool invariant);
125
126 const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
127
128 // Checks whether there is a built-in accessible by a shader with the specified version.
129 bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion);
130
131 void initializeBuiltIns(sh::GLenum type,
132 ShShaderSpec spec,
133 const ShBuiltInResources &resources);
134 void clearCompilationResults();
135
136 private:
137 friend class TSymbolUniqueId;
138 int nextUniqueIdValue();
139
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200140 class TSymbolTableBuiltInLevel;
Olli Etuaho29bda812018-01-26 17:37:36 +0200141 class TSymbolTableLevel;
142
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200143 void pushBuiltInLevel();
144
145 ESymbolLevel currentLevel() const
146 {
147 return static_cast<ESymbolLevel>(mTable.size() + LAST_BUILTIN_LEVEL);
148 }
Olli Etuaho29bda812018-01-26 17:37:36 +0200149
Olli Etuaho0f684632017-07-13 12:42:15 +0300150 // The insert* entry points are used when initializing the symbol table with built-ins.
Olli Etuaho035419f2017-11-28 14:27:15 +0200151 // They return the created symbol / true in case the declaration was successful, and nullptr /
152 // false if the declaration failed due to redefinition.
Olli Etuahofbb1c792018-01-19 16:26:59 +0200153 TVariable *insertVariable(ESymbolLevel level, const ImmutableString &name, const TType *type);
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200154 void insertVariableExt(ESymbolLevel level,
155 TExtension ext,
156 const ImmutableString &name,
157 const TType *type);
Olli Etuaho195be942017-12-04 23:40:14 +0200158 bool insertVariable(ESymbolLevel level, TVariable *variable);
Olli Etuaho035419f2017-11-28 14:27:15 +0200159 bool insertStructType(ESymbolLevel level, TStructure *str);
Olli Etuaho378c3a52017-12-04 11:32:13 +0200160 bool insertInterfaceBlock(ESymbolLevel level, TInterfaceBlock *interfaceBlock);
Nicolas Capensc9d9b302015-02-20 23:02:15 -0500161
Olli Etuahob60d30f2018-01-16 12:31:06 +0200162 template <TPrecision precision>
Olli Etuahofbb1c792018-01-19 16:26:59 +0200163 bool insertConstInt(ESymbolLevel level, const ImmutableString &name, int value);
Nicolas Capens49a88872013-06-20 09:54:03 -0400164
Olli Etuahob60d30f2018-01-16 12:31:06 +0200165 template <TPrecision precision>
Olli Etuahofbb1c792018-01-19 16:26:59 +0200166 bool insertConstIntExt(ESymbolLevel level,
167 TExtension ext,
168 const ImmutableString &name,
169 int value);
Kimmo Kinnunenb18609b2015-07-16 14:13:11 +0300170
Olli Etuahob60d30f2018-01-16 12:31:06 +0200171 template <TPrecision precision>
Olli Etuahofbb1c792018-01-19 16:26:59 +0200172 bool insertConstIvec3(ESymbolLevel level,
173 const ImmutableString &name,
174 const std::array<int, 3> &values);
Martin Radeve93d24e2016-07-28 12:06:05 +0300175
Olli Etuaho342b83d2018-01-10 13:24:01 +0200176 // Note that for inserted built-in functions the const char *name needs to remain valid for the
177 // lifetime of the SymbolTable. SymbolTable does not allocate a copy of it.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500178 void insertBuiltIn(ESymbolLevel level,
179 TOperator op,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300180 TExtension ext,
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500181 const TType *rvalue,
182 const char *name,
183 const TType *ptype1,
184 const TType *ptype2 = 0,
185 const TType *ptype3 = 0,
186 const TType *ptype4 = 0,
187 const TType *ptype5 = 0);
Nicolas Capens759b9942014-02-14 17:57:14 -0500188
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500189 void insertBuiltIn(ESymbolLevel level,
190 const TType *rvalue,
191 const char *name,
192 const TType *ptype1,
193 const TType *ptype2 = 0,
194 const TType *ptype3 = 0,
195 const TType *ptype4 = 0,
196 const TType *ptype5 = 0)
Nicolas Capens482907e2015-02-23 16:56:33 -0500197 {
Martin Radevda6254b2016-12-14 17:00:36 +0200198 insertUnmangledBuiltInName(name, level);
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300199 insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3,
200 ptype4, ptype5);
Nicolas Capensc9d9b302015-02-20 23:02:15 -0500201 }
202
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500203 void insertBuiltIn(ESymbolLevel level,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300204 TExtension ext,
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500205 const TType *rvalue,
206 const char *name,
207 const TType *ptype1,
208 const TType *ptype2 = 0,
209 const TType *ptype3 = 0,
210 const TType *ptype4 = 0,
211 const TType *ptype5 = 0)
Nicolas Capensc9d9b302015-02-20 23:02:15 -0500212 {
Martin Radevda6254b2016-12-14 17:00:36 +0200213 insertUnmangledBuiltInName(name, level);
Nicolas Capensc9d9b302015-02-20 23:02:15 -0500214 insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
215 }
216
Olli Etuaho492cfab2017-01-20 21:18:29 +0000217 void insertBuiltInOp(ESymbolLevel level,
218 TOperator op,
219 const TType *rvalue,
220 const TType *ptype1,
221 const TType *ptype2 = 0,
222 const TType *ptype3 = 0,
223 const TType *ptype4 = 0,
224 const TType *ptype5 = 0);
225
226 void insertBuiltInOp(ESymbolLevel level,
227 TOperator op,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300228 TExtension ext,
Olli Etuaho492cfab2017-01-20 21:18:29 +0000229 const TType *rvalue,
230 const TType *ptype1,
231 const TType *ptype2 = 0,
232 const TType *ptype3 = 0,
233 const TType *ptype4 = 0,
234 const TType *ptype5 = 0);
Nicolas Capens482907e2015-02-23 16:56:33 -0500235
Martin Radevd7c5b0a2016-07-27 14:04:43 +0300236 void insertBuiltInFunctionNoParameters(ESymbolLevel level,
237 TOperator op,
238 const TType *rvalue,
239 const char *name);
240
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800241 void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
Olli Etuaho2a1e8f92017-07-14 11:49:36 +0300242 TExtension ext,
Jiawei Shaod27f5c82017-08-23 09:38:08 +0800243 TOperator op,
244 const TType *rvalue,
245 const char *name);
246
Olli Etuaho9d4d7f02017-12-07 17:11:41 +0100247 TVariable *insertVariable(ESymbolLevel level,
Olli Etuahofbb1c792018-01-19 16:26:59 +0200248 const ImmutableString &name,
Olli Etuahob60d30f2018-01-16 12:31:06 +0200249 const TType *type,
Olli Etuaho9d4d7f02017-12-07 17:11:41 +0100250 SymbolType symbolType);
Olli Etuaho0f684632017-07-13 12:42:15 +0300251
Olli Etuahodd21ecf2018-01-10 12:42:09 +0200252 bool insert(ESymbolLevel level, TSymbol *symbol);
253
Olli Etuahofbb1c792018-01-19 16:26:59 +0200254 TFunction *findUserDefinedFunction(const ImmutableString &name) const;
Olli Etuaho0f684632017-07-13 12:42:15 +0300255
Martin Radevda6254b2016-12-14 17:00:36 +0200256 // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and
257 // above.
258 void insertUnmangledBuiltInName(const char *name, ESymbolLevel level);
259
260 bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level);
Olli Etuahoc4a96d62015-07-23 17:37:39 +0530261
Olli Etuaho29bda812018-01-26 17:37:36 +0200262 void initSamplerDefaultPrecision(TBasicType samplerType);
263
264 void initializeBuiltInFunctions(sh::GLenum type,
265 ShShaderSpec spec,
266 const ShBuiltInResources &resources);
267 void initializeBuiltInVariables(sh::GLenum type,
268 ShShaderSpec spec,
269 const ShBuiltInResources &resources);
270 void markBuiltInInitializationFinished();
271
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200272 std::vector<std::unique_ptr<TSymbolTableBuiltInLevel>> mBuiltInTable;
273 std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
274
275 // There's one precision stack level for predefined precisions and then one level for each scope
276 // in table.
Alok Priyadarshibc3f1ac2013-09-23 14:57:02 -0400277 typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
Olli Etuahoe5fe7aa2018-01-29 12:06:11 +0200278 std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack;
Jamie Madillbfa91f42014-06-05 15:45:18 -0400279
Olli Etuahoa5e693a2017-07-13 16:07:26 +0300280 int mUniqueIdCounter;
Olli Etuaho2d88e9b2017-07-21 16:52:03 +0300281
Olli Etuaho5d69db12017-11-24 16:51:15 +0200282 // -1 before built-in init has finished, one past the last built-in id afterwards.
283 // TODO(oetuaho): Make this a compile-time constant once the symbol table is initialized at
284 // compile time. http://anglebug.com/1432
285 int mUserDefinedUniqueIdsStart;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286};
287
Jamie Madill45bcc782016-11-07 13:58:48 -0500288} // namespace sh
289
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500290#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_