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