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