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