|
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 |
|
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 // |
|
32 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 |
|
61 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 |
|
83 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 |
|
93 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 |
|
104 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 |
|
117 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 |
|
130 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 |
|
139 void TFunction::dump(TInfoSink &infoSink) const |
|
140 { |
|
141 infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n"; |
|
142 } |
|
143 |
|
144 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 |
|
151 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 // |
|
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 // |
|
171 TSymbolTableLevel::~TSymbolTableLevel() |
|
172 { |
|
173 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) |
|
174 if ((*it).first == (*it).second->getMangledName()) |
|
175 delete (*it).second; |
|
176 } |
|
177 |
|
178 // |
|
179 // Change all function entries in the table with the non-mangled name |
|
180 // to be related to the provided built-in operation. This is a low |
|
181 // performance operation, and only intended for symbol tables that |
|
182 // live across a large number of compiles. |
|
183 // |
|
184 void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) |
|
185 { |
|
186 tLevel::iterator it; |
|
187 for (it = level.begin(); it != level.end(); ++it) { |
|
188 if ((*it).second->isFunction()) { |
|
189 TFunction* function = static_cast<TFunction*>((*it).second); |
|
190 if (function->getName() == name) |
|
191 function->relateToOperator(op); |
|
192 } |
|
193 } |
|
194 } |
|
195 |
|
196 // |
|
197 // Change all function entries in the table with the non-mangled name |
|
198 // to be related to the provided built-in extension. This is a low |
|
199 // performance operation, and only intended for symbol tables that |
|
200 // live across a large number of compiles. |
|
201 // |
|
202 void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) |
|
203 { |
|
204 for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { |
|
205 TSymbol* symbol = it->second; |
|
206 if (symbol->getName() == name) |
|
207 symbol->relateToExtension(ext); |
|
208 } |
|
209 } |