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/intermediate.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, 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(const TString &name, TSymbol &symbol); 292 bool insert(TSymbol &symbol); 293 294 TSymbol *find(const TString &name) const; 295 296 void relateToOperator(const char *name, TOperator op); 297 void relateToExtension(const char *name, const TString &ext); 298 299 protected: 300 tLevel level; 301 static int uniqueId; // for unique identification in code generation 302 }; 303 304 enum ESymbolLevel 305 { 306 COMMON_BUILTINS = 0, 307 ESSL1_BUILTINS = 1, 308 ESSL3_BUILTINS = 2, 309 LAST_BUILTIN_LEVEL = ESSL3_BUILTINS, 310 GLOBAL_LEVEL = 3 311 }; 312 313 class TSymbolTable 314 { 315 public: 316 TSymbolTable() 317 { 318 // The symbol table cannot be used until push() is called, but 319 // the lack of an initial call to push() can be used to detect 320 // that the symbol table has not been preloaded with built-ins. 321 } 322 323 ~TSymbolTable(); 324 325 // When the symbol table is initialized with the built-ins, there should 326 // 'push' calls, so that built-ins are at level 0 and the shader 327 // globals are at level 1. 328 bool isEmpty() 329 { 330 return table.empty(); 331 } 332 bool atBuiltInLevel() 333 { 334 return currentLevel() <= LAST_BUILTIN_LEVEL; 335 } 336 bool atGlobalLevel() 337 { 338 return currentLevel() <= GLOBAL_LEVEL; 339 } 340 void push() 341 { 342 table.push_back(new TSymbolTableLevel); 343 precisionStack.push_back(new PrecisionStackLevel); 344 } 345 346 void pop() 347 { 348 delete table.back(); 349 table.pop_back(); 350 351 delete precisionStack.back(); 352 precisionStack.pop_back(); 353 } 354 355 bool declare(TSymbol &symbol) 356 { 357 return insert(currentLevel(), symbol); 358 } 359 360 bool insert(ESymbolLevel level, TSymbol &symbol) 361 { 362 return table[level]->insert(symbol); 363 } 364 365 bool insertConstInt(ESymbolLevel level, const char *name, int value) 366 { 367 TVariable *constant = new TVariable( 368 NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); 369 constant->getConstPointer()->setIConst(value); 370 return insert(level, *constant); 371 } 372 373 void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name, 374 TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, 375 TType *ptype4 = 0, TType *ptype5 = 0); 376 377 TSymbol *find(const TString &name, int shaderVersion, 378 bool *builtIn = NULL, bool *sameScope = NULL); 379 TSymbol *findBuiltIn(const TString &name, int shaderVersion); 380 381 TSymbolTableLevel *getOuterLevel() 382 { 383 assert(currentLevel() >= 1); 384 return table[currentLevel() - 1]; 385 } 386 387 void relateToOperator(ESymbolLevel level, const char *name, TOperator op) 388 { 389 table[level]->relateToOperator(name, op); 390 } 391 void relateToExtension(ESymbolLevel level, const char *name, const TString &ext) 392 { 393 table[level]->relateToExtension(name, ext); 394 } 395 void dump(TInfoSink &infoSink) const; 396 397 bool setDefaultPrecision(const TPublicType &type, TPrecision prec) 398 { 399 if (!SupportsPrecision(type.type)) 400 return false; 401 if (type.isAggregate()) 402 return false; // Not allowed to set for aggregate types 403 int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1; 404 // Uses map operator [], overwrites the current value 405 (*precisionStack[indexOfLastElement])[type.type] = prec; 406 return true; 407 } 408 409 // Searches down the precisionStack for a precision qualifier 410 // for the specified TBasicType 411 TPrecision getDefaultPrecision(TBasicType type); 412 413 static int nextUniqueId() 414 { 415 return ++uniqueIdCounter; 416 } 417 418 private: 419 ESymbolLevel currentLevel() const 420 { 421 return static_cast<ESymbolLevel>(table.size() - 1); 422 } 423 424 std::vector<TSymbolTableLevel *> table; 425 typedef TMap<TBasicType, TPrecision> PrecisionStackLevel; 426 std::vector< PrecisionStackLevel *> precisionStack; 427 428 static int uniqueIdCounter; 429 }; 430 431 #endif // _SYMBOL_TABLE_INCLUDED_ 432