|  | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | // | 
|  | // Symbol table for parsing.  Most functionaliy and main ideas | 
|  | // are documented in the header file. | 
|  | // | 
|  |  | 
|  | #if defined(_MSC_VER) | 
|  | #pragma warning(disable: 4718) | 
|  | #endif | 
|  |  | 
|  | #include "SymbolTable.h" | 
|  |  | 
|  | #include <stdio.h> | 
|  | #include <limits.h> | 
|  | #include <algorithm> | 
|  |  | 
|  | #if defined(_MSC_VER) && MSC_VER < 1900 | 
|  | #define snprintf _snprintf | 
|  | #endif | 
|  |  | 
|  | int TSymbolTableLevel::uniqueId = 0; | 
|  |  | 
|  | TType::TType(const TPublicType &p) : | 
|  | type(p.type), precision(p.precision), qualifier(p.qualifier), | 
|  | primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), maxArraySize(0), | 
|  | arrayInformationType(0), interfaceBlock(0), layoutQualifier(p.layoutQualifier), structure(0), mangled(0) | 
|  | { | 
|  | if (p.userDef) | 
|  | { | 
|  | structure = p.userDef->getStruct(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // | 
|  | // Recursively generate mangled names. | 
|  | // | 
|  | void TType::buildMangledName(TString& mangledName) | 
|  | { | 
|  | if (isMatrix()) | 
|  | mangledName += 'm'; | 
|  | else if (isVector()) | 
|  | mangledName += 'v'; | 
|  |  | 
|  | switch (type) { | 
|  | case EbtFloat:              mangledName += 'f';      break; | 
|  | case EbtInt:                mangledName += 'i';      break; | 
|  | case EbtUInt:               mangledName += 'u';      break; | 
|  | case EbtBool:               mangledName += 'b';      break; | 
|  | case EbtSampler2D:          mangledName += "s2";     break; | 
|  | case EbtSampler3D:          mangledName += "s3";     break; | 
|  | case EbtSamplerCube:        mangledName += "sC";     break; | 
|  | case EbtSampler2DArray:		mangledName += "s2a";    break; | 
|  | case EbtSampler2DRect:      mangledName += "s2r";    break; | 
|  | case EbtSamplerExternalOES: mangledName += "sext";   break; | 
|  | case EbtISampler2D:  		mangledName += "is2";    break; | 
|  | case EbtISampler3D: 		mangledName += "is3";    break; | 
|  | case EbtISamplerCube:		mangledName += "isC";    break; | 
|  | case EbtISampler2DArray:	mangledName += "is2a";   break; | 
|  | case EbtUSampler2D: 		mangledName += "us2";    break; | 
|  | case EbtUSampler3D:  		mangledName += "us3";    break; | 
|  | case EbtUSamplerCube:		mangledName += "usC";    break; | 
|  | case EbtUSampler2DArray:	mangledName += "us2a";   break; | 
|  | case EbtSampler2DShadow:	mangledName += "s2s";    break; | 
|  | case EbtSamplerCubeShadow:  mangledName += "sCs";    break; | 
|  | case EbtSampler2DArrayShadow: mangledName += "s2as"; break; | 
|  | case EbtStruct:             mangledName += structure->mangledName(); break; | 
|  | case EbtInterfaceBlock:	    mangledName += interfaceBlock->mangledName(); break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | mangledName += static_cast<char>('0' + getNominalSize()); | 
|  | if(isMatrix()) { | 
|  | mangledName += static_cast<char>('0' + getSecondarySize()); | 
|  | } | 
|  | if (isArray()) { | 
|  | char buf[20]; | 
|  | snprintf(buf, sizeof(buf), "%d", arraySize); | 
|  | mangledName += '['; | 
|  | mangledName += buf; | 
|  | mangledName += ']'; | 
|  | } | 
|  | } | 
|  |  | 
|  | size_t TType::getStructSize() const | 
|  | { | 
|  | if (!getStruct()) { | 
|  | assert(false && "Not a struct"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | return getStruct()->objectSize(); | 
|  | } | 
|  |  | 
|  | bool TStructure::containsArrays() const | 
|  | { | 
|  | for(const auto& field : *mFields) | 
|  | { | 
|  | const TType *fieldType = field->type(); | 
|  | if(fieldType->isArray() || fieldType->isStructureContainingArrays()) | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool TStructure::containsType(TBasicType type) const | 
|  | { | 
|  | for(const auto& field : *mFields) | 
|  | { | 
|  | const TType *fieldType = field->type(); | 
|  | if(fieldType->getBasicType() == type || fieldType->isStructureContainingType(type)) | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool TStructure::containsSamplers() const | 
|  | { | 
|  | for(const auto& field : *mFields) | 
|  | { | 
|  | const TType *fieldType = field->type(); | 
|  | if(IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void TStructure::setMatrixPackingIfUnspecified(TLayoutMatrixPacking matrixPacking) | 
|  | { | 
|  | for(auto& field : *mFields) | 
|  | { | 
|  | field->type()->setMatrixPackingIfUnspecified(matrixPacking); | 
|  | } | 
|  | } | 
|  |  | 
|  | TString TFieldListCollection::buildMangledName() const | 
|  | { | 
|  | TString mangledName(mangledNamePrefix()); | 
|  | mangledName += *mName; | 
|  | for(const auto& field : *mFields) | 
|  | { | 
|  | mangledName += '-'; | 
|  | mangledName += field->type()->getMangledName(); | 
|  | } | 
|  | return mangledName; | 
|  | } | 
|  |  | 
|  | size_t TFieldListCollection::calculateObjectSize() const | 
|  | { | 
|  | size_t size = 0; | 
|  | for(const auto& field : *mFields) | 
|  | { | 
|  | size_t fieldSize = field->type()->getObjectSize(); | 
|  | if(fieldSize > INT_MAX - size) | 
|  | size = INT_MAX; | 
|  | else | 
|  | size += fieldSize; | 
|  | } | 
|  | return size; | 
|  | } | 
|  |  | 
|  | int TStructure::calculateDeepestNesting() const | 
|  | { | 
|  | int maxNesting = 0; | 
|  | for(const auto& field : *mFields) | 
|  | maxNesting = std::max(maxNesting, field->type()->getDeepestStructNesting()); | 
|  | return 1 + maxNesting; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Functions have buried pointers to delete. | 
|  | // | 
|  | TFunction::~TFunction() | 
|  | { | 
|  | for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) | 
|  | delete (*i).type; | 
|  | } | 
|  |  | 
|  | // | 
|  | // Symbol table levels are a map of pointers to symbols that have to be deleted. | 
|  | // | 
|  | TSymbolTableLevel::~TSymbolTableLevel() | 
|  | { | 
|  | for (tLevel::iterator it = level.begin(); it != level.end(); ++it) | 
|  | delete (*it).second; | 
|  | } | 
|  |  | 
|  | bool TSymbolTableLevel::insert(TSymbol *symbol) | 
|  | { | 
|  | symbol->setUniqueId(nextUniqueId()); | 
|  |  | 
|  | // returning true means symbol was added to the table | 
|  | tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol)); | 
|  |  | 
|  | return result.second; | 
|  | } | 
|  |  | 
|  | bool TSymbolTableLevel::insertUnmangled(TFunction *function) | 
|  | { | 
|  | function->setUniqueId(nextUniqueId()); | 
|  |  | 
|  | // returning true means symbol was added to the table | 
|  | tInsertResult result = level.insert(tLevelPair(function->getName(), function)); | 
|  |  | 
|  | return result.second; | 
|  | } | 
|  |  | 
|  | TSymbol *TSymbolTableLevel::find(const TString &name) const | 
|  | { | 
|  | tLevel::const_iterator it = level.find(name); | 
|  | if (it == level.end()) | 
|  | return 0; | 
|  | else | 
|  | return (*it).second; | 
|  | } | 
|  |  | 
|  | TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) const | 
|  | { | 
|  | int level = currentLevel(); | 
|  | TSymbol *symbol = nullptr; | 
|  |  | 
|  | do | 
|  | { | 
|  | while((level == ESSL3_BUILTINS && shaderVersion != 300) || | 
|  | (level == ESSL1_BUILTINS && shaderVersion != 100))   // Skip version specific levels | 
|  | { | 
|  | --level; | 
|  | } | 
|  |  | 
|  | symbol = table[level]->find(name); | 
|  | } | 
|  | while(!symbol && --level >= 0);   // Doesn't decrement level when a symbol was found | 
|  |  | 
|  | if(builtIn) | 
|  | { | 
|  | *builtIn = (level <= LAST_BUILTIN_LEVEL); | 
|  | } | 
|  |  | 
|  | if(sameScope) | 
|  | { | 
|  | *sameScope = (level == currentLevel()); | 
|  | } | 
|  |  | 
|  | return symbol; | 
|  | } | 
|  |  | 
|  | TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const | 
|  | { | 
|  | for(int level = LAST_BUILTIN_LEVEL; level >= 0; --level) | 
|  | { | 
|  | while((level == ESSL3_BUILTINS && shaderVersion != 300) || | 
|  | (level == ESSL1_BUILTINS && shaderVersion != 100))   // Skip version specific levels | 
|  | { | 
|  | --level; | 
|  | } | 
|  |  | 
|  | TSymbol *symbol = table[level]->find(name); | 
|  |  | 
|  | if(symbol) | 
|  | { | 
|  | return symbol; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | TSymbol::TSymbol(const TSymbol& copyOf) | 
|  | { | 
|  | name = NewPoolTString(copyOf.name->c_str()); | 
|  | } |