1//
2// Copyright (c) 2002-2010 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#include "compiler/SymbolTable.h"
13
14#include <stdio.h>
15
16//
17// TType helper function needs a place to live.
18//
19
20//
21// Recursively generate mangled names.
22//
23void TType::buildMangledName(TString& mangledName)
24{
25    if (isMatrix())
26        mangledName += 'm';
27    else if (isVector())
28        mangledName += 'v';
29
30    switch (type) {
31    case EbtFloat:              mangledName += 'f';      break;
32    case EbtInt:                mangledName += 'i';      break;
33    case EbtBool:               mangledName += 'b';      break;
34    case EbtSampler2D:          mangledName += "s2";     break;
35    case EbtSamplerCube:        mangledName += "sC";     break;
36    case EbtStruct:
37        mangledName += "struct-";
38        if (typeName)
39            mangledName += *typeName;
40        {// support MSVC++6.0
41            for (unsigned int i = 0; i < structure->size(); ++i) {
42                mangledName += '-';
43                (*structure)[i].type->buildMangledName(mangledName);
44            }
45        }
46    default:
47        break;
48    }
49
50    mangledName += static_cast<char>('0' + getNominalSize());
51    if (isArray()) {
52        char buf[20];
53        sprintf(buf, "%d", arraySize);
54        mangledName += '[';
55        mangledName += buf;
56        mangledName += ']';
57    }
58}
59
60int TType::getStructSize() const
61{
62    if (!getStruct()) {
63        assert(false && "Not a struct");
64        return 0;
65    }
66
67    if (structureSize == 0)
68        for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++)
69            structureSize += ((*tl).type)->getObjectSize();
70
71    return structureSize;
72}
73
74//
75// Dump functions.
76//
77
78void TVariable::dump(TInfoSink& infoSink) const
79{
80    infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
81    if (type.isArray()) {
82        infoSink.debug << "[0]";
83    }
84    infoSink.debug << "\n";
85}
86
87void TFunction::dump(TInfoSink &infoSink) const
88{
89    infoSink.debug << getName().c_str() << ": " <<  returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
90}
91
92void TSymbolTableLevel::dump(TInfoSink &infoSink) const
93{
94    tLevel::const_iterator it;
95    for (it = level.begin(); it != level.end(); ++it)
96        (*it).second->dump(infoSink);
97}
98
99void TSymbolTable::dump(TInfoSink &infoSink) const
100{
101    for (int level = currentLevel(); level >= 0; --level) {
102        infoSink.debug << "LEVEL " << level << "\n";
103        table[level]->dump(infoSink);
104    }
105}
106
107//
108// Functions have buried pointers to delete.
109//
110TFunction::~TFunction()
111{
112    for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
113        delete (*i).type;
114}
115
116//
117// Symbol table levels are a map of pointers to symbols that have to be deleted.
118//
119TSymbolTableLevel::~TSymbolTableLevel()
120{
121    for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
122        delete (*it).second;
123}
124
125//
126// Change all function entries in the table with the non-mangled name
127// to be related to the provided built-in operation.  This is a low
128// performance operation, and only intended for symbol tables that
129// live across a large number of compiles.
130//
131void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
132{
133    tLevel::iterator it;
134    for (it = level.begin(); it != level.end(); ++it) {
135        if ((*it).second->isFunction()) {
136            TFunction* function = static_cast<TFunction*>((*it).second);
137            if (function->getName() == name)
138                function->relateToOperator(op);
139        }
140    }
141}
142
143//
144// Change all function entries in the table with the non-mangled name
145// to be related to the provided built-in extension. This is a low
146// performance operation, and only intended for symbol tables that
147// live across a large number of compiles.
148//
149void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
150{
151    for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
152        if (it->second->isFunction()) {
153            TFunction* function = static_cast<TFunction*>(it->second);
154            if (function->getName() == name)
155                function->relateToExtension(ext);
156        }
157    }
158}
159
160TSymbol::TSymbol(const TSymbol& copyOf)
161{
162    name = NewPoolTString(copyOf.name->c_str());
163    uniqueId = copyOf.uniqueId;
164}
165
166TVariable::TVariable(const TVariable& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
167{
168    type.copyType(copyOf.type, remapper);
169    userType = copyOf.userType;
170    // for builtIn symbol table level, unionArray and arrayInformation pointers should be NULL
171    assert(copyOf.arrayInformationType == 0);
172    arrayInformationType = 0;
173
174    if (copyOf.unionArray) {
175        assert(!copyOf.type.getStruct());
176        assert(copyOf.type.getObjectSize() == 1);
177        unionArray = new ConstantUnion[1];
178        unionArray[0] = copyOf.unionArray[0];
179    } else
180        unionArray = 0;
181}
182
183TVariable* TVariable::clone(TStructureMap& remapper)
184{
185    TVariable *variable = new TVariable(*this, remapper);
186
187    return variable;
188}
189
190TFunction::TFunction(const TFunction& copyOf, TStructureMap& remapper) : TSymbol(copyOf)
191{
192    for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
193        TParameter param;
194        parameters.push_back(param);
195        parameters.back().copyParam(copyOf.parameters[i], remapper);
196    }
197
198    returnType.copyType(copyOf.returnType, remapper);
199    mangledName = copyOf.mangledName;
200    op = copyOf.op;
201    defined = copyOf.defined;
202}
203
204TFunction* TFunction::clone(TStructureMap& remapper)
205{
206    TFunction *function = new TFunction(*this, remapper);
207
208    return function;
209}
210
211TSymbolTableLevel* TSymbolTableLevel::clone(TStructureMap& remapper)
212{
213    TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
214    tLevel::iterator iter;
215    for (iter = level.begin(); iter != level.end(); ++iter) {
216        symTableLevel->insert(*iter->second->clone(remapper));
217    }
218
219    return symTableLevel;
220}
221
222void TSymbolTable::copyTable(const TSymbolTable& copyOf)
223{
224    TStructureMap remapper;
225    uniqueId = copyOf.uniqueId;
226    for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
227        table.push_back(copyOf.table[i]->clone(remapper));
228    }
229    for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
230        precisionStack.push_back( copyOf.precisionStack[i] );
231    }
232}
233