// // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // // 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 "compiler/SymbolTable.h" #include #include #include TType::TType(const TPublicType &p) : type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0) { if (p.userDef) structure = p.userDef->getStruct(); } // // Recursively generate mangled names. // TString TType::buildMangledName() const { TString mangledName; if (isMatrix()) mangledName += 'm'; else if (isVector()) mangledName += 'v'; switch (type) { case EbtFloat: mangledName += 'f'; break; case EbtInt: mangledName += 'i'; break; case EbtBool: mangledName += 'b'; break; case EbtSampler2D: mangledName += "s2"; break; case EbtSamplerCube: mangledName += "sC"; break; case EbtStruct: mangledName += structure->mangledName(); break; default: break; } mangledName += static_cast('0' + getNominalSize()); if (isArray()) { char buf[20]; snprintf(buf, sizeof(buf), "%d", arraySize); mangledName += '['; mangledName += buf; mangledName += ']'; } return mangledName; } size_t TType::getObjectSize() const { size_t totalSize = 0; if (getBasicType() == EbtStruct) totalSize = structure->objectSize(); else if (matrix) totalSize = size * size; else totalSize = size; if (isArray()) { size_t arraySize = getArraySize(); if (arraySize > INT_MAX / totalSize) totalSize = INT_MAX; else totalSize *= arraySize; } return totalSize; } bool TStructure::containsArrays() const { for (size_t i = 0; i < mFields->size(); ++i) { const TType* fieldType = (*mFields)[i]->type(); if (fieldType->isArray() || fieldType->isStructureContainingArrays()) return true; } return false; } TString TStructure::buildMangledName() const { TString mangledName("struct-"); mangledName += *mName; for (size_t i = 0; i < mFields->size(); ++i) { mangledName += '-'; mangledName += (*mFields)[i]->type()->getMangledName(); } return mangledName; } size_t TStructure::calculateObjectSize() const { size_t size = 0; for (size_t i = 0; i < mFields->size(); ++i) { size_t fieldSize = (*mFields)[i]->type()->getObjectSize(); if (fieldSize > INT_MAX - size) size = INT_MAX; else size += fieldSize; } return size; } int TStructure::calculateDeepestNesting() const { int maxNesting = 0; for (size_t i = 0; i < mFields->size(); ++i) { maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); } return 1 + maxNesting; } // // Dump functions. // void TVariable::dump(TInfoSink& infoSink) const { infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString(); if (type.isArray()) { infoSink.debug << "[0]"; } infoSink.debug << "\n"; } void TFunction::dump(TInfoSink &infoSink) const { infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n"; } void TSymbolTableLevel::dump(TInfoSink &infoSink) const { tLevel::const_iterator it; for (it = level.begin(); it != level.end(); ++it) (*it).second->dump(infoSink); } void TSymbolTable::dump(TInfoSink &infoSink) const { for (int level = currentLevel(); level >= 0; --level) { infoSink.debug << "LEVEL " << level << "\n"; table[level]->dump(infoSink); } } // // 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; } // // Change all function entries in the table with the non-mangled name // to be related to the provided built-in operation. This is a low // performance operation, and only intended for symbol tables that // live across a large number of compiles. // void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) { tLevel::iterator it; for (it = level.begin(); it != level.end(); ++it) { if ((*it).second->isFunction()) { TFunction* function = static_cast((*it).second); if (function->getName() == name) function->relateToOperator(op); } } } // // Change all function entries in the table with the non-mangled name // to be related to the provided built-in extension. This is a low // performance operation, and only intended for symbol tables that // live across a large number of compiles. // void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) { for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { TSymbol* symbol = it->second; if (symbol->getName() == name) symbol->relateToExtension(ext); } } TSymbolTable::~TSymbolTable() { for (size_t i = 0; i < table.size(); ++i) delete table[i]; for (size_t i = 0; i < precisionStack.size(); ++i) delete precisionStack[i]; }