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