1//
2// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_
8#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_
9
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//
21// * Pushing and popping of scope, so symbol table will really be a stack
22// 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
33#include <memory>
34#include <set>
35
36#include "common/angleutils.h"
37#include "compiler/translator/ExtensionBehavior.h"
38#include "compiler/translator/ImmutableString.h"
39#include "compiler/translator/InfoSink.h"
40#include "compiler/translator/IntermNode.h"
41#include "compiler/translator/Symbol.h"
42#include "compiler/translator/SymbolTable_autogen.h"
43
44namespace sh
45{
46
47// Define ESymbolLevel as int rather than an enum so that we can do arithmetic on it.
48typedef int ESymbolLevel;
49const int COMMON_BUILTINS = 0;
50const int ESSL1_BUILTINS = 1;
51const int ESSL3_BUILTINS = 2;
52const int ESSL3_1_BUILTINS = 3;
53// GLSL_BUILTINS are desktop GLSL builtins that don't exist in ESSL but are used to implement
54// features in ANGLE's GLSL backend. They're not visible to the parser.
55const int GLSL_BUILTINS = 4;
56const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS;
57
58struct UnmangledBuiltIn
59{
60 constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {}
61
62 TExtension extension;
63};
64
65class TSymbolTable : angle::NonCopyable, TSymbolTableBase
66{
67 public:
68 TSymbolTable();
69 // To start using the symbol table after construction:
70 // * initializeBuiltIns() needs to be called.
71 // * push() needs to be called to push the global level.
72
73 ~TSymbolTable();
74
75 bool isEmpty() const;
76 bool atGlobalLevel() const;
77
78 void push();
79 void pop();
80
81 // Declare a non-function symbol at the current scope. Return true in case the declaration was
82 // successful, and false if the declaration failed due to redefinition.
83 bool declare(TSymbol *symbol);
84
85 // Only used to declare internal variables.
86 bool declareInternal(TSymbol *symbol);
87
88 // Functions are always declared at global scope.
89 void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName);
90
91 // These return the TFunction pointer to keep using to refer to this function.
92 const TFunction *markFunctionHasPrototypeDeclaration(const ImmutableString &mangledName,
93 bool *hadPrototypeDeclarationOut) const;
94 const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function,
95 bool *wasDefinedOut) const;
96
97 // Return false if the gl_in array size has already been initialized with a mismatching value.
98 bool setGlInArraySize(unsigned int inputArraySize);
99 TVariable *getGlInVariableWithArraySize() const;
100
101 const TVariable *gl_FragData() const;
102 const TVariable *gl_SecondaryFragDataEXT() const;
103
104 void markStaticRead(const TVariable &variable);
105 void markStaticWrite(const TVariable &variable);
106
107 // Note: Should not call this for constant variables.
108 bool isStaticallyUsed(const TVariable &variable) const;
109
110 // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString
111 // with a reference to a short-lived char * is fine to pass here.
112 const TSymbol *find(const ImmutableString &name, int shaderVersion) const;
113
114 const TSymbol *findUserDefined(const ImmutableString &name) const;
115
116 TFunction *findUserDefinedFunction(const ImmutableString &name) const;
117
118 const TSymbol *findGlobal(const ImmutableString &name) const;
119
120 const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const;
121
122 void setDefaultPrecision(TBasicType type, TPrecision prec);
123
124 // Searches down the precisionStack for a precision qualifier
125 // for the specified TBasicType
126 TPrecision getDefaultPrecision(TBasicType type) const;
127
128 // This records invariant varyings declared through "invariant varying_name;".
129 void addInvariantVarying(const TVariable &variable);
130
131 // If this returns false, the varying could still be invariant if it is set as invariant during
132 // the varying variable declaration - this piece of information is stored in the variable's
133 // type, not here.
134 bool isVaryingInvariant(const TVariable &variable) const;
135
136 void setGlobalInvariant(bool invariant);
137
138 const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
139
140 // Gets the built-in accessible by a shader with the specified version, if any.
141 const UnmangledBuiltIn *getUnmangledBuiltInForShaderVersion(const ImmutableString &name,
142 int shaderVersion);
143
144 void initializeBuiltIns(sh::GLenum type,
145 ShShaderSpec spec,
146 const ShBuiltInResources &resources);
147 void clearCompilationResults();
148
149 private:
150 friend class TSymbolUniqueId;
151
152 struct VariableMetadata
153 {
154 VariableMetadata();
155 bool staticRead;
156 bool staticWrite;
157 bool invariant;
158 };
159
160 int nextUniqueIdValue();
161
162 class TSymbolTableLevel;
163
164 void initSamplerDefaultPrecision(TBasicType samplerType);
165
166 void initializeBuiltInVariables(sh::GLenum shaderType,
167 ShShaderSpec spec,
168 const ShBuiltInResources &resources);
169
170 VariableMetadata *getOrCreateVariableMetadata(const TVariable &variable);
171
172 std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
173
174 // There's one precision stack level for predefined precisions and then one level for each scope
175 // in table.
176 typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
177 std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack;
178
179 bool mGlobalInvariant;
180
181 int mUniqueIdCounter;
182
183 static const int kLastBuiltInId;
184
185 sh::GLenum mShaderType;
186 ShBuiltInResources mResources;
187
188 // Indexed by unique id. Map instead of vector since the variables are fairly sparse.
189 std::map<int, VariableMetadata> mVariableMetadata;
190
191 // Store gl_in variable with its array size once the array size can be determined. The array
192 // size can also be checked against latter input primitive type declaration.
193 TVariable *mGlInVariableWithArraySize;
194};
195
196} // namespace sh
197
198#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
199