• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TType(const TPublicType & p)22 TType::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 //
buildMangledName() const32 TString 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 
getObjectSize() const61 size_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 
containsArrays() const83 bool 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 
buildMangledName() const93 TString 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 
calculateObjectSize() const104 size_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 
calculateDeepestNesting() const117 int 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 
dump(TInfoSink & infoSink) const130 void 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 
dump(TInfoSink & infoSink) const139 void TFunction::dump(TInfoSink &infoSink) const
140 {
141     infoSink.debug << getName().c_str() << ": " <<  returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
142 }
143 
dump(TInfoSink & infoSink) const144 void 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 
dump(TInfoSink & infoSink) const151 void 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 //
~TFunction()162 TFunction::~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 //
~TSymbolTableLevel()171 TSymbolTableLevel::~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 //
relateToOperator(const char * name,TOperator op)183 void 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 //
relateToExtension(const char * name,const TString & ext)201 void 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 
~TSymbolTable()210 TSymbolTable::~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