1 // 2 // Copyright (c) 2002-2014 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 #ifndef _SYMBOL_TABLE_INCLUDED_ 8 #define _SYMBOL_TABLE_INCLUDED_ 9 10 // 11 // Symbol table for parsing. Has these design characteristics: 12 // 13 // * Same symbol table can be used to compile many shaders, to preserve 14 // effort of creating and loading with the large numbers of built-in 15 // symbols. 16 // 17 // * Name mangling will be used to give each function a unique name 18 // so that symbol table lookups are never ambiguous. This allows 19 // a simpler symbol table structure. 20 // 21 // * Pushing and popping of scope, so symbol table will really be a stack 22 // of symbol tables. Searched from the top, with new inserts going into 23 // the top. 24 // 25 // * Constants: Compile time constant symbols will keep their values 26 // in the symbol table. The parser can substitute constants at parse 27 // time, including doing constant folding and constant propagation. 28 // 29 // * No temporaries: Temporaries made from operations (+, --, .xy, etc.) 30 // are tracked in the intermediate representation, not the symbol table. 31 // 32 33 #include <assert.h> 34 35 #include "common/angleutils.h" 36 #include "compiler/translator/InfoSink.h" 37 #include "compiler/translator/IntermNode.h" 38 39 // Symbol base class. (Can build functions or variables out of these...) 40 class TSymbol 41 { 42 public: 43 POOL_ALLOCATOR_NEW_DELETE(); 44 TSymbol(const TString *n) 45 : uniqueId(0), 46 name(n) 47 { 48 } 49 virtual ~TSymbol() 50 { 51 // don't delete name, it's from the pool 52 } 53 54 const TString &getName() const 55 { 56 return *name; 57 } 58 virtual const TString &getMangledName() const 59 { 60 return getName(); 61 } 62 virtual bool isFunction() const 63 { 64 return false; 65 } 66 virtual bool isVariable() const 67 { 68 return false; 69 } 70 void setUniqueId(int id) 71 { 72 uniqueId = id; 73 } 74 int getUniqueId() const 75 { 76 return uniqueId; 77 } 78 void relateToExtension(const TString &ext) 79 { 80 extension = ext; 81 } 82 const TString &getExtension() const 83 { 84 return extension; 85 } 86 87 private: 88 DISALLOW_COPY_AND_ASSIGN(TSymbol); 89 90 int uniqueId; // For real comparing during code generation 91 const TString *name; 92 TString extension; 93 }; 94 95 // Variable class, meaning a symbol that's not a function. 96 // 97 // There could be a separate class heirarchy for Constant variables; 98 // Only one of int, bool, or float, (or none) is correct for 99 // any particular use, but it's easy to do this way, and doesn't 100 // seem worth having separate classes, and "getConst" can't simply return 101 // different values for different types polymorphically, so this is 102 // just simple and pragmatic. 103 class TVariable : public TSymbol 104 { 105 public: 106 TVariable(const TString *name, const TType &t, bool uT = false) 107 : TSymbol(name), 108 type(t), 109 userType(uT), 110 unionArray(0) 111 { 112 } 113 virtual ~TVariable() 114 { 115 } 116 virtual bool isVariable() const 117 { 118 return true; 119 } 120 TType &getType() 121 { 122 return type; 123 } 124 const TType &getType() const 125 { 126 return type; 127 } 128 bool isUserType() const 129 { 130 return userType; 131 } 132 void setQualifier(TQualifier qualifier) 133 { 134 type.setQualifier(qualifier); 135 } 136 137 ConstantUnion *getConstPointer() 138 { 139 if (!unionArray) 140 unionArray = new ConstantUnion[type.getObjectSize()]; 141 142 return unionArray; 143 } 144 145 ConstantUnion *getConstPointer() const 146 { 147 return unionArray; 148 } 149 150 void shareConstPointer(ConstantUnion *constArray) 151 { 152 if (unionArray == constArray) 153 return; 154 155 delete[] unionArray; 156 unionArray = constArray; 157 } 158 159 private: 160 DISALLOW_COPY_AND_ASSIGN(TVariable); 161 162 TType type; 163 bool userType; 164 // we are assuming that Pool Allocator will free the memory 165 // allocated to unionArray when this object is destroyed. 166 ConstantUnion *unionArray; 167 }; 168 169 // The function sub-class of symbols and the parser will need to 170 // share this definition of a function parameter. 171 struct TParameter 172 { 173 TString *name; 174 TType *type; 175 }; 176 177 // The function sub-class of a symbol. 178 class TFunction : public TSymbol 179 { 180 public: 181 TFunction(TOperator o) 182 : TSymbol(0), 183 returnType(TType(EbtVoid, EbpUndefined)), 184 op(o), 185 defined(false) 186 { 187 } 188 TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull) 189 : TSymbol(name), 190 returnType(retType), 191 mangledName(TFunction::mangleName(*name)), 192 op(tOp), 193 defined(false) 194 { 195 } 196 virtual ~TFunction(); 197 virtual bool isFunction() const 198 { 199 return true; 200 } 201 202 static TString mangleName(const TString &name) 203 { 204 return name + '('; 205 } 206 static TString unmangleName(const TString &mangledName) 207 { 208 return TString(mangledName.c_str(), mangledName.find_first_of('(')); 209 } 210 211 void addParameter(TParameter &p) 212 { 213 parameters.push_back(p); 214 mangledName = mangledName + p.type->getMangledName(); 215 } 216 217 const TString &getMangledName() const 218 { 219 return mangledName; 220 } 221 const TType &getReturnType() const 222 { 223 return returnType; 224 } 225 226 void relateToOperator(TOperator o) 227 { 228 op = o; 229 } 230 TOperator getBuiltInOp() const 231 { 232 return op; 233 } 234 235 void setDefined() 236 { 237 defined = true; 238 } 239 bool isDefined() 240 { 241 return defined; 242 } 243 244 size_t getParamCount() const 245 { 246 return parameters.size(); 247 } 248 const TParameter &getParam(size_t i) const 249 { 250 return parameters[i]; 251 } 252 253 private: 254 DISALLOW_COPY_AND_ASSIGN(TFunction); 255 256 typedef TVector<TParameter> TParamList; 257 TParamList parameters; 258 TType returnType; 259 TString mangledName; 260 TOperator op; 261 bool defined; 262 }; 263 264 // Interface block name sub-symbol 265 class TInterfaceBlockName : public TSymbol 266 { 267 public: 268 TInterfaceBlockName(const TString *name) 269 : TSymbol(name) 270 { 271 } 272 273 virtual ~TInterfaceBlockName() 274 { 275 } 276 }; 277 278 class TSymbolTableLevel 279 { 280 public: 281 typedef TMap<TString, TSymbol *> tLevel; 282 typedef tLevel::const_iterator const_iterator; 283 typedef const tLevel::value_type tLevelPair; 284 typedef std::pair<tLevel::iterator, bool> tInsertResult; 285 286 TSymbolTableLevel() 287 { 288 } 289 ~TSymbolTableLevel(); 290 291 bool insert(TSymbol *symbol); 292 293 TSymbol *find(const TString &name) const; 294 295 void relateToOperator(const char *name, TOperator op); 296 void relateToExtension(const char *name, const TString &ext); 297 298 protected: 299 tLevel level; 300 }; 301 302 enum ESymbolLevel 303 { 304 COMMON_BUILTINS = 0, 305 ESSL1_BUILTINS = 1, 306 ESSL3_BUILTINS = 2, 307 LAST_BUILTIN_LEVEL = ESSL3_BUILTINS, 308 GLOBAL_LEVEL = 3 309 }; 310 311 class TSymbolTable 312 { 313 public: 314 TSymbolTable() 315 { 316 // The symbol table cannot be used until push() is called, but 317 // the lack of an initial call to push() can be used to detect 318 // that the symbol table has not been preloaded with built-ins. 319 } 320 321 ~TSymbolTable(); 322 323 // When the symbol table is initialized with the built-ins, there should 324 // 'push' calls, so that built-ins are at level 0 and the shader 325 // globals are at level 1. 326 bool isEmpty() const 327 { 328 return table.empty(); 329 } 330 bool atBuiltInLevel() const 331 { 332 return currentLevel() <= LAST_BUILTIN_LEVEL; 333 } 334 bool atGlobalLevel() const 335 { 336 return currentLevel() <= GLOBAL_LEVEL; 337 } 338 void push() 339 { 340 table.push_back(new TSymbolTableLevel); 341 precisionStack.push_back(new PrecisionStackLevel); 342 } 343 344 void pop() 345 { 346 delete table.back(); 347 table.pop_back(); 348 349 delete precisionStack.back(); 350 precisionStack.pop_back(); 351 } 352 353 bool declare(TSymbol *symbol) 354 { 355 return insert(currentLevel(), symbol); 356 } 357 358 bool insert(ESymbolLevel level, TSymbol *symbol) 359 { 360 return table[level]->insert(symbol); 361 } 362 363 bool insertConstInt(ESymbolLevel level, const char *name, int value) 364 { 365 TVariable *constant = new TVariable( 366 NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); 367 constant->getConstPointer()->setIConst(value); 368 return insert(level, constant); 369 } 370 371 void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name, 372 TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, 373 TType *ptype4 = 0, TType *ptype5 = 0); 374 375 TSymbol *find(const TString &name, int shaderVersion, 376 bool *builtIn = NULL, bool *sameScope = NULL) const; 377 TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; 378 379 TSymbolTableLevel *getOuterLevel() 380 { 381 assert(currentLevel() >= 1); 382 return table[currentLevel() - 1]; 383 } 384 385 void relateToOperator(ESymbolLevel level, const char *name, TOperator op) 386 { 387 table[level]->relateToOperator(name, op); 388 } 389 void relateToExtension(ESymbolLevel level, const char *name, const TString &ext) 390 { 391 table[level]->relateToExtension(name, ext); 392 } 393 void dump(TInfoSink &infoSink) const; 394 395 bool setDefaultPrecision(const TPublicType &type, TPrecision prec) 396 { 397 if (!SupportsPrecision(type.type)) 398 return false; 399 if (type.isAggregate()) 400 return false; // Not allowed to set for aggregate types 401 int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; 402 // Uses map operator [], overwrites the current value 403 (*precisionStack[indexOfLastElement])[type.type] = prec; 404 return true; 405 } 406 407 // Searches down the precisionStack for a precision qualifier 408 // for the specified TBasicType 409 TPrecision getDefaultPrecision(TBasicType type) const; 410 411 static int nextUniqueId() 412 { 413 return ++uniqueIdCounter; 414 } 415 416 private: 417 ESymbolLevel currentLevel() const 418 { 419 return static_cast<ESymbolLevel>(table.size() - 1); 420 } 421 422 std::vector<TSymbolTableLevel *> table; 423 typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; 424 std::vector< PrecisionStackLevel *> precisionStack; 425 426 static int uniqueIdCounter; 427 }; 428 429 #endif // _SYMBOL_TABLE_INCLUDED_ 430