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 {
201     // Functions with an empty name are not allowed.
202     ASSERT(symbolType != SymbolType::Empty);
203     ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal);
204 }
205 
addParameter(const TVariable * p)206 void TFunction::addParameter(const TVariable *p)
207 {
208     ASSERT(mParametersVector);
209     mParametersVector->push_back(p);
210     mParameters  = mParametersVector->data();
211     mParamCount  = mParametersVector->size();
212     mMangledName = kEmptyImmutableString;
213 }
214 
shareParameters(const TFunction & parametersSource)215 void TFunction::shareParameters(const TFunction &parametersSource)
216 {
217     mParametersVector = nullptr;
218     mParameters       = parametersSource.mParameters;
219     mParamCount       = parametersSource.mParamCount;
220     ASSERT(parametersSource.name() == name());
221     mMangledName = parametersSource.mMangledName;
222 }
223 
buildMangledName() const224 ImmutableString TFunction::buildMangledName() const
225 {
226     ImmutableString name = this->name();
227     std::string newName(name.data(), name.length());
228     newName += kFunctionMangledNameSeparator;
229 
230     for (size_t i = 0u; i < mParamCount; ++i)
231     {
232         newName += mParameters[i]->getType().getMangledName();
233     }
234     return ImmutableString(newName);
235 }
236 
isMain() const237 bool TFunction::isMain() const
238 {
239     return symbolType() == SymbolType::UserDefined && name() == kMainName;
240 }
241 
isImageFunction() const242 bool TFunction::isImageFunction() const
243 {
244     return symbolType() == SymbolType::BuiltIn &&
245            (name() == kImageSizeName || name() == kImageLoadName || name() == kImageStoreName ||
246             name() == kImageAtomicExchangeName);
247 }
248 
isAtomicCounterFunction() const249 bool TFunction::isAtomicCounterFunction() const
250 {
251     return SymbolType() == SymbolType::BuiltIn && name().beginsWith(kAtomicCounterName);
252 }
253 }  // namespace sh
254