• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 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 // Symbol.cpp: Symbols representing variables, functions, structures and interface blocks.
7 //
8 
9 #if defined(_MSC_VER)
10 #    pragma warning(disable : 4718)
11 #endif
12 
13 #include "compiler/translator/Symbol.h"
14 
15 #include "compiler/translator/ImmutableStringBuilder.h"
16 #include "compiler/translator/SymbolTable.h"
17 
18 namespace sh
19 {
20 
21 namespace
22 {
23 
24 constexpr const ImmutableString kMainName("main");
25 constexpr const ImmutableString kImageLoadName("imageLoad");
26 constexpr const ImmutableString kImageStoreName("imageStore");
27 constexpr const ImmutableString kImageSizeName("imageSize");
28 constexpr const ImmutableString kImageAtomicExchangeName("imageAtomicExchange");
29 constexpr const ImmutableString kAtomicCounterName("atomicCounter");
30 
31 static const char kFunctionMangledNameSeparator = '(';
32 
33 }  // anonymous namespace
34 
TSymbol(TSymbolTable * symbolTable,const ImmutableString & name,SymbolType symbolType,SymbolClass symbolClass,TExtension extension)35 TSymbol::TSymbol(TSymbolTable *symbolTable,
36                  const ImmutableString &name,
37                  SymbolType symbolType,
38                  SymbolClass symbolClass,
39                  TExtension extension)
40     : mName(name),
41       mUniqueId(symbolTable->nextUniqueId()),
42       mExtensions(
43           std::array<TExtension, 3u>{{extension, TExtension::UNDEFINED, TExtension::UNDEFINED}}),
44       mSymbolType(symbolType),
45       mSymbolClass(symbolClass)
46 {
47     ASSERT(mSymbolType == SymbolType::BuiltIn || extension == TExtension::UNDEFINED);
48     ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal ||
49            mSymbolType == SymbolType::Empty);
50 }
51 
TSymbol(TSymbolTable * symbolTable,const ImmutableString & name,SymbolType symbolType,SymbolClass symbolClass,const std::array<TExtension,3u> & extensions)52 TSymbol::TSymbol(TSymbolTable *symbolTable,
53                  const ImmutableString &name,
54                  SymbolType symbolType,
55                  SymbolClass symbolClass,
56                  const std::array<TExtension, 3u> &extensions)
57     : mName(name),
58       mUniqueId(symbolTable->nextUniqueId()),
59       mExtensions(extensions),
60       mSymbolType(symbolType),
61       mSymbolClass(symbolClass)
62 {
63     ASSERT(mSymbolType == SymbolType::BuiltIn || extensions[0] == TExtension::UNDEFINED);
64     ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal ||
65            mSymbolType == SymbolType::Empty);
66 }
67 
name() const68 ImmutableString TSymbol::name() const
69 {
70     if (!mName.empty())
71     {
72         return mName;
73     }
74     // This can be called for nameless function parameters in HLSL.
75     ASSERT(mSymbolType == SymbolType::AngleInternal ||
76            (mSymbolType == SymbolType::Empty && isVariable()));
77     int uniqueId = mUniqueId.get();
78     ImmutableStringBuilder symbolNameOut(sizeof(uniqueId) * 2u + 1u);
79     symbolNameOut << 's';
80     symbolNameOut.appendHex(mUniqueId.get());
81     return symbolNameOut;
82 }
83 
getMangledName() const84 ImmutableString TSymbol::getMangledName() const
85 {
86     if (mSymbolClass == SymbolClass::Function)
87     {
88         // We do this instead of using proper virtual functions so that we can better support
89         // constexpr symbols.
90         return static_cast<const TFunction *>(this)->getFunctionMangledName();
91     }
92     ASSERT(mSymbolType != SymbolType::Empty);
93     return name();
94 }
95 
TVariable(TSymbolTable * symbolTable,const ImmutableString & name,const TType * type,SymbolType symbolType,TExtension extension)96 TVariable::TVariable(TSymbolTable *symbolTable,
97                      const ImmutableString &name,
98                      const TType *type,
99                      SymbolType symbolType,
100                      TExtension extension)
101     : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extension),
102       mType(type),
103       unionArray(nullptr)
104 {
105     ASSERT(mType);
106     ASSERT(name.empty() || symbolType != SymbolType::Empty);
107 }
108 
TVariable(TSymbolTable * symbolTable,const ImmutableString & name,const TType * type,SymbolType symbolType,const std::array<TExtension,3u> & extensions)109 TVariable::TVariable(TSymbolTable *symbolTable,
110                      const ImmutableString &name,
111                      const TType *type,
112                      SymbolType symbolType,
113                      const std::array<TExtension, 3u> &extensions)
114     : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extensions),
115       mType(type),
116       unionArray(nullptr)
117 {
118     ASSERT(mType);
119     ASSERT(name.empty() || symbolType != SymbolType::Empty);
120 }
121 
TStructure(TSymbolTable * symbolTable,const ImmutableString & name,const TFieldList * fields,SymbolType symbolType)122 TStructure::TStructure(TSymbolTable *symbolTable,
123                        const ImmutableString &name,
124                        const TFieldList *fields,
125                        SymbolType symbolType)
126     : TSymbol(symbolTable, name, symbolType, SymbolClass::Struct), TFieldListCollection(fields)
127 {}
128 
createSamplerSymbols(const char * namePrefix,const TString & apiNamePrefix,TVector<const TVariable * > * outputSymbols,TMap<const TVariable *,TString> * outputSymbolsToAPINames,TSymbolTable * symbolTable) const129 void TStructure::createSamplerSymbols(const char *namePrefix,
130                                       const TString &apiNamePrefix,
131                                       TVector<const TVariable *> *outputSymbols,
132                                       TMap<const TVariable *, TString> *outputSymbolsToAPINames,
133                                       TSymbolTable *symbolTable) const
134 {
135     ASSERT(containsSamplers());
136     for (const auto *field : *mFields)
137     {
138         const TType *fieldType = field->type();
139         if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
140         {
141             std::stringstream fieldName = sh::InitializeStream<std::stringstream>();
142             fieldName << namePrefix << "_" << field->name();
143             TString fieldApiName = apiNamePrefix + ".";
144             fieldApiName += field->name().data();
145             fieldType->createSamplerSymbols(ImmutableString(fieldName.str()), fieldApiName,
146                                             outputSymbols, outputSymbolsToAPINames, symbolTable);
147         }
148     }
149 }
150 
setName(const ImmutableString & name)151 void TStructure::setName(const ImmutableString &name)
152 {
153     ImmutableString *mutableName = const_cast<ImmutableString *>(&mName);
154     *mutableName                 = name;
155 }
156 
TInterfaceBlock(TSymbolTable * symbolTable,const ImmutableString & name,const TFieldList * fields,const TLayoutQualifier & layoutQualifier,SymbolType symbolType,TExtension extension)157 TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
158                                  const ImmutableString &name,
159                                  const TFieldList *fields,
160                                  const TLayoutQualifier &layoutQualifier,
161                                  SymbolType symbolType,
162                                  TExtension extension)
163     : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extension),
164       TFieldListCollection(fields),
165       mBlockStorage(layoutQualifier.blockStorage),
166       mBinding(layoutQualifier.binding)
167 {
168     ASSERT(name != nullptr);
169 }
170 
TInterfaceBlock(TSymbolTable * symbolTable,const ImmutableString & name,const TFieldList * fields,const TLayoutQualifier & layoutQualifier,SymbolType symbolType,const std::array<TExtension,3u> & extensions)171 TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
172                                  const ImmutableString &name,
173                                  const TFieldList *fields,
174                                  const TLayoutQualifier &layoutQualifier,
175                                  SymbolType symbolType,
176                                  const std::array<TExtension, 3u> &extensions)
177     : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extensions),
178       TFieldListCollection(fields),
179       mBlockStorage(layoutQualifier.blockStorage),
180       mBinding(layoutQualifier.binding)
181 {
182     ASSERT(name != nullptr);
183 }
184 
TFunction(TSymbolTable * symbolTable,const ImmutableString & name,SymbolType symbolType,const TType * retType,bool knownToNotHaveSideEffects)185 TFunction::TFunction(TSymbolTable *symbolTable,
186                      const ImmutableString &name,
187                      SymbolType symbolType,
188                      const TType *retType,
189                      bool knownToNotHaveSideEffects)
190     : TSymbol(symbolTable, name, symbolType, SymbolClass::Function, TExtension::UNDEFINED),
191       mParametersVector(new TParamVector()),
192       mParameters(nullptr),
193       returnType(retType),
194       mMangledName(""),
195       mParamCount(0u),
196       mOp(EOpNull),
197       defined(false),
198       mHasPrototypeDeclaration(false),
199       mKnownToNotHaveSideEffects(knownToNotHaveSideEffects),
200       mHasVoidParameter(false)
201 {
202     // Functions with an empty name are not allowed.
203     ASSERT(symbolType != SymbolType::Empty);
204     ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal);
205 }
206 
addParameter(const TVariable * p)207 void TFunction::addParameter(const TVariable *p)
208 {
209     ASSERT(mParametersVector);
210     mParametersVector->push_back(p);
211     mParameters  = mParametersVector->data();
212     mParamCount  = mParametersVector->size();
213     mMangledName = kEmptyImmutableString;
214 }
215 
shareParameters(const TFunction & parametersSource)216 void TFunction::shareParameters(const TFunction &parametersSource)
217 {
218     mParametersVector = nullptr;
219     mParameters       = parametersSource.mParameters;
220     mParamCount       = parametersSource.mParamCount;
221     ASSERT(parametersSource.name() == name());
222     mMangledName = parametersSource.mMangledName;
223 }
224 
buildMangledName() const225 ImmutableString TFunction::buildMangledName() const
226 {
227     ImmutableString name = this->name();
228     std::string newName(name.data(), name.length());
229     newName += kFunctionMangledNameSeparator;
230 
231     for (size_t i = 0u; i < mParamCount; ++i)
232     {
233         newName += mParameters[i]->getType().getMangledName();
234     }
235     return ImmutableString(newName);
236 }
237 
isMain() const238 bool TFunction::isMain() const
239 {
240     return symbolType() == SymbolType::UserDefined && name() == kMainName;
241 }
242 
isImageFunction() const243 bool TFunction::isImageFunction() const
244 {
245     return symbolType() == SymbolType::BuiltIn &&
246            (name() == kImageSizeName || name() == kImageLoadName || name() == kImageStoreName ||
247             name() == kImageAtomicExchangeName);
248 }
249 
isAtomicCounterFunction() const250 bool TFunction::isAtomicCounterFunction() const
251 {
252     return SymbolType() == SymbolType::BuiltIn && name().beginsWith(kAtomicCounterName);
253 }
254 }  // namespace sh
255