blob: 0269efc80d8afc30a6ff40fcbe44ab68cbc9c4d4 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman66b8ab22014-05-06 15:57:45 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// 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
John Bauman66b8ab22014-05-06 15:57:45 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// 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.
John Bauman66b8ab22014-05-06 15:57:45 -040014
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
Nicolas Capenscc863da2015-01-21 15:50:55 -050024#include "SymbolTable.h"
John Bauman66b8ab22014-05-06 15:57:45 -040025
26#include <stdio.h>
Nicolas Capens94352d92015-06-11 08:53:40 -050027#include <limits.h>
John Bauman66b8ab22014-05-06 15:57:45 -040028#include <algorithm>
29
Nicolas Capens0b7471a2018-01-09 21:39:21 -050030#if defined(_MSC_VER) && MSC_VER < 1900
31#define snprintf _snprintf
John Bauman66b8ab22014-05-06 15:57:45 -040032#endif
33
John Baumand4ae8632014-05-06 16:18:33 -040034int TSymbolTableLevel::uniqueId = 0;
35
John Bauman66b8ab22014-05-06 15:57:45 -040036TType::TType(const TPublicType &p) :
Alexis Hetu29cb0032016-12-16 11:42:38 -050037 type(p.type), precision(p.precision), qualifier(p.qualifier), invariant(p.invariant), layoutQualifier(p.layoutQualifier),
Nicolas Capens0bac2852016-05-07 06:09:58 -040038 primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), maxArraySize(0),
39 arrayInformationType(0), interfaceBlock(0), structure(0), deepestStructNesting(0), mangled(0)
John Bauman66b8ab22014-05-06 15:57:45 -040040{
Nicolas Capens0bac2852016-05-07 06:09:58 -040041 if (p.userDef)
42 {
43 structure = p.userDef->getStruct();
44 computeDeepestStructNesting();
45 }
John Bauman66b8ab22014-05-06 15:57:45 -040046}
47
48//
49// Recursively generate mangled names.
50//
51void TType::buildMangledName(TString& mangledName)
52{
Nicolas Capens0bac2852016-05-07 06:09:58 -040053 if (isMatrix())
54 mangledName += 'm';
55 else if (isVector())
56 mangledName += 'v';
John Bauman66b8ab22014-05-06 15:57:45 -040057
Nicolas Capens0bac2852016-05-07 06:09:58 -040058 switch (type) {
59 case EbtFloat: mangledName += 'f'; break;
60 case EbtInt: mangledName += 'i'; break;
61 case EbtUInt: mangledName += 'u'; break;
62 case EbtBool: mangledName += 'b'; break;
63 case EbtSampler2D: mangledName += "s2"; break;
Alexis Hetub027aa92015-01-19 15:56:12 -050064 case EbtSampler3D: mangledName += "s3"; break;
Alexis Hetua8b364b2015-06-10 11:48:40 -040065 case EbtSamplerCube: mangledName += "sC"; break;
66 case EbtSampler2DArray: mangledName += "s2a"; break;
Alexis Hetu46768622018-01-16 22:09:28 -050067 case EbtSampler2DRect: mangledName += "s2r"; break;
Alexis Hetua8b364b2015-06-10 11:48:40 -040068 case EbtSamplerExternalOES: mangledName += "sext"; break;
69 case EbtISampler2D: mangledName += "is2"; break;
70 case EbtISampler3D: mangledName += "is3"; break;
71 case EbtISamplerCube: mangledName += "isC"; break;
72 case EbtISampler2DArray: mangledName += "is2a"; break;
73 case EbtUSampler2D: mangledName += "us2"; break;
74 case EbtUSampler3D: mangledName += "us3"; break;
75 case EbtUSamplerCube: mangledName += "usC"; break;
76 case EbtUSampler2DArray: mangledName += "us2a"; break;
77 case EbtSampler2DShadow: mangledName += "s2s"; break;
78 case EbtSamplerCubeShadow: mangledName += "sCs"; break;
79 case EbtSampler2DArrayShadow: mangledName += "s2as"; break;
80 case EbtStruct: mangledName += structure->mangledName(); break;
81 case EbtInterfaceBlock: mangledName += interfaceBlock->mangledName(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -040082 default:
83 break;
84 }
John Bauman66b8ab22014-05-06 15:57:45 -040085
Nicolas Capens0bac2852016-05-07 06:09:58 -040086 mangledName += static_cast<char>('0' + getNominalSize());
87 if(isMatrix()) {
88 mangledName += static_cast<char>('0' + getSecondarySize());
89 }
90 if (isArray()) {
91 char buf[20];
92 snprintf(buf, sizeof(buf), "%d", arraySize);
93 mangledName += '[';
94 mangledName += buf;
95 mangledName += ']';
96 }
John Bauman66b8ab22014-05-06 15:57:45 -040097}
98
Alexis Hetuab752792016-04-21 16:11:31 -040099size_t TType::getStructSize() const
John Bauman66b8ab22014-05-06 15:57:45 -0400100{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400101 if (!getStruct()) {
102 assert(false && "Not a struct");
103 return 0;
104 }
John Bauman66b8ab22014-05-06 15:57:45 -0400105
Nicolas Capens0bac2852016-05-07 06:09:58 -0400106 return getStruct()->objectSize();
John Bauman66b8ab22014-05-06 15:57:45 -0400107}
108
109void TType::computeDeepestStructNesting()
110{
Alexis Hetua8b364b2015-06-10 11:48:40 -0400111 deepestStructNesting = structure ? structure->deepestNesting() : 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400112}
113
Alexis Hetua8b364b2015-06-10 11:48:40 -0400114bool TStructure::containsArrays() const
John Bauman66b8ab22014-05-06 15:57:45 -0400115{
Alexis Hetud2742532018-01-23 16:53:41 -0500116 for(const auto& field : *mFields)
Alexis Hetua8b364b2015-06-10 11:48:40 -0400117 {
Alexis Hetud2742532018-01-23 16:53:41 -0500118 const TType *fieldType = field->type();
Alexis Hetua8b364b2015-06-10 11:48:40 -0400119 if(fieldType->isArray() || fieldType->isStructureContainingArrays())
120 return true;
121 }
122 return false;
123}
John Bauman66b8ab22014-05-06 15:57:45 -0400124
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500125bool TStructure::containsType(TBasicType type) const
126{
Alexis Hetud2742532018-01-23 16:53:41 -0500127 for(const auto& field : *mFields)
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500128 {
Alexis Hetud2742532018-01-23 16:53:41 -0500129 const TType *fieldType = field->type();
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500130 if(fieldType->getBasicType() == type || fieldType->isStructureContainingType(type))
131 return true;
132 }
133 return false;
134}
135
Alexis Hetua8b364b2015-06-10 11:48:40 -0400136bool TStructure::containsSamplers() const
137{
Alexis Hetud2742532018-01-23 16:53:41 -0500138 for(const auto& field : *mFields)
Alexis Hetua8b364b2015-06-10 11:48:40 -0400139 {
Alexis Hetud2742532018-01-23 16:53:41 -0500140 const TType *fieldType = field->type();
Alexis Hetua8b364b2015-06-10 11:48:40 -0400141 if(IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
142 return true;
143 }
144 return false;
145}
John Bauman66b8ab22014-05-06 15:57:45 -0400146
Alexis Hetud2742532018-01-23 16:53:41 -0500147void TStructure::setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking)
148{
149 for(auto& field : *mFields)
150 {
151 field->type()->setMatrixPackingIfUnspecified(matrixPacking);
152 }
153}
154
Alexis Hetua8b364b2015-06-10 11:48:40 -0400155TString TFieldListCollection::buildMangledName() const
156{
157 TString mangledName(mangledNamePrefix());
158 mangledName += *mName;
Alexis Hetud2742532018-01-23 16:53:41 -0500159 for(const auto& field : *mFields)
Alexis Hetua8b364b2015-06-10 11:48:40 -0400160 {
161 mangledName += '-';
Alexis Hetud2742532018-01-23 16:53:41 -0500162 mangledName += field->type()->getMangledName();
Alexis Hetua8b364b2015-06-10 11:48:40 -0400163 }
164 return mangledName;
165}
166
167size_t TFieldListCollection::calculateObjectSize() const
168{
169 size_t size = 0;
Alexis Hetud2742532018-01-23 16:53:41 -0500170 for(const auto& field : *mFields)
Alexis Hetua8b364b2015-06-10 11:48:40 -0400171 {
Alexis Hetud2742532018-01-23 16:53:41 -0500172 size_t fieldSize = field->type()->getObjectSize();
Alexis Hetua8b364b2015-06-10 11:48:40 -0400173 if(fieldSize > INT_MAX - size)
174 size = INT_MAX;
175 else
176 size += fieldSize;
177 }
178 return size;
179}
180
181int TStructure::calculateDeepestNesting() const
182{
183 int maxNesting = 0;
Alexis Hetud2742532018-01-23 16:53:41 -0500184 for(const auto& field : *mFields)
185 maxNesting = std::max(maxNesting, field->type()->getDeepestStructNesting());
Alexis Hetua8b364b2015-06-10 11:48:40 -0400186 return 1 + maxNesting;
John Bauman66b8ab22014-05-06 15:57:45 -0400187}
188
189//
John Bauman66b8ab22014-05-06 15:57:45 -0400190// Functions have buried pointers to delete.
191//
192TFunction::~TFunction()
193{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400194 for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
195 delete (*i).type;
John Bauman66b8ab22014-05-06 15:57:45 -0400196}
197
198//
199// Symbol table levels are a map of pointers to symbols that have to be deleted.
200//
201TSymbolTableLevel::~TSymbolTableLevel()
202{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400203 for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
204 delete (*it).second;
John Bauman66b8ab22014-05-06 15:57:45 -0400205}
206
Nicolas Capens0b7471a2018-01-09 21:39:21 -0500207bool TSymbolTableLevel::insert(TSymbol *symbol)
208{
209 symbol->setUniqueId(nextUniqueId());
210
211 // returning true means symbol was added to the table
212 tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
213
214 return result.second;
215}
216
217bool TSymbolTableLevel::insertUnmangled(TFunction *function)
218{
219 function->setUniqueId(nextUniqueId());
220
221 // returning true means symbol was added to the table
222 tInsertResult result = level.insert(tLevelPair(function->getName(), function));
223
224 return result.second;
225}
226
227TSymbol *TSymbolTableLevel::find(const TString &name) const
228{
229 tLevel::const_iterator it = level.find(name);
230 if (it == level.end())
231 return 0;
232 else
233 return (*it).second;
234}
235
Nicolas Capense2858652015-02-18 15:30:51 -0500236TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) const
237{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400238 int level = currentLevel();
239 TSymbol *symbol = nullptr;
Nicolas Capense2858652015-02-18 15:30:51 -0500240
Nicolas Capens0bac2852016-05-07 06:09:58 -0400241 do
242 {
243 while((level == ESSL3_BUILTINS && shaderVersion != 300) ||
244 (level == ESSL1_BUILTINS && shaderVersion != 100)) // Skip version specific levels
245 {
246 --level;
247 }
Nicolas Capense2858652015-02-18 15:30:51 -0500248
Nicolas Capens0bac2852016-05-07 06:09:58 -0400249 symbol = table[level]->find(name);
250 }
251 while(!symbol && --level >= 0); // Doesn't decrement level when a symbol was found
Nicolas Capense2858652015-02-18 15:30:51 -0500252
Nicolas Capens0bac2852016-05-07 06:09:58 -0400253 if(builtIn)
254 {
255 *builtIn = (level <= LAST_BUILTIN_LEVEL);
256 }
Nicolas Capense2858652015-02-18 15:30:51 -0500257
Nicolas Capens0bac2852016-05-07 06:09:58 -0400258 if(sameScope)
259 {
260 *sameScope = (level == currentLevel());
261 }
Nicolas Capense2858652015-02-18 15:30:51 -0500262
Nicolas Capens0bac2852016-05-07 06:09:58 -0400263 return symbol;
Nicolas Capense2858652015-02-18 15:30:51 -0500264}
265
266TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
267{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400268 for(int level = LAST_BUILTIN_LEVEL; level >= 0; --level)
269 {
270 while((level == ESSL3_BUILTINS && shaderVersion != 300) ||
271 (level == ESSL1_BUILTINS && shaderVersion != 100)) // Skip version specific levels
272 {
273 --level;
274 }
Nicolas Capens3d7f6ed2015-02-18 16:34:50 -0500275
Nicolas Capens0bac2852016-05-07 06:09:58 -0400276 TSymbol *symbol = table[level]->find(name);
Nicolas Capens3d7f6ed2015-02-18 16:34:50 -0500277
Nicolas Capens0bac2852016-05-07 06:09:58 -0400278 if(symbol)
279 {
280 return symbol;
281 }
282 }
Nicolas Capens3d7f6ed2015-02-18 16:34:50 -0500283
Nicolas Capens0bac2852016-05-07 06:09:58 -0400284 return 0;
Nicolas Capense2858652015-02-18 15:30:51 -0500285}
286
John Bauman66b8ab22014-05-06 15:57:45 -0400287TSymbol::TSymbol(const TSymbol& copyOf)
288{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400289 name = NewPoolTString(copyOf.name->c_str());
John Bauman66b8ab22014-05-06 15:57:45 -0400290}