blob: 51180aff663d87122c09b960754c96b4c4cf2d0e [file] [log] [blame]
//
// 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 <stdio.h>
#include <algorithm>
#include <climits>
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<char>('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<TFunction*>((*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);
}
}