| // 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()); | |
| } |