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