1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//
16// Symbol table for parsing.  Most functionaliy and main ideas
17// are documented in the header file.
18//
19
20#if defined(_MSC_VER)
21#pragma warning(disable: 4718)
22#endif
23
24#include "SymbolTable.h"
25
26#include <stdio.h>
27#include <limits.h>
28#include <algorithm>
29
30#if defined(_MSC_VER) && MSC_VER < 1900
31#define snprintf _snprintf
32#endif
33
34int TSymbolTableLevel::uniqueId = 0;
35
36TType::TType(const TPublicType &p) :
37	type(p.type), precision(p.precision), qualifier(p.qualifier),
38	primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), maxArraySize(0),
39	arrayInformationType(0), interfaceBlock(0), layoutQualifier(p.layoutQualifier), structure(0), mangled(0)
40{
41	if (p.userDef)
42	{
43		structure = p.userDef->getStruct();
44	}
45}
46
47//
48// Recursively generate mangled names.
49//
50void TType::buildMangledName(TString& mangledName)
51{
52	if (isMatrix())
53		mangledName += 'm';
54	else if (isVector())
55		mangledName += 'v';
56
57	switch (type) {
58	case EbtFloat:              mangledName += 'f';      break;
59	case EbtInt:                mangledName += 'i';      break;
60	case EbtUInt:               mangledName += 'u';      break;
61	case EbtBool:               mangledName += 'b';      break;
62	case EbtSampler2D:          mangledName += "s2";     break;
63	case EbtSampler3D:          mangledName += "s3";     break;
64	case EbtSamplerCube:        mangledName += "sC";     break;
65	case EbtSampler2DArray:		mangledName += "s2a";    break;
66	case EbtSampler2DRect:      mangledName += "s2r";    break;
67	case EbtSamplerExternalOES: mangledName += "sext";   break;
68	case EbtISampler2D:  		mangledName += "is2";    break;
69	case EbtISampler3D: 		mangledName += "is3";    break;
70	case EbtISamplerCube:		mangledName += "isC";    break;
71	case EbtISampler2DArray:	mangledName += "is2a";   break;
72	case EbtUSampler2D: 		mangledName += "us2";    break;
73	case EbtUSampler3D:  		mangledName += "us3";    break;
74	case EbtUSamplerCube:		mangledName += "usC";    break;
75	case EbtUSampler2DArray:	mangledName += "us2a";   break;
76	case EbtSampler2DShadow:	mangledName += "s2s";    break;
77	case EbtSamplerCubeShadow:  mangledName += "sCs";    break;
78	case EbtSampler2DArrayShadow: mangledName += "s2as"; break;
79	case EbtStruct:             mangledName += structure->mangledName(); break;
80	case EbtInterfaceBlock:	    mangledName += interfaceBlock->mangledName(); break;
81	default:
82		break;
83	}
84
85	mangledName += static_cast<char>('0' + getNominalSize());
86	if(isMatrix()) {
87		mangledName += static_cast<char>('0' + getSecondarySize());
88	}
89	if (isArray()) {
90		char buf[20];
91		snprintf(buf, sizeof(buf), "%d", arraySize);
92		mangledName += '[';
93		mangledName += buf;
94		mangledName += ']';
95	}
96}
97
98size_t TType::getStructSize() const
99{
100	if (!getStruct()) {
101		assert(false && "Not a struct");
102		return 0;
103	}
104
105	return getStruct()->objectSize();
106}
107
108bool TStructure::containsArrays() const
109{
110	for(const auto& field : *mFields)
111	{
112		const TType *fieldType = field->type();
113		if(fieldType->isArray() || fieldType->isStructureContainingArrays())
114			return true;
115	}
116	return false;
117}
118
119bool TStructure::containsType(TBasicType type) const
120{
121	for(const auto& field : *mFields)
122	{
123		const TType *fieldType = field->type();
124		if(fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
125			return true;
126	}
127	return false;
128}
129
130bool TStructure::containsSamplers() const
131{
132	for(const auto& field : *mFields)
133	{
134		const TType *fieldType = field->type();
135		if(IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
136			return true;
137	}
138	return false;
139}
140
141void TStructure::setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking)
142{
143	for(auto& field : *mFields)
144	{
145		field->type()->setMatrixPackingIfUnspecified(matrixPacking);
146	}
147}
148
149TString TFieldListCollection::buildMangledName() const
150{
151	TString mangledName(mangledNamePrefix());
152	mangledName += *mName;
153	for(const auto& field : *mFields)
154	{
155		mangledName += '-';
156		mangledName += field->type()->getMangledName();
157	}
158	return mangledName;
159}
160
161size_t TFieldListCollection::calculateObjectSize() const
162{
163	size_t size = 0;
164	for(const auto& field : *mFields)
165	{
166		size_t fieldSize = field->type()->getObjectSize();
167		if(fieldSize > INT_MAX - size)
168			size = INT_MAX;
169		else
170			size += fieldSize;
171	}
172	return size;
173}
174
175int TStructure::calculateDeepestNesting() const
176{
177	int maxNesting = 0;
178	for(const auto& field : *mFields)
179		maxNesting = std::max(maxNesting, field->type()->getDeepestStructNesting());
180	return 1 + maxNesting;
181}
182
183//
184// Functions have buried pointers to delete.
185//
186TFunction::~TFunction()
187{
188	for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
189		delete (*i).type;
190}
191
192//
193// Symbol table levels are a map of pointers to symbols that have to be deleted.
194//
195TSymbolTableLevel::~TSymbolTableLevel()
196{
197	for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
198		delete (*it).second;
199}
200
201bool TSymbolTableLevel::insert(TSymbol *symbol)
202{
203	symbol->setUniqueId(nextUniqueId());
204
205	// returning true means symbol was added to the table
206	tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
207
208	return result.second;
209}
210
211bool TSymbolTableLevel::insertUnmangled(TFunction *function)
212{
213	function->setUniqueId(nextUniqueId());
214
215	// returning true means symbol was added to the table
216	tInsertResult result = level.insert(tLevelPair(function->getName(), function));
217
218	return result.second;
219}
220
221TSymbol *TSymbolTableLevel::find(const TString &name) const
222{
223	tLevel::const_iterator it = level.find(name);
224	if (it == level.end())
225		return 0;
226	else
227		return (*it).second;
228}
229
230TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) const
231{
232	int level = currentLevel();
233	TSymbol *symbol = nullptr;
234
235	do
236	{
237		while((level == ESSL3_BUILTINS && shaderVersion != 300) ||
238		      (level == ESSL1_BUILTINS && shaderVersion != 100))   // Skip version specific levels
239		{
240			--level;
241		}
242
243		symbol = table[level]->find(name);
244	}
245	while(!symbol && --level >= 0);   // Doesn't decrement level when a symbol was found
246
247	if(builtIn)
248	{
249		*builtIn = (level <= LAST_BUILTIN_LEVEL);
250	}
251
252	if(sameScope)
253	{
254		*sameScope = (level == currentLevel());
255	}
256
257	return symbol;
258}
259
260TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
261{
262	for(int level = LAST_BUILTIN_LEVEL; level >= 0; --level)
263	{
264		while((level == ESSL3_BUILTINS && shaderVersion != 300) ||
265		      (level == ESSL1_BUILTINS && shaderVersion != 100))   // Skip version specific levels
266		{
267			--level;
268		}
269
270		TSymbol *symbol = table[level]->find(name);
271
272		if(symbol)
273		{
274			return symbol;
275		}
276	}
277
278	return 0;
279}
280
281TSymbol::TSymbol(const TSymbol& copyOf)
282{
283	name = NewPoolTString(copyOf.name->c_str());
284}
285