1//
2// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Symbol table for parsing.  Most functionaliy and main ideas
9// are documented in the header file.
10//
11
12#if defined(_MSC_VER)
13#pragma warning(disable: 4718)
14#endif
15
16#include "compiler/SymbolTable.h"
17
18#include <stdio.h>
19#include <algorithm>
20#include <climits>
21
22TType::TType(const TPublicType &p) :
23            type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0)
24{
25    if (p.userDef)
26        structure = p.userDef->getStruct();
27}
28
29//
30// Recursively generate mangled names.
31//
32TString TType::buildMangledName() const
33{
34    TString mangledName;
35    if (isMatrix())
36        mangledName += 'm';
37    else if (isVector())
38        mangledName += 'v';
39
40    switch (type) {
41    case EbtFloat:       mangledName += 'f';      break;
42    case EbtInt:         mangledName += 'i';      break;
43    case EbtBool:        mangledName += 'b';      break;
44    case EbtSampler2D:   mangledName += "s2";     break;
45    case EbtSamplerCube: mangledName += "sC";     break;
46    case EbtStruct:      mangledName += structure->mangledName(); break;
47    default:             break;
48    }
49
50    mangledName += static_cast<char>('0' + getNominalSize());
51    if (isArray()) {
52        char buf[20];
53        snprintf(buf, sizeof(buf), "%d", arraySize);
54        mangledName += '[';
55        mangledName += buf;
56        mangledName += ']';
57    }
58    return mangledName;
59}
60
61size_t TType::getObjectSize() const
62{
63    size_t totalSize = 0;
64
65    if (getBasicType() == EbtStruct)
66        totalSize = structure->objectSize();
67    else if (matrix)
68        totalSize = size * size;
69    else
70        totalSize = size;
71
72    if (isArray()) {
73        size_t arraySize = getArraySize();
74        if (arraySize > INT_MAX / totalSize)
75            totalSize = INT_MAX;
76        else
77            totalSize *= arraySize;
78    }
79
80    return totalSize;
81}
82
83bool TStructure::containsArrays() const
84{
85    for (size_t i = 0; i < mFields->size(); ++i) {
86        const TType* fieldType = (*mFields)[i]->type();
87        if (fieldType->isArray() || fieldType->isStructureContainingArrays())
88            return true;
89    }
90    return false;
91}
92
93TString TStructure::buildMangledName() const
94{
95    TString mangledName("struct-");
96    mangledName += *mName;
97    for (size_t i = 0; i < mFields->size(); ++i) {
98        mangledName += '-';
99        mangledName += (*mFields)[i]->type()->getMangledName();
100    }
101    return mangledName;
102}
103
104size_t TStructure::calculateObjectSize() const
105{
106    size_t size = 0;
107    for (size_t i = 0; i < mFields->size(); ++i) {
108        size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
109        if (fieldSize > INT_MAX - size)
110            size = INT_MAX;
111        else
112            size += fieldSize;
113    }
114    return size;
115}
116
117int TStructure::calculateDeepestNesting() const
118{
119    int maxNesting = 0;
120    for (size_t i = 0; i < mFields->size(); ++i) {
121        maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
122    }
123    return 1 + maxNesting;
124}
125
126//
127// Dump functions.
128//
129
130void TVariable::dump(TInfoSink& infoSink) const
131{
132    infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
133    if (type.isArray()) {
134        infoSink.debug << "[0]";
135    }
136    infoSink.debug << "\n";
137}
138
139void TFunction::dump(TInfoSink &infoSink) const
140{
141    infoSink.debug << getName().c_str() << ": " <<  returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
142}
143
144void TSymbolTableLevel::dump(TInfoSink &infoSink) const
145{
146    tLevel::const_iterator it;
147    for (it = level.begin(); it != level.end(); ++it)
148        (*it).second->dump(infoSink);
149}
150
151void TSymbolTable::dump(TInfoSink &infoSink) const
152{
153    for (int level = currentLevel(); level >= 0; --level) {
154        infoSink.debug << "LEVEL " << level << "\n";
155        table[level]->dump(infoSink);
156    }
157}
158
159//
160// Functions have buried pointers to delete.
161//
162TFunction::~TFunction()
163{
164    for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
165        delete (*i).type;
166}
167
168//
169// Symbol table levels are a map of pointers to symbols that have to be deleted.
170//
171TSymbolTableLevel::~TSymbolTableLevel()
172{
173    for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
174        delete (*it).second;
175}
176
177//
178// Change all function entries in the table with the non-mangled name
179// to be related to the provided built-in operation.  This is a low
180// performance operation, and only intended for symbol tables that
181// live across a large number of compiles.
182//
183void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
184{
185    tLevel::iterator it;
186    for (it = level.begin(); it != level.end(); ++it) {
187        if ((*it).second->isFunction()) {
188            TFunction* function = static_cast<TFunction*>((*it).second);
189            if (function->getName() == name)
190                function->relateToOperator(op);
191        }
192    }
193}
194
195//
196// Change all function entries in the table with the non-mangled name
197// to be related to the provided built-in extension. This is a low
198// performance operation, and only intended for symbol tables that
199// live across a large number of compiles.
200//
201void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
202{
203    for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
204        TSymbol* symbol = it->second;
205        if (symbol->getName() == name)
206            symbol->relateToExtension(ext);
207    }
208}
209
210TSymbolTable::~TSymbolTable()
211{
212    for (size_t i = 0; i < table.size(); ++i)
213        delete table[i];
214    for (size_t i = 0; i < precisionStack.size(); ++i)
215        delete precisionStack[i];
216}
217