Changeset b8665e3
- Timestamp:
- Mar 14, 2019, 11:53:28 AM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, persistent-indexer, pthread-emulation, qualifiedEnum
- Children:
- b419abb
- Parents:
- fca6ca6
- Location:
- src
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/PassVisitor.cc
rfca6ca6 rb8665e3 17 17 18 18 PassVisitorStats pass_visitor_stats; 19 Stats::Counters::SimpleCounter* BaseSyntaxNode::new_nodes = nullptr; -
src/Common/Stats/Counter.h
rfca6ca6 rb8665e3 37 37 class SimpleCounter { 38 38 public: 39 inline void operator++() {} 39 40 inline void operator++(int) {} 40 41 inline void operator+=(size_t) {} … … 84 85 virtual void print(std::ostream & os) override { os << count; } 85 86 87 inline void operator++() { if(!enabled) return; count++; } 86 88 inline void operator++(int) { if(!enabled) return; count++; } 87 89 inline void operator+=(size_t value) { if(!enabled) return; count += value; } -
src/SymTab/Indexer.cc
rfca6ca6 rb8665e3 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:37:33 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Aug 17 16:08:40 201713 // Update Count : 2 011 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Mar 8 13:55:00 2019 13 // Update Count : 21 14 14 // 15 15 … … 19 19 #include <iostream> // for operator<<, basic_ostream, ostream 20 20 #include <string> // for string, operator<<, operator!= 21 #include <memory> // for shared_ptr, make_shared 21 22 #include <unordered_map> // for operator!=, unordered_map<>::const... 22 23 #include <unordered_set> // for unordered_set … … 26 27 #include "Common/SemanticError.h" // for SemanticError 27 28 #include "Common/utility.h" // for cloneAll 28 #include "Common/Stats/Counter.h" // for counters29 #include "GenPoly/GenPoly.h" 29 #include "Common/Stats/Counter.h" // for counters 30 #include "GenPoly/GenPoly.h" // for getFunctionType 30 31 #include "InitTweak/InitTweak.h" // for isConstructor, isCopyFunction, isC... 31 32 #include "Mangler.h" // for Mangler … … 44 45 45 46 // Statistics block 46 namespace { 47 48 static inline auto stats_idtable() { 49 using namespace Stats::Counters; 50 static auto group = build<CounterGroup>("IdTable"); 51 static struct { 52 SimpleCounter * find; 53 AverageCounter<double> * size; 54 AverageCounter<double> * key; 55 } ret = { 56 .find = build<SimpleCounter>("Find calls", group), 57 .size = build<AverageCounter<double>>("Average Size", group), 58 .key = build<AverageCounter<double>>("Average Key Size", group), 59 }; 60 return ret; 61 } 62 63 static inline auto stats_indexers() { 64 using namespace Stats::Counters; 65 static auto group = build<CounterGroup>("Indexers"); 66 static struct { 67 SimpleCounter * count; 68 AverageCounter<double> * size; 69 AverageCounter<double> * depth_a; 70 MaxCounter<size_t> * depth_m; 71 } ret = { 72 .count = build<SimpleCounter>("Count", group), 73 .size = build<AverageCounter<double>>("Average Size", group), 74 .depth_a = build<AverageCounter<double>>("Average Depth", group), 75 .depth_m = build<MaxCounter<size_t>>("Max Depth", group), 76 }; 77 return ret; 78 } 79 } 80 81 std::ostream & operator<<( std::ostream & out, const Indexer::IdData & data ) { 82 return out << "(" << data.id << "," << data.baseExpr << ")"; 83 } 84 85 typedef std::unordered_map< std::string, Indexer::IdData > MangleTable; 86 typedef std::unordered_map< std::string, MangleTable > IdTable; 87 typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable; 88 typedef std::unordered_map< std::string, StructDecl* > StructTable; 89 typedef std::unordered_map< std::string, EnumDecl* > EnumTable; 90 typedef std::unordered_map< std::string, UnionDecl* > UnionTable; 91 typedef std::unordered_map< std::string, TraitDecl* > TraitTable; 92 93 void dump( const IdTable &table, std::ostream &os ) { 94 for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) { 95 for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) { 96 os << mangle->second << std::endl; 97 } 98 } 99 } 100 101 template< typename Decl > 102 void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) { 103 for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) { 104 os << it->second << std::endl; 105 } // for 106 } 107 108 struct Indexer::Impl { 109 Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(), 110 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {} 111 Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ), 112 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {} 113 unsigned long refCount; ///< Number of references to these tables 114 unsigned long scope; ///< Scope these tables are associated with 115 unsigned long size; ///< Number of elements stored in this table 116 const Indexer base; ///< Base indexer this extends 117 118 IdTable idTable; ///< Identifier namespace 119 TypeTable typeTable; ///< Type namespace 120 StructTable structTable; ///< Struct namespace 121 EnumTable enumTable; ///< Enum namespace 122 UnionTable unionTable; ///< Union namespace 123 TraitTable traitTable; ///< Trait namespace 124 }; 125 126 Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) { 127 if ( ! toClone ) return 0; 128 129 // shorten the search chain by skipping empty links 130 Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone; 131 if ( ret ) { ++ret->refCount; } 132 133 return ret; 134 } 135 136 void Indexer::deleteRef( Indexer::Impl *toFree ) { 137 if ( ! toFree ) return; 138 139 if ( --toFree->refCount == 0 ) delete toFree; 140 } 47 // namespace { 48 49 // static inline auto stats_idtable() { 50 // using namespace Stats::Counters; 51 // static auto group = build<CounterGroup>("IdTable"); 52 // static struct { 53 // SimpleCounter * find; 54 // AverageCounter<double> * size; 55 // AverageCounter<double> * key; 56 // } ret = { 57 // .find = build<SimpleCounter>("Find calls", group), 58 // .size = build<AverageCounter<double>>("Average Size", group), 59 // .key = build<AverageCounter<double>>("Average Key Size", group), 60 // }; 61 // return ret; 62 // } 63 64 // static inline auto stats_indexers() { 65 // using namespace Stats::Counters; 66 // static auto group = build<CounterGroup>("Indexers"); 67 // static struct { 68 // SimpleCounter * count; 69 // AverageCounter<double> * size; 70 // AverageCounter<double> * depth_a; 71 // MaxCounter<size_t> * depth_m; 72 // SimpleCounter * new_scopes; 73 // AverageCounter<double> * avg_scope_depth; 74 // MaxCounter<size_t> * max_scope_depth; 75 // SimpleCounter * add_calls; 76 // SimpleCounter * lookup_calls; 77 // SimpleCounter * map_lookups; 78 // } ret = { 79 // .count = build<SimpleCounter>("Count", group), 80 // .size = build<AverageCounter<double>>("Average Size", group), 81 // .depth_a = build<AverageCounter<double>>("Average Depth", group), 82 // .depth_m = build<MaxCounter<size_t>>("Max Depth", group), 83 // .new_scopes = build<SimpleCounter>("Scopes", group), 84 // .avg_scope_depth = build<AverageCounter<double>>("Average Scope", group), 85 // .max_scope_depth = build<MaxCounter<size_t>>("Max Scope", group), 86 // .add_calls = build<SimpleCounter>("Add Calls", group), 87 // .lookup_calls = build<SimpleCounter>("Lookup Calls", group), 88 // .map_lookups = build<SimpleCounter>("Map Lookups", group), 89 // }; 90 // return ret; 91 // } 92 // } 93 94 // std::ostream & operator<<( std::ostream & out, const Indexer::IdData & data ) { 95 // return out << "(" << data.id << "," << data.baseExpr << ")"; 96 // } 97 98 // void dump( const Indexer::IdTable &table, std::ostream &os ) { 99 // for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) { 100 // for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) { 101 // os << mangle->second << std::endl; 102 // } 103 // } 104 // } 105 106 // template< typename Decl > 107 // void dump( const PersistentMap< std::string, Decl* > &table, std::ostream &os ) { 108 // for ( auto decl : table ) { 109 // os << decl.second << std::endl; 110 // } // for 111 // } 141 112 142 113 void Indexer::removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const { … … 163 134 bool isCopyFunc = InitTweak::isCopyFunction( function, function->name ); 164 135 decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } ); 165 existsUserDefinedCopyFunc = existsUserDefinedCopyFunc ||(isUserDefinedFunc && isCopyFunc);136 existsUserDefinedCopyFunc |= (isUserDefinedFunc && isCopyFunc); 166 137 if ( isUserDefinedFunc && ! deleteStmt ) { 167 138 // any user-defined function can act as an implicit delete statement for generated constructors. … … 225 196 } 226 197 227 void Indexer::makeWritable() { 228 if ( ! tables ) { 229 // create indexer if not yet set 230 tables = new Indexer::Impl( scope ); 231 } else if ( tables->refCount > 1 || tables->scope != scope ) { 232 // make this indexer the base of a fresh indexer at the current scope 233 tables = new Indexer::Impl( scope, std::move( *this ) ); 234 } 235 } 236 237 Indexer::Indexer() : tables( 0 ), scope( 0 ) { 238 (*stats_indexers().count)++; 239 } 240 241 Indexer::Indexer( const Indexer &that ) : doDebug( that.doDebug ), tables( newRef( that.tables ) ), scope( that.scope ) { 242 (*stats_indexers().count)++; 243 } 244 245 Indexer::Indexer( Indexer &&that ) : doDebug( that.doDebug ), tables( that.tables ), scope( that.scope ) { 246 that.tables = 0; 247 } 248 249 Indexer::~Indexer() { 250 if(tables) { 251 stats_indexers().size->push( tables->idTable.size() ); 252 size_t depth = 1; 253 for( auto crnt = tables->base.tables; crnt; crnt = crnt->base.tables ) { 254 ++depth; 255 } 256 stats_indexers().depth_a->push( depth ); 257 stats_indexers().depth_m->push( depth ); 258 } 259 deleteRef( tables ); 260 } 261 262 Indexer& Indexer::operator= ( const Indexer &that ) { 263 deleteRef( tables ); 264 265 tables = newRef( that.tables ); 266 scope = that.scope; 267 doDebug = that.doDebug; 268 269 return *this; 270 } 271 272 Indexer& Indexer::operator= ( Indexer &&that ) { 273 deleteRef( tables ); 274 275 tables = that.tables; 276 scope = that.scope; 277 doDebug = that.doDebug; 278 279 that.tables = 0; 280 281 return *this; 198 Indexer::Indexer() 199 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 200 prevScope(), scope( 0 ) {} 201 202 Indexer::~Indexer() {} 203 204 void Indexer::enterScope() { 205 // save current state in prevScope and increment scope 206 prevScope = std::make_shared<Indexer>( *this ); 207 ++scope; 208 209 // if ( doDebug ) { 210 // std::cerr << "--- Entering scope " << scope << std::endl; 211 // } 212 } 213 214 void Indexer::leaveScope() { 215 // if ( doDebug ) { 216 // std::cerr << "--- Leaving scope " << scope << " containing" << std::endl; 217 // dump( idTable, std::cerr ); 218 // dump( typeTable, std::cerr ); 219 // dump( structTable, std::cerr ); 220 // dump( enumTable, std::cerr ); 221 // dump( unionTable, std::cerr ); 222 // dump( traitTable, std::cerr ); 223 // } 224 225 // replace all maps and scope index with previous scope's versions 226 *this = *prevScope; 282 227 } 283 228 284 229 void Indexer::lookupId( const std::string &id, std::list< IdData > &out ) const { 285 std::unordered_set< std::string > foundMangleNames; 286 287 Indexer::Impl *searchTables = tables; 288 while ( searchTables ) { 289 290 (*stats_idtable().find)++; 291 stats_idtable().key->push( id.size() ); 292 stats_idtable().size->push( searchTables->idTable.size() ); 293 IdTable::const_iterator decls = searchTables->idTable.find( id ); 294 if ( decls != searchTables->idTable.end() ) { 295 const MangleTable &mangleTable = decls->second; 296 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 297 // mark the mangled name as found, skipping this insertion if a declaration for that name has already been found 298 if ( foundMangleNames.insert( decl->first ).second == false ) continue; 299 300 out.push_back( decl->second ); 301 } 302 } 303 304 // get declarations from base indexers 305 searchTables = searchTables->base.tables; 306 } 307 230 if ( ! idTable ) return; 231 232 auto decls = idTable->find( id ); 233 if ( decls == idTable->end() ) return; 234 235 for ( auto decl : *(decls->second) ) { 236 out.push_back( decl.second ); 237 } 238 308 239 // some special functions, e.g. constructors and destructors 309 240 // remove autogenerated functions when they are defined so that … … 313 244 314 245 NamedTypeDecl *Indexer::lookupType( const std::string &id ) const { 315 if ( ! tables ) return 0; 316 317 TypeTable::const_iterator ret = tables->typeTable.find( id ); 318 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id ); 246 if ( ! typeTable ) return nullptr; 247 auto it = typeTable->find( id ); 248 return it == typeTable->end() ? nullptr : it->second.decl; 319 249 } 320 250 321 251 StructDecl *Indexer::lookupStruct( const std::string &id ) const { 322 if ( ! tables ) return 0; 323 324 StructTable::const_iterator ret = tables->structTable.find( id ); 325 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id ); 326 } 252 if ( ! structTable ) return nullptr; 253 auto it = structTable->find( id ); 254 return it == structTable->end() ? nullptr : it->second.decl; 255 } 256 257 EnumDecl *Indexer::lookupEnum( const std::string &id ) const { 258 if ( ! enumTable ) return nullptr; 259 auto it = enumTable->find( id ); 260 return it == enumTable->end() ? nullptr : it->second.decl; 261 } 262 263 UnionDecl *Indexer::lookupUnion( const std::string &id ) const { 264 if ( ! unionTable ) return nullptr; 265 auto it = unionTable->find( id ); 266 return it == unionTable->end() ? nullptr : it->second.decl; 267 } 268 269 TraitDecl *Indexer::lookupTrait( const std::string &id ) const { 270 if ( ! traitTable ) return nullptr; 271 auto it = traitTable->find( id ); 272 return it == traitTable->end() ? nullptr : it->second.decl; 273 } 274 275 const Indexer* Indexer::atScope( unsigned long scope ) const { 276 // scan back to scope; guaranteed one indexer per scope by construction of enterScope, 277 // final indexer in list has scope 0, cannot be > scope 278 const Indexer* indexer = this; 279 while ( indexer->scope > scope ) { 280 indexer = indexer->prevScope.get(); 281 } 282 return indexer; 283 } 284 285 // const Indexer::IdData * Indexer::localLookupId( 286 // const std::string &id, const std::string &mangleName ) const { 287 // if ( ! idTable ) return nullptr; 288 289 // // lookup name 290 // auto decls = idTable->find( id ); 291 // if ( decls == idTable->end() ) return nullptr; 292 293 // // lookup mangleName 294 // // assume any mangle-table pointer added is non-null 295 // const MangleTable& mangleTable = *(decls->second); 296 // auto decl = mangleTable.find( mangleName ); 297 // if ( decl == mangleTable.end() ) return nullptr; 298 299 // // skip identifiers not defined in this scope 300 // if ( decl->second.scope != scope ) return nullptr; 301 // return &decl->second; 302 // } 303 304 // Indexer::IdData * Indexer::lookupIdAtScope( 305 // const std::string &id, const std::string &mangleName, unsigned long scope ) { 306 // return const_cast<IdData *>( 307 // const_cast<const Indexer *>(this)->lookupIdAtScope( id, mangleName, scope )); 308 // } 309 310 // NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const { 311 312 // if ( ! tables ) return ++*stats_indexers().lookup_calls, nullptr; 313 // if ( tables->scope < scope ) return ++*stats_indexers().lookup_calls, nullptr; 314 // if ( tables->scope > scope ) return tables->base.lookupTypeAtScope( id, scope ); 315 316 // ++*stats_indexers().map_lookups; 317 // TypeTable::const_iterator ret = tables->typeTable.find( id ); 318 // return ret != tables->typeTable.end() ? 319 // ++*stats_indexers().lookup_calls, ret->second : 320 // tables->base.lookupTypeAtScope( id, scope ); 321 // } 322 323 // StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const { 324 // if ( ! tables ) return ++*stats_indexers().lookup_calls, nullptr; 325 // if ( tables->scope < scope ) return ++*stats_indexers().lookup_calls, nullptr; 326 // if ( tables->scope > scope ) return tables->base.lookupStructAtScope( id, scope ); 327 328 // ++*stats_indexers().map_lookups; 329 // StructTable::const_iterator ret = tables->structTable.find( id ); 330 // return ret != tables->structTable.end() ? 331 // ++*stats_indexers().lookup_calls, ret->second : 332 // tables->base.lookupStructAtScope( id, scope ); 333 // } 334 335 // EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const { 336 // if ( ! tables ) return ++*stats_indexers().lookup_calls, nullptr; 337 // if ( tables->scope < scope ) return ++*stats_indexers().lookup_calls, nullptr; 338 // if ( tables->scope > scope ) return tables->base.lookupEnumAtScope( id, scope ); 339 340 // ++*stats_indexers().map_lookups; 341 // EnumTable::const_iterator ret = tables->enumTable.find( id ); 342 // return ret != tables->enumTable.end() ? 343 // ++*stats_indexers().lookup_calls, ret->second : 344 // tables->base.lookupEnumAtScope( id, scope ); 345 // } 346 347 // UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const { 348 // if ( ! tables ) return ++*stats_indexers().lookup_calls, nullptr; 349 // if ( tables->scope < scope ) return ++*stats_indexers().lookup_calls, nullptr; 350 // if ( tables->scope > scope ) return tables->base.lookupUnionAtScope( id, scope ); 351 352 // ++*stats_indexers().map_lookups; 353 // UnionTable::const_iterator ret = tables->unionTable.find( id ); 354 // return ret != tables->unionTable.end() ? 355 // ++*stats_indexers().lookup_calls, ret->second : 356 // tables->base.lookupUnionAtScope( id, scope ); 357 // } 358 359 // TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const { 360 // if ( ! tables ) return ++*stats_indexers().lookup_calls, nullptr; 361 // if ( tables->scope < scope ) return ++*stats_indexers().lookup_calls, nullptr; 362 // if ( tables->scope > scope ) return tables->base.lookupTraitAtScope( id, scope ); 363 364 // ++*stats_indexers().map_lookups; 365 // TraitTable::const_iterator ret = tables->traitTable.find( id ); 366 // return ret != tables->traitTable.end() ? 367 // ++*stats_indexers().lookup_calls, ret->second : 368 // tables->base.lookupTraitAtScope( id, scope ); 369 // } 327 370 328 371 NamedTypeDecl *Indexer::globalLookupType( const std::string &id ) const { 329 return lookupTypeAtScope( id, 0);372 return atScope( 0 )->lookupType( id ); 330 373 } 331 374 332 375 StructDecl *Indexer::globalLookupStruct( const std::string &id ) const { 333 return lookupStructAtScope( id, 0);376 return atScope( 0 )->lookupStruct( id ); 334 377 } 335 378 336 379 UnionDecl *Indexer::globalLookupUnion( const std::string &id ) const { 337 return lookupUnionAtScope( id, 0);380 return atScope( 0 )->lookupUnion( id ); 338 381 } 339 382 340 383 EnumDecl *Indexer::globalLookupEnum( const std::string &id ) const { 341 return lookupEnumAtScope( id, 0 ); 342 } 343 344 EnumDecl *Indexer::lookupEnum( const std::string &id ) const { 345 if ( ! tables ) return 0; 346 347 EnumTable::const_iterator ret = tables->enumTable.find( id ); 348 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id ); 349 } 350 351 UnionDecl *Indexer::lookupUnion( const std::string &id ) const { 352 if ( ! tables ) return 0; 353 354 UnionTable::const_iterator ret = tables->unionTable.find( id ); 355 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id ); 356 } 357 358 TraitDecl *Indexer::lookupTrait( const std::string &id ) const { 359 if ( ! tables ) return 0; 360 361 TraitTable::const_iterator ret = tables->traitTable.find( id ); 362 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id ); 363 } 364 365 const Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 366 if ( ! tables ) return nullptr; 367 if ( tables->scope < scope ) return nullptr; 368 369 (*stats_idtable().find)++; 370 stats_idtable().key->push( id.size() ); 371 stats_idtable().size->push( tables->idTable.size() ); 372 IdTable::const_iterator decls = tables->idTable.find( id ); 373 if ( decls != tables->idTable.end() ) { 374 const MangleTable &mangleTable = decls->second; 375 MangleTable::const_iterator decl = mangleTable.find( mangleName ); 376 if ( decl != mangleTable.end() ) return &decl->second; 377 } 378 379 return tables->base.lookupIdAtScope( id, mangleName, scope ); 380 } 381 382 Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) { 383 return const_cast<IdData *>(const_cast<const Indexer *>(this)->lookupIdAtScope( id, mangleName, scope )); 384 } 385 386 bool Indexer::hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 387 if ( ! tables ) return false; 388 if ( tables->scope < scope ) return false; 389 390 (*stats_idtable().find)++; 391 stats_idtable().key->push( id.size() ); 392 stats_idtable().size->push( tables->idTable.size() ); 393 IdTable::const_iterator decls = tables->idTable.find( id ); 394 if ( decls != tables->idTable.end() ) { 395 const MangleTable &mangleTable = decls->second; 396 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 397 // check for C decls with the same name, skipping those with a compatible type (by mangleName) 398 if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first != mangleName ) return true; 399 } 400 } 401 402 return tables->base.hasIncompatibleCDecl( id, mangleName, scope ); 403 } 404 405 bool Indexer::hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 406 if ( ! tables ) return false; 407 if ( tables->scope < scope ) return false; 408 409 (*stats_idtable().find)++; 410 stats_idtable().key->push( id.size() ); 411 stats_idtable().size->push( tables->idTable.size() ); 412 IdTable::const_iterator decls = tables->idTable.find( id ); 413 if ( decls != tables->idTable.end() ) { 414 const MangleTable &mangleTable = decls->second; 415 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 416 // check for C decls with the same name, skipping 417 // those with an incompatible type (by mangleName) 418 if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first == mangleName ) return true; 419 } 420 } 421 422 return tables->base.hasCompatibleCDecl( id, mangleName, scope ); 423 } 424 425 NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const { 426 if ( ! tables ) return 0; 427 if ( tables->scope < scope ) return 0; 428 if ( tables->scope > scope ) return tables->base.lookupTypeAtScope( id, scope ); 429 430 TypeTable::const_iterator ret = tables->typeTable.find( id ); 431 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope ); 432 } 433 434 StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const { 435 if ( ! tables ) return 0; 436 if ( tables->scope < scope ) return 0; 437 if ( tables->scope > scope ) return tables->base.lookupStructAtScope( id, scope ); 438 439 StructTable::const_iterator ret = tables->structTable.find( id ); 440 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope ); 441 } 442 443 EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const { 444 if ( ! tables ) return 0; 445 if ( tables->scope < scope ) return 0; 446 if ( tables->scope > scope ) return tables->base.lookupEnumAtScope( id, scope ); 447 448 EnumTable::const_iterator ret = tables->enumTable.find( id ); 449 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope ); 450 } 451 452 UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const { 453 if ( ! tables ) return 0; 454 if ( tables->scope < scope ) return 0; 455 if ( tables->scope > scope ) return tables->base.lookupUnionAtScope( id, scope ); 456 457 UnionTable::const_iterator ret = tables->unionTable.find( id ); 458 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope ); 459 } 460 461 TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const { 462 if ( ! tables ) return 0; 463 if ( tables->scope < scope ) return 0; 464 if ( tables->scope > scope ) return tables->base.lookupTraitAtScope( id, scope ); 465 466 TraitTable::const_iterator ret = tables->traitTable.find( id ); 467 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope ); 384 return atScope( 0 )->lookupEnum( id ); 468 385 } 469 386 … … 487 404 } 488 405 489 bool addedIdConflicts( Indexer::IdData & existing, DeclarationWithType *added, BaseSyntaxNode * deleteStmt, Indexer::ConflictFunction handleConflicts ) { 406 407 bool Indexer::addedIdConflicts( 408 const Indexer::IdData & existing, DeclarationWithType *added, 409 Indexer::OnConflict handleConflicts, BaseSyntaxNode * deleteStmt ) { 490 410 // if we're giving the same name mangling to things of different types then there is something wrong 491 411 assert( (isObject( added ) && isObject( existing.id ) ) 492 412 || ( isFunction( added ) && isFunction( existing.id ) ) ); 493 413 494 if ( LinkageSpec::isOverridable( existing.id-> get_linkage()) ) {414 if ( LinkageSpec::isOverridable( existing.id->linkage ) ) { 495 415 // new definition shadows the autogenerated one, even at the same scope 496 416 return false; 497 } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing.id->get_type(), Indexer() ) ) { 417 } else if ( LinkageSpec::isMangled( added->linkage ) 418 || ResolvExpr::typesCompatible( 419 added->get_type(), existing.id->get_type(), Indexer() ) ) { 498 420 499 421 // it is a conflict if one declaration is deleted and the other is not 500 422 if ( deleteStmt && ! existing.deleteStmt ) { 501 return handleConflicts( existing, "deletion of defined identifier " ); 423 if ( handleConflicts.mode == OnConflict::Error ) { 424 SemanticError( added, "deletion of defined identifier " ); 425 } 426 return true; 502 427 } else if ( ! deleteStmt && existing.deleteStmt ) { 503 return handleConflicts( existing, "definition of deleted identifier " ); 428 if ( handleConflicts.mode == OnConflict::Error ) { 429 SemanticError( added, "definition of deleted identifier " ); 430 } 431 return true; 504 432 } 505 433 506 434 if ( isDefinition( added ) && isDefinition( existing.id ) ) { 507 if ( isFunction( added ) ) { 508 return handleConflicts( existing, "duplicate function definition for " ); 509 } else { 510 return handleConflicts( existing, "duplicate object definition for " ); 511 } // if 435 if ( handleConflicts.mode == OnConflict::Error ) { 436 SemanticError( added, 437 isFunction( added ) ? 438 "duplicate function definition for " : 439 "duplicate object definition for " ); 440 } 441 return true; 512 442 } // if 513 443 } else { 514 return handleConflicts( existing, "duplicate definition for " ); 444 if ( handleConflicts.mode == OnConflict::Error ) { 445 SemanticError( added, "duplicate definition for " ); 446 } 447 return true; 515 448 } // if 516 449 … … 518 451 } 519 452 520 void Indexer::addId( DeclarationWithType *decl, ConflictFunction handleConflicts, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) { 453 bool Indexer::hasCompatibleCDecl( const std::string &id, const std::string &mangleName ) const { 454 if ( ! idTable ) return false; 455 456 auto decls = idTable->find( id ); 457 if ( decls == idTable->end() ) return false; 458 459 for ( auto decl : *(decls->second) ) { 460 // skip other scopes (hidden by this decl) 461 if ( decl.second.scope != scope ) continue; 462 // check for C decl with compatible type (by mangleName) 463 if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first == mangleName ) { 464 return true; 465 } 466 } 467 468 return false; 469 } 470 471 bool Indexer::hasIncompatibleCDecl( 472 const std::string &id, const std::string &mangleName ) const { 473 if ( ! idTable ) return false; 474 475 auto decls = idTable->find( id ); 476 if ( decls == idTable->end() ) return false; 477 478 for ( auto decl : *(decls->second) ) { 479 // skip other scopes (hidden by this decl) 480 if ( decl.second.scope != scope ) continue; 481 // check for C decl with incompatible type (by manglename) 482 if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first != mangleName ) { 483 return true; 484 } 485 } 486 487 return false; 488 } 489 490 void Indexer::addId( 491 DeclarationWithType *decl, OnConflict handleConflicts, Expression * baseExpr, 492 BaseSyntaxNode * deleteStmt ) { 521 493 if ( decl->name == "" ) return; 522 debugPrint( "Adding Id " << decl->name << std::endl ); 523 makeWritable(); 524 494 // debugPrint( "Adding Id " << decl->name << std::endl ); 495 525 496 const std::string &name = decl->name; 526 497 std::string mangleName; 527 498 if ( LinkageSpec::isOverridable( decl->linkage ) ) { 528 // mangle the name without including the appropriate suffix, so overridable routines are placed into the529 // same "bucket" as their user defined versions.499 // mangle the name without including the appropriate suffix, so overridable routines 500 // are placed into the same "bucket" as their user defined versions. 530 501 mangleName = Mangler::mangle( decl, false ); 531 502 } else { … … 533 504 } // if 534 505 535 // this ensures that no two declarations with the same unmangled name at the same scope both have C linkage 536 if ( ! LinkageSpec::isMangled( decl->linkage ) ) { 537 // NOTE this is broken in Richard's original code in such a way that it never triggers (it 538 // doesn't check decls that have the same manglename, and all C-linkage decls are defined to 539 // have their name as their manglename, hence the error can never trigger). 540 // The code here is closer to correct, but name mangling would have to be completely 541 // isomorphic to C type-compatibility, which it may not be. 542 if ( hasIncompatibleCDecl( name, mangleName, scope ) ) { 506 // this ensures that no two declarations with the same unmangled name at the same scope 507 // both have C linkage 508 if ( LinkageSpec::isMangled( decl->linkage ) ) { 509 // Check that a Cforall declaration doesn't override any C declaration 510 if ( hasCompatibleCDecl( name, mangleName ) ) { 511 SemanticError( decl, "Cforall declaration hides C function " ); 512 } 513 } else { 514 // NOTE: only correct if name mangling is completely isomorphic to C 515 // type-compatibility, which it may not be. 516 if ( hasIncompatibleCDecl( name, mangleName ) ) { 543 517 SemanticError( decl, "conflicting overload of C function " ); 544 518 } 545 } else { 546 // Check that a Cforall declaration doesn't override any C declaration 547 if ( hasCompatibleCDecl( name, mangleName, scope ) ) { 548 SemanticError( decl, "Cforall declaration hides C function " ); 549 } 550 } 551 552 // Skip repeat declarations of the same identifier 553 IdData * existing = lookupIdAtScope( name, mangleName, scope ); 554 if ( existing && existing->id && addedIdConflicts( *existing, decl, deleteStmt, handleConflicts ) ) return; 555 556 // add to indexer 557 tables->idTable[ name ][ mangleName ] = IdData{ decl, baseExpr, deleteStmt }; 558 ++tables->size; 519 } 520 521 // ensure tables exist and add identifier 522 MangleTable::Ptr mangleTable; 523 if ( ! idTable ) { 524 idTable = IdTable::new_ptr(); 525 mangleTable = MangleTable::new_ptr(); 526 } else { 527 auto decls = idTable->find( name ); 528 if ( decls == idTable->end() ) { 529 mangleTable = MangleTable::new_ptr(); 530 } else { 531 mangleTable = decls->second; 532 // skip in-scope repeat declarations of same identifier 533 auto existing = mangleTable->find( mangleName ); 534 if ( existing != mangleTable->end() 535 && existing->second.scope == scope 536 && existing->second.id ) { 537 if ( addedIdConflicts( existing->second, decl, handleConflicts, deleteStmt ) ) { 538 if ( handleConflicts.mode == OnConflict::Delete ) { 539 // set delete expression for conflicting identifier 540 idTable = idTable->set( 541 name, 542 mangleTable->set( 543 mangleName, 544 IdData{ existing->second, handleConflicts.deleteStmt } ) ); 545 } 546 return; 547 } 548 } 549 } 550 } 551 552 // add/overwrite with new identifier 553 idTable = idTable->set( 554 name, 555 mangleTable->set( mangleName, IdData{ decl, baseExpr, deleteStmt, scope } ) ); 559 556 } 560 557 561 558 void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) { 562 559 // default handling of conflicts is to raise an error 563 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );560 addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr ); 564 561 } 565 562 566 563 void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) { 567 564 // default handling of conflicts is to raise an error 568 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );565 addId( decl, OnConflict::error(), nullptr, deleteStmt ); 569 566 } 570 567 … … 586 583 587 584 void Indexer::addType( NamedTypeDecl *decl ) { 588 debugPrint( "Adding type " << decl->name << std::endl );589 makeWritable();590 591 585 const std::string &id = decl->name; 592 TypeTable::iterator existing = tables->typeTable.find( id ); 593 if ( existing == tables->typeTable.end() ) { 594 NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope ); 595 if ( ! parent || ! addedTypeConflicts( parent, decl ) ) { 596 tables->typeTable.insert( existing, std::make_pair( id, decl ) ); 597 ++tables->size; 598 } 599 } else { 600 if ( ! addedTypeConflicts( existing->second, decl ) ) { 601 existing->second = decl; 602 } 603 } 586 587 if ( ! typeTable ) { 588 typeTable = TypeTable::new_ptr(); 589 } else { 590 auto existing = typeTable->find( id ); 591 if ( existing != typeTable->end() 592 && existing->second.scope == scope 593 && addedTypeConflicts( existing->second.decl, decl ) ) return; 594 } 595 596 typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } ); 604 597 } 605 598 … … 614 607 615 608 void Indexer::addStruct( const std::string &id ) { 616 debugPrint( "Adding fwd decl for struct " << id << std::endl );617 609 addStruct( new StructDecl( id ) ); 618 610 } 619 611 620 612 void Indexer::addStruct( StructDecl *decl ) { 621 debugPrint( "Adding struct " << decl->name << std::endl );622 makeWritable();623 624 613 const std::string &id = decl->name; 625 StructTable::iterator existing = tables->structTable.find( id ); 626 if ( existing == tables->structTable.end() ) { 627 StructDecl *parent = tables->base.lookupStructAtScope( id, scope ); 628 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) { 629 tables->structTable.insert( existing, std::make_pair( id, decl ) ); 630 ++tables->size; 631 } 632 } else { 633 if ( ! addedDeclConflicts( existing->second, decl ) ) { 634 existing->second = decl; 635 } 636 } 614 615 if ( ! structTable ) { 616 structTable = StructTable::new_ptr(); 617 } else { 618 auto existing = structTable->find( id ); 619 if ( existing != structTable->end() 620 && existing->second.scope == scope 621 && addedDeclConflicts( existing->second.decl, decl ) ) return; 622 } 623 624 structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } ); 637 625 } 638 626 639 627 void Indexer::addEnum( EnumDecl *decl ) { 640 debugPrint( "Adding enum " << decl->name << std::endl );641 makeWritable();642 643 628 const std::string &id = decl->name; 644 EnumTable::iterator existing = tables->enumTable.find( id ); 645 if ( existing == tables->enumTable.end() ) { 646 EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope ); 647 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) { 648 tables->enumTable.insert( existing, std::make_pair( id, decl ) ); 649 ++tables->size; 650 } 651 } else { 652 if ( ! addedDeclConflicts( existing->second, decl ) ) { 653 existing->second = decl; 654 } 655 } 629 630 if ( ! enumTable ) { 631 enumTable = EnumTable::new_ptr(); 632 } else { 633 auto existing = enumTable->find( id ); 634 if ( existing != enumTable->end() 635 && existing->second.scope == scope 636 && addedDeclConflicts( existing->second.decl, decl ) ) return; 637 } 638 639 enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } ); 656 640 } 657 641 658 642 void Indexer::addUnion( const std::string &id ) { 659 debugPrint( "Adding fwd decl for union " << id << std::endl );660 643 addUnion( new UnionDecl( id ) ); 661 644 } 662 645 663 646 void Indexer::addUnion( UnionDecl *decl ) { 664 debugPrint( "Adding union " << decl->name << std::endl );665 makeWritable();666 667 647 const std::string &id = decl->name; 668 UnionTable::iterator existing = tables->unionTable.find( id ); 669 if ( existing == tables->unionTable.end() ) { 670 UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope ); 671 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) { 672 tables->unionTable.insert( existing, std::make_pair( id, decl ) ); 673 ++tables->size; 674 } 675 } else { 676 if ( ! addedDeclConflicts( existing->second, decl ) ) { 677 existing->second = decl; 678 } 679 } 648 649 if ( ! unionTable ) { 650 unionTable = UnionTable::new_ptr(); 651 } else { 652 auto existing = unionTable->find( id ); 653 if ( existing != unionTable->end() 654 && existing->second.scope == scope 655 && addedDeclConflicts( existing->second.decl, decl ) ) return; 656 } 657 658 unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } ); 680 659 } 681 660 682 661 void Indexer::addTrait( TraitDecl *decl ) { 683 debugPrint( "Adding trait " << decl->name << std::endl );684 makeWritable();685 686 662 const std::string &id = decl->name; 687 TraitTable::iterator existing = tables->traitTable.find( id ); 688 if ( existing == tables->traitTable.end()) {689 TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope);690 if ( ! parent || ! addedDeclConflicts( parent, decl ) ){691 tables->traitTable.insert( existing, std::make_pair( id, decl ));692 ++tables->size;693 }694 } else {695 if ( ! addedDeclConflicts( existing->second, decl ) ) {696 existing->second = decl; 697 }698 699 } 700 701 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunctionhandleConflicts ) {663 664 if ( ! traitTable ) { 665 traitTable = TraitTable::new_ptr(); 666 } else { 667 auto existing = traitTable->find( id ); 668 if ( existing != traitTable->end() 669 && existing->second.scope == scope 670 && addedDeclConflicts( existing->second.decl, decl ) ) return; 671 } 672 673 traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } ); 674 } 675 676 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, 677 OnConflict handleConflicts ) { 702 678 for ( Declaration * decl : aggr->members ) { 703 679 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { … … 705 681 if ( dwt->name == "" ) { 706 682 Type * t = dwt->get_type()->stripReferences(); 707 if ( dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType *>( t ) ) {683 if ( dynamic_cast<StructInstType*>( t ) || dynamic_cast<UnionInstType*>( t ) ) { 708 684 Expression * base = expr->clone(); 709 685 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost? … … 722 698 assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() ); 723 699 724 addMembers( aggr, expr, [withStmt](IdData & existing, const std::string &) { 725 // on conflict, delete the identifier 726 existing.deleteStmt = withStmt; 727 return true; 728 }); 700 addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) ); 729 701 } 730 702 } … … 750 722 } 751 723 752 void Indexer::enterScope() { 753 ++scope; 754 755 if ( doDebug ) { 756 std::cerr << "--- Entering scope " << scope << std::endl; 757 } 758 } 759 760 void Indexer::leaveScope() { 761 using std::cerr; 762 763 assert( scope > 0 && "cannot leave initial scope" ); 764 if ( doDebug ) { 765 cerr << "--- Leaving scope " << scope << " containing" << std::endl; 766 } 767 --scope; 768 769 while ( tables && tables->scope > scope ) { 770 if ( doDebug ) { 771 dump( tables->idTable, cerr ); 772 dump( tables->typeTable, cerr ); 773 dump( tables->structTable, cerr ); 774 dump( tables->enumTable, cerr ); 775 dump( tables->unionTable, cerr ); 776 dump( tables->traitTable, cerr ); 777 } 778 779 // swap tables for base table until we find one at an appropriate scope 780 Indexer::Impl *base = newRef( tables->base.tables ); 781 deleteRef( tables ); 782 tables = base; 783 } 784 } 785 786 void Indexer::print( std::ostream &os, int indent ) const { 787 using std::cerr; 788 789 if ( tables ) { 790 os << "--- scope " << tables->scope << " ---" << std::endl; 791 792 os << "===idTable===" << std::endl; 793 dump( tables->idTable, os ); 794 os << "===typeTable===" << std::endl; 795 dump( tables->typeTable, os ); 796 os << "===structTable===" << std::endl; 797 dump( tables->structTable, os ); 798 os << "===enumTable===" << std::endl; 799 dump( tables->enumTable, os ); 800 os << "===unionTable===" << std::endl; 801 dump( tables->unionTable, os ); 802 os << "===contextTable===" << std::endl; 803 dump( tables->traitTable, os ); 804 805 tables->base.print( os, indent ); 806 } else { 807 os << "--- end ---" << std::endl; 808 } 809 810 } 724 // void Indexer::print( std::ostream &os, int indent ) const { 725 // using std::cerr; 726 727 // if ( tables ) { 728 // os << "--- scope " << tables->scope << " ---" << std::endl; 729 730 // os << "===idTable===" << std::endl; 731 // dump( tables->idTable, os ); 732 // os << "===typeTable===" << std::endl; 733 // dump( tables->typeTable, os ); 734 // os << "===structTable===" << std::endl; 735 // dump( tables->structTable, os ); 736 // os << "===enumTable===" << std::endl; 737 // dump( tables->enumTable, os ); 738 // os << "===unionTable===" << std::endl; 739 // dump( tables->unionTable, os ); 740 // os << "===contextTable===" << std::endl; 741 // dump( tables->traitTable, os ); 742 743 // tables->base.print( os, indent ); 744 // } else { 745 // os << "--- end ---" << std::endl; 746 // } 747 // } 811 748 812 749 Expression * Indexer::IdData::combine( ResolvExpr::Cost & cost ) const { -
src/SymTab/Indexer.h
rfca6ca6 rb8665e3 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:38:55 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Aug 17 16:09:12 201713 // Update Count : 811 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Mar 8 13:55:00 2019 13 // Update Count : 9 14 14 // 15 15 16 16 #pragma once 17 17 18 #include <iosfwd> // for ostream 19 #include <list> // for list 20 #include <string> // for string 21 #include <functional> // for function 22 23 #include "SynTree/Visitor.h" // for Visitor 24 #include "SynTree/SynTree.h" // for AST nodes 18 #include <functional> // for function 19 #include <iosfwd> // for ostream 20 #include <list> // for list 21 #include <memory> // for shared_ptr, enable_shared_from_this 22 #include <string> // for string 23 24 #include "Common/PersistentMap.h" // for PersistentMap 25 #include "SynTree/SynTree.h" // for AST nodes 25 26 26 27 namespace ResolvExpr { 27 class Cost;28 class Cost; 28 29 } 29 30 30 31 namespace SymTab { 31 class Indexer {32 32 class Indexer : public std::enable_shared_from_this<SymTab::Indexer> { 33 public: 33 34 explicit Indexer(); 34 35 Indexer( const Indexer &that );36 Indexer( Indexer &&that );37 35 virtual ~Indexer(); 38 Indexer& operator= ( const Indexer &that );39 Indexer& operator= ( Indexer &&that );40 36 41 37 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to tell the indexer … … 50 46 /// non-null if this declaration is deleted 51 47 BaseSyntaxNode * deleteStmt = nullptr; 48 /// scope of identifier 49 unsigned long scope = 0; 52 50 53 51 // NOTE: shouldn't need either of these constructors, but gcc-4 does not properly support initializer lists with default members. 54 52 IdData() = default; 55 IdData( DeclarationWithType * id, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ) {} 53 IdData( 54 DeclarationWithType * id, Expression * baseExpr, BaseSyntaxNode * deleteStmt, 55 unsigned long scope ) 56 : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ), scope( scope ) {} 57 IdData( const IdData& o, BaseSyntaxNode * deleteStmt ) 58 : id( o.id ), baseExpr( o.baseExpr ), deleteStmt( deleteStmt ), scope( o.scope ) {} 56 59 57 60 Expression * combine( ResolvExpr::Cost & cost ) const; … … 71 74 TraitDecl *lookupTrait( const std::string &id ) const; 72 75 76 // void print( std::ostream &os, int indent = 0 ) const; 77 78 /// looks up a specific mangled ID in local scope only 79 // IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ); 80 // const IdData * localLookupId( const std::string &id, const std::string &mangleName ) const; 81 // equivalents to lookup functions that only look at tables at scope `scope` (which should be >= tables->scope) 82 // NamedTypeDecl *lookupTypeAtScope( const std::string &id, unsigned long scope ) const; 83 // StructDecl *lookupStructAtScope( const std::string &id, unsigned long scope ) const; 84 // EnumDecl *lookupEnumAtScope( const std::string &id, unsigned long scope ) const; 85 // UnionDecl *lookupUnionAtScope( const std::string &id, unsigned long scope ) const; 86 // TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const; 87 73 88 /// Gets the type declaration with the given ID at global scope 74 89 NamedTypeDecl *globalLookupType( const std::string &id ) const; … … 80 95 EnumDecl *globalLookupEnum( const std::string &id ) const; 81 96 82 void print( std::ostream &os, int indent = 0 ) const;83 84 /// looks up a specific mangled ID at the given scope85 IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope );86 const IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;87 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name88 bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const;89 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name90 bool hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const;91 // equivalents to lookup functions that only look at tables at scope `scope` (which should be >= tables->scope)92 NamedTypeDecl *lookupTypeAtScope( const std::string &id, unsigned long scope ) const;93 StructDecl *lookupStructAtScope( const std::string &id, unsigned long scope ) const;94 EnumDecl *lookupEnumAtScope( const std::string &id, unsigned long scope ) const;95 UnionDecl *lookupUnionAtScope( const std::string &id, unsigned long scope ) const;96 TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;97 98 typedef std::function<bool(IdData &, const std::string &)> ConflictFunction;99 100 97 void addId( DeclarationWithType * decl, Expression * baseExpr = nullptr ); 101 98 void addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ); … … 112 109 void addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ); 113 110 114 /// adds all of the members of the Aggregate (addWith helper)115 void addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction );116 117 111 /// convenience function for adding a list of Ids to the indexer 118 112 void addIds( const std::list< DeclarationWithType * > & decls ); … … 124 118 void addFunctionType( FunctionType * ftype ); 125 119 126 bool doDebug = false; ///< Display debugging trace?120 // bool doDebug = false; ///< Display debugging trace? 127 121 private: 128 struct Impl; 129 130 Impl *tables; ///< Copy-on-write instance of table data structure 131 unsigned long scope; ///< Scope index of this pointer 132 133 /// Takes a new ref to a table (returns null if null) 134 static Impl *newRef( Impl *toClone ); 135 /// Clears a ref to a table (does nothing if null) 136 static void deleteRef( Impl *toFree ); 137 138 // Removes matching autogenerated constructors and destructors 139 // so that they will not be selected 140 // void removeSpecialOverrides( FunctionDecl *decl ); 122 /// Wraps a Decl* with a scope 123 template<typename Decl> 124 struct Scoped { 125 Decl* decl; ///< declaration 126 unsigned long scope; ///< scope of this declaration 127 128 Scoped(Decl* d, unsigned long s) : decl(d), scope(s) {} 129 }; 130 131 using Ptr = std::shared_ptr<const Indexer>; 132 133 using MangleTable = PersistentMap< std::string, IdData >; 134 using IdTable = PersistentMap< std::string, MangleTable::Ptr >; 135 using TypeTable = PersistentMap< std::string, Scoped<NamedTypeDecl> >; 136 using StructTable = PersistentMap< std::string, Scoped<StructDecl> >; 137 using EnumTable = PersistentMap< std::string, Scoped<EnumDecl> >; 138 using UnionTable = PersistentMap< std::string, Scoped<UnionDecl> >; 139 using TraitTable = PersistentMap< std::string, Scoped<TraitDecl> >; 140 141 IdTable::Ptr idTable; ///< identifier namespace 142 TypeTable::Ptr typeTable; ///< type namespace 143 StructTable::Ptr structTable; ///< struct namespace 144 EnumTable::Ptr enumTable; ///< enum namespace 145 UnionTable::Ptr unionTable; ///< union namespace 146 TraitTable::Ptr traitTable; ///< trait namespace 147 148 Ptr prevScope; ///< reference to indexer for parent scope 149 unsigned long scope; ///< Scope index of this indexer 150 151 /// Gets the indexer at the given scope 152 const Indexer* atScope( unsigned long scope ) const; 153 154 /// Removes matching autogenerated constructors and destructors 155 /// so that they will not be selected 156 /// void removeSpecialOverrides( FunctionDecl *decl ); 141 157 void removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const; 142 158 143 /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope) 144 void makeWritable(); 159 /// Options for handling identifier conflicts 160 struct OnConflict { 161 enum { 162 Error, ///< Throw a semantic error 163 Delete ///< Delete the earlier version with the delete statement 164 } mode; 165 BaseSyntaxNode * deleteStmt; ///< Statement that deletes this expression 166 167 private: 168 OnConflict() : mode(Error), deleteStmt(nullptr) {} 169 OnConflict( BaseSyntaxNode * d ) : mode(Delete), deleteStmt(d) {} 170 public: 171 OnConflict( const OnConflict& ) = default; 172 173 static OnConflict error() { return {}; } 174 static OnConflict deleteWith( BaseSyntaxNode * d ) { return { d }; } 175 }; 176 177 /// true if the existing identifier conflicts with the added identifier 178 bool addedIdConflicts( 179 const IdData& existing, DeclarationWithType * added, OnConflict handleConflicts, 180 BaseSyntaxNode * deleteStmt ); 145 181 146 182 /// common code for addId, addDeletedId, etc. 147 void addId( DeclarationWithType * decl, ConflictFunction, Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr ); 183 void addId( 184 DeclarationWithType * decl, OnConflict handleConflicts, 185 Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr ); 186 187 /// adds all of the members of the Aggregate (addWith helper) 188 void addMembers( AggregateDecl * aggr, Expression * expr, OnConflict handleConflicts ); 189 190 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name 191 bool hasCompatibleCDecl( const std::string &id, const std::string &mangleName ) const; 192 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name 193 bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName ) const; 148 194 }; 149 195 } // namespace SymTab -
src/SynTree/BaseSyntaxNode.h
rfca6ca6 rb8665e3 18 18 #include "Common/CodeLocation.h" 19 19 #include "Common/Indenter.h" 20 #include "Common/Stats.h" 21 20 22 class Visitor; 21 23 class Mutator; … … 23 25 class BaseSyntaxNode { 24 26 public: 27 static Stats::Counters::SimpleCounter* new_nodes; 28 25 29 CodeLocation location; 30 31 BaseSyntaxNode() { ++*new_nodes; } 32 BaseSyntaxNode( const BaseSyntaxNode& ) { ++*new_nodes; } 26 33 27 34 virtual ~BaseSyntaxNode() {} -
src/main.cc
rfca6ca6 rb8665e3 65 65 using namespace std; 66 66 67 68 67 void NewPass(const char * const name) { 69 68 Stats::Heap::newPass(name); 70 69 using namespace Stats::Counters; 71 static auto pass_visitor_group = build<CounterGroup>("Pass Visitor"); 72 auto pass = build<CounterGroup>(name, pass_visitor_group); 73 pass_visitor_stats.depth = 0; 74 pass_visitor_stats.avg = build<AverageCounter<double>>("Average Depth", pass); 75 pass_visitor_stats.max = build<MaxCounter<double>>("Max Depth", pass); 70 71 { 72 static auto group = build<CounterGroup>("Pass Visitor"); 73 auto pass = build<CounterGroup>(name, group); 74 pass_visitor_stats.depth = 0; 75 pass_visitor_stats.avg = build<AverageCounter<double>>("Average Depth", pass); 76 pass_visitor_stats.max = build<MaxCounter<double>>("Max Depth", pass); 77 } 78 79 { 80 static auto group = build<CounterGroup>("Syntax Node"); 81 auto pass = build<CounterGroup>(name, group); 82 BaseSyntaxNode::new_nodes = build<SimpleCounter>("Allocs", pass); 83 } 76 84 } 77 85
Note: See TracChangeset
for help on using the changeset viewer.