Changeset ef5b828 for src/SymTab/Indexer.cc
- Timestamp:
- Jul 12, 2019, 1:35:58 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- fce4e31
- Parents:
- 7870799
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Indexer.cc
r7870799 ref5b828 74 74 } 75 75 76 Indexer::Indexer() 77 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 78 prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; }76 Indexer::Indexer() 77 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 78 prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; } 79 79 80 80 Indexer::~Indexer() { … … 84 84 void Indexer::lazyInitScope() { 85 85 if ( repScope < scope ) { 86 ++* stats().lazy_scopes;86 ++* stats().lazy_scopes; 87 87 // create rollback 88 prevScope = std::make_shared<Indexer>( * this );88 prevScope = std::make_shared<Indexer>( * this ); 89 89 // update repScope 90 90 repScope = scope; … … 95 95 ++scope; 96 96 97 ++* stats().new_scopes;97 ++* stats().new_scopes; 98 98 stats().avg_scope_depth->push( scope ); 99 99 stats().max_scope_depth->push( scope ); … … 103 103 if ( repScope == scope ) { 104 104 Ptr prev = prevScope; // make sure prevScope stays live 105 * this = std::move(*prevScope); // replace with previous scope105 * this = std::move(* prevScope); // replace with previous scope 106 106 } 107 107 … … 109 109 } 110 110 111 void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const {112 ++* stats().lookup_calls;111 void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const { 112 ++* stats().lookup_calls; 113 113 if ( ! idTable ) return; 114 114 115 ++* stats().map_lookups;115 ++* stats().map_lookups; 116 116 auto decls = idTable->find( id ); 117 117 if ( decls == idTable->end() ) return; … … 122 122 } 123 123 124 NamedTypeDecl *Indexer::lookupType( const std::string &id ) const { 125 ++*stats().lookup_calls; 124 const NamedTypeDecl * Indexer::lookupType( const std::string & id ) const { return lookupMutableType(id); } 125 NamedTypeDecl * Indexer::lookupMutableType( const std::string & id ) const { 126 ++* stats().lookup_calls; 126 127 if ( ! typeTable ) return nullptr; 127 ++* stats().map_lookups;128 ++* stats().map_lookups; 128 129 auto it = typeTable->find( id ); 129 130 return it == typeTable->end() ? nullptr : it->second.decl; 130 131 } 131 132 132 StructDecl *Indexer::lookupStruct( const std::string &id ) const { 133 ++*stats().lookup_calls; 133 const StructDecl * Indexer::lookupStruct( const std::string & id ) const { return lookupMutableStruct(id); } 134 StructDecl * Indexer::lookupMutableStruct( const std::string & id ) const { 135 ++* stats().lookup_calls; 134 136 if ( ! structTable ) return nullptr; 135 ++* stats().map_lookups;137 ++* stats().map_lookups; 136 138 auto it = structTable->find( id ); 137 139 return it == structTable->end() ? nullptr : it->second.decl; 138 140 } 139 141 140 EnumDecl *Indexer::lookupEnum( const std::string &id ) const { 141 ++*stats().lookup_calls; 142 const EnumDecl * Indexer::lookupEnum( const std::string & id ) const { return lookupMutableEnum(id); } 143 EnumDecl * Indexer::lookupMutableEnum( const std::string & id ) const { 144 ++* stats().lookup_calls; 142 145 if ( ! enumTable ) return nullptr; 143 ++* stats().map_lookups;146 ++* stats().map_lookups; 144 147 auto it = enumTable->find( id ); 145 148 return it == enumTable->end() ? nullptr : it->second.decl; 146 149 } 147 150 148 UnionDecl *Indexer::lookupUnion( const std::string &id ) const { 149 ++*stats().lookup_calls; 151 const UnionDecl * Indexer::lookupUnion( const std::string & id ) const { return lookupMutableUnion(id); } 152 UnionDecl * Indexer::lookupMutableUnion( const std::string & id ) const { 153 ++* stats().lookup_calls; 150 154 if ( ! unionTable ) return nullptr; 151 ++* stats().map_lookups;155 ++* stats().map_lookups; 152 156 auto it = unionTable->find( id ); 153 157 return it == unionTable->end() ? nullptr : it->second.decl; 154 158 } 155 159 156 TraitDecl *Indexer::lookupTrait( const std::string &id ) const { 157 ++*stats().lookup_calls; 160 const TraitDecl * Indexer::lookupTrait( const std::string & id ) const { return lookupMutableTrait(id); } 161 TraitDecl * Indexer::lookupMutableTrait( const std::string & id ) const { 162 ++* stats().lookup_calls; 158 163 if ( ! traitTable ) return nullptr; 159 ++* stats().map_lookups;164 ++* stats().map_lookups; 160 165 auto it = traitTable->find( id ); 161 166 return it == traitTable->end() ? nullptr : it->second.decl; 162 167 } 163 168 164 const Indexer * Indexer::atScope( unsigned long target ) const {169 const Indexer * Indexer::atScope( unsigned long target ) const { 165 170 // by lazy construction, final indexer in list has repScope 0, cannot be > target 166 171 // otherwise, will find first scope representing the target 167 const Indexer * indexer = this;172 const Indexer * indexer = this; 168 173 while ( indexer->repScope > target ) { 169 174 indexer = indexer->prevScope.get(); … … 172 177 } 173 178 174 NamedTypeDecl *Indexer::globalLookupType( const std::string &id ) const {179 const NamedTypeDecl * Indexer::globalLookupType( const std::string & id ) const { 175 180 return atScope( 0 )->lookupType( id ); 176 181 } 177 182 178 StructDecl *Indexer::globalLookupStruct( const std::string &id ) const {183 const StructDecl * Indexer::globalLookupStruct( const std::string & id ) const { 179 184 return atScope( 0 )->lookupStruct( id ); 180 185 } 181 186 182 UnionDecl *Indexer::globalLookupUnion( const std::string &id ) const {187 const UnionDecl * Indexer::globalLookupUnion( const std::string & id ) const { 183 188 return atScope( 0 )->lookupUnion( id ); 184 189 } 185 190 186 EnumDecl *Indexer::globalLookupEnum( const std::string &id ) const {191 const EnumDecl * Indexer::globalLookupEnum( const std::string & id ) const { 187 192 return atScope( 0 )->lookupEnum( id ); 188 193 } … … 207 212 } 208 213 209 210 bool Indexer::addedIdConflicts( 211 const Indexer::IdData & existing, DeclarationWithType * added,214 215 bool Indexer::addedIdConflicts( 216 const Indexer::IdData & existing, DeclarationWithType * added, 212 217 Indexer::OnConflict handleConflicts, BaseSyntaxNode * deleteStmt ) { 213 // if we're giving the same name mangling to things of different types then there is 218 // if we're giving the same name mangling to things of different types then there is 214 219 // something wrong 215 220 assert( (isObject( added ) && isObject( existing.id ) ) … … 219 224 // new definition shadows the autogenerated one, even at the same scope 220 225 return false; 221 } else if ( LinkageSpec::isMangled( added->linkage ) 222 || ResolvExpr::typesCompatible( 226 } else if ( LinkageSpec::isMangled( added->linkage ) 227 || ResolvExpr::typesCompatible( 223 228 added->get_type(), existing.id->get_type(), Indexer() ) ) { 224 229 … … 238 243 if ( isDefinition( added ) && isDefinition( existing.id ) ) { 239 244 if ( handleConflicts.mode == OnConflict::Error ) { 240 SemanticError( added, 241 isFunction( added ) ? 242 "duplicate function definition for " : 245 SemanticError( added, 246 isFunction( added ) ? 247 "duplicate function definition for " : 243 248 "duplicate object definition for " ); 244 249 } … … 255 260 } 256 261 257 bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const {262 bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const { 258 263 if ( ! idTable ) return false; 259 264 260 ++* stats().map_lookups;265 ++* stats().map_lookups; 261 266 auto decls = idTable->find( id ); 262 267 if ( decls == idTable->end() ) return false; … … 270 275 } 271 276 } 272 277 273 278 return false; 274 279 } 275 280 276 bool Indexer::hasIncompatibleCDecl( 277 const std::string & id, const std::string &mangleName ) const {281 bool Indexer::hasIncompatibleCDecl( 282 const std::string & id, const std::string &mangleName ) const { 278 283 if ( ! idTable ) return false; 279 284 280 ++* stats().map_lookups;285 ++* stats().map_lookups; 281 286 auto decls = idTable->find( id ); 282 287 if ( decls == idTable->end() ) return false; … … 295 300 296 301 /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function 297 std::string getOtypeKey( FunctionDecl * function ) {302 std::string getOtypeKey( FunctionDecl * function ) { 298 303 auto& params = function->type->parameters; 299 304 assert( ! params.empty() ); 300 305 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 301 Type * base = InitTweak::getPointerBase( params.front()->get_type() );306 Type * base = InitTweak::getPointerBase( params.front()->get_type() ); 302 307 assert( base ); 303 308 return Mangler::mangle( base ); 304 309 } 305 310 306 /// gets the declaration for the function acting on a type specified by otype key, 311 /// gets the declaration for the function acting on a type specified by otype key, 307 312 /// nullptr if none such 308 313 FunctionDecl * getFunctionForOtype( DeclarationWithType * decl, const std::string& otypeKey ) { … … 312 317 } 313 318 314 bool Indexer::removeSpecialOverrides( 319 bool Indexer::removeSpecialOverrides( 315 320 Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) { 316 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which 317 // determinethe set of ctor/dtor/assign that can be used by the requester. In particular, 318 // if the user defines a default ctor, then the generated default ctor is unavailable, 319 // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated 320 // field ctors are available. If the user defines any ctor then the generated default ctor 321 // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines 322 // anything that looks like a copy constructor, then the generated copy constructor is 321 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which 322 // determinethe set of ctor/dtor/assign that can be used by the requester. In particular, 323 // if the user defines a default ctor, then the generated default ctor is unavailable, 324 // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated 325 // field ctors are available. If the user defines any ctor then the generated default ctor 326 // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines 327 // anything that looks like a copy constructor, then the generated copy constructor is 323 328 // unavailable, and likewise for the assignment operator. 324 329 … … 340 345 std::vector< MangleTable::value_type > deleted; 341 346 bool alreadyUserDefinedFunc = false; 342 343 for ( const auto& entry : * mangleTable ) {347 348 for ( const auto& entry : * mangleTable ) { 344 349 // skip decls that aren't functions or are for the wrong type 345 350 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); … … 368 373 // perform removals from mangle table, and deletions if necessary 369 374 for ( const auto& key : removed ) { 370 ++* stats().map_mutations;375 ++* stats().map_mutations; 371 376 mangleTable = mangleTable->erase( key ); 372 377 } 373 378 if ( ! alreadyUserDefinedFunc ) for ( const auto& entry : deleted ) { 374 ++* stats().map_mutations;379 ++* stats().map_mutations; 375 380 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } ); 376 381 } … … 379 384 // if this is the first user-defined function, delete non-user-defined overloads 380 385 std::vector< MangleTable::value_type > deleted; 381 382 for ( const auto& entry : * mangleTable ) {386 387 for ( const auto& entry : * mangleTable ) { 383 388 // skip decls that aren't functions or are for the wrong type 384 389 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); … … 402 407 // this needs to be a separate loop because of iterator invalidation 403 408 for ( const auto& entry : deleted ) { 404 ++* stats().map_mutations;409 ++* stats().map_mutations; 405 410 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } ); 406 411 } … … 408 413 // this is an overridable generated function 409 414 // if there already exists a matching user-defined function, delete this appropriately 410 for ( const auto& entry : * mangleTable ) {415 for ( const auto& entry : * mangleTable ) { 411 416 // skip decls that aren't functions or are for the wrong type 412 417 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); … … 418 423 if ( dataIsCopyFunc ) { 419 424 // remove current function if exists a user-defined copy function 420 // since the signatures for copy functions don't need to match exactly, using 425 // since the signatures for copy functions don't need to match exactly, using 421 426 // a delete statement is the wrong approach 422 427 if ( InitTweak::isCopyFunction( decl, decl->name ) ) return false; … … 428 433 } 429 434 } 430 435 431 436 // nothing (more) to fix, return true 432 437 return true; 433 438 } 434 439 435 void Indexer::addId( 436 DeclarationWithType * decl, OnConflict handleConflicts, Expression * baseExpr,440 void Indexer::addId( 441 DeclarationWithType * decl, OnConflict handleConflicts, Expression * baseExpr, 437 442 BaseSyntaxNode * deleteStmt ) { 438 ++* stats().add_calls;443 ++* stats().add_calls; 439 444 const std::string &name = decl->name; 440 445 if ( name == "" ) return; 441 446 442 447 std::string mangleName; 443 448 if ( LinkageSpec::isOverridable( decl->linkage ) ) { 444 // mangle the name without including the appropriate suffix, so overridable routines 449 // mangle the name without including the appropriate suffix, so overridable routines 445 450 // are placed into the same "bucket" as their user defined versions. 446 451 mangleName = Mangler::mangle( decl, false ); … … 449 454 } // if 450 455 451 // this ensures that no two declarations with the same unmangled name at the same scope 456 // this ensures that no two declarations with the same unmangled name at the same scope 452 457 // both have C linkage 453 458 if ( LinkageSpec::isMangled( decl->linkage ) ) { … … 457 462 } 458 463 } else { 459 // NOTE: only correct if name mangling is completely isomorphic to C 464 // NOTE: only correct if name mangling is completely isomorphic to C 460 465 // type-compatibility, which it may not be. 461 466 if ( hasIncompatibleCDecl( name, mangleName ) ) { … … 470 475 mangleTable = MangleTable::new_ptr(); 471 476 } else { 472 ++* stats().map_lookups;477 ++* stats().map_lookups; 473 478 auto decls = idTable->find( name ); 474 479 if ( decls == idTable->end() ) { … … 477 482 mangleTable = decls->second; 478 483 // skip in-scope repeat declarations of same identifier 479 ++* stats().map_lookups;484 ++* stats().map_lookups; 480 485 auto existing = mangleTable->find( mangleName ); 481 486 if ( existing != mangleTable->end() … … 486 491 // set delete expression for conflicting identifier 487 492 lazyInitScope(); 488 * stats().map_mutations += 2;493 * stats().map_mutations += 2; 489 494 idTable = idTable->set( 490 495 name, 491 mangleTable->set( 492 mangleName, 496 mangleTable->set( 497 mangleName, 493 498 IdData{ existing->second, handleConflicts.deleteStmt } ) ); 494 499 } … … 504 509 // Ensure that auto-generated ctor/dtor/assignment are deleted if necessary 505 510 if ( ! removeSpecialOverrides( data, mangleTable ) ) return; 506 * stats().map_mutations += 2;511 * stats().map_mutations += 2; 507 512 idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) ); 508 513 } … … 518 523 } 519 524 520 bool addedTypeConflicts( NamedTypeDecl * existing, NamedTypeDecl *added ) {525 bool addedTypeConflicts( NamedTypeDecl * existing, NamedTypeDecl * added ) { 521 526 if ( existing->base == nullptr ) { 522 527 return false; … … 530 535 } 531 536 } 532 // does not need to be added to the table if both existing and added have a base that are 537 // does not need to be added to the table if both existing and added have a base that are 533 538 // the same 534 539 return true; 535 540 } 536 541 537 void Indexer::addType( NamedTypeDecl * decl ) {538 ++* stats().add_calls;539 const std::string & id = decl->name;540 541 if ( ! typeTable ) { 542 void Indexer::addType( NamedTypeDecl * decl ) { 543 ++* stats().add_calls; 544 const std::string & id = decl->name; 545 546 if ( ! typeTable ) { 542 547 typeTable = TypeTable::new_ptr(); 543 548 } else { 544 ++* stats().map_lookups;549 ++* stats().map_lookups; 545 550 auto existing = typeTable->find( id ); 546 if ( existing != typeTable->end() 547 && existing->second.scope == scope 551 if ( existing != typeTable->end() 552 && existing->second.scope == scope 548 553 && addedTypeConflicts( existing->second.decl, decl ) ) return; 549 554 } 550 555 551 556 lazyInitScope(); 552 ++* stats().map_mutations;557 ++* stats().map_mutations; 553 558 typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } ); 554 559 } 555 560 556 bool addedDeclConflicts( AggregateDecl * existing, AggregateDecl *added ) {561 bool addedDeclConflicts( AggregateDecl * existing, AggregateDecl * added ) { 557 562 if ( ! existing->body ) { 558 563 return false; … … 563 568 } 564 569 565 void Indexer::addStruct( const std::string & id ) {570 void Indexer::addStruct( const std::string & id ) { 566 571 addStruct( new StructDecl( id ) ); 567 572 } 568 573 569 void Indexer::addStruct( StructDecl * decl ) {570 ++* stats().add_calls;571 const std::string & id = decl->name;574 void Indexer::addStruct( StructDecl * decl ) { 575 ++* stats().add_calls; 576 const std::string & id = decl->name; 572 577 573 578 if ( ! structTable ) { 574 579 structTable = StructTable::new_ptr(); 575 580 } else { 576 ++* stats().map_lookups;581 ++* stats().map_lookups; 577 582 auto existing = structTable->find( id ); 578 if ( existing != structTable->end() 579 && existing->second.scope == scope 583 if ( existing != structTable->end() 584 && existing->second.scope == scope 580 585 && addedDeclConflicts( existing->second.decl, decl ) ) return; 581 586 } 582 587 583 588 lazyInitScope(); 584 ++* stats().map_mutations;589 ++* stats().map_mutations; 585 590 structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } ); 586 591 } 587 592 588 void Indexer::addEnum( EnumDecl * decl ) {589 ++* stats().add_calls;590 const std::string & id = decl->name;593 void Indexer::addEnum( EnumDecl * decl ) { 594 ++* stats().add_calls; 595 const std::string & id = decl->name; 591 596 592 597 if ( ! enumTable ) { 593 598 enumTable = EnumTable::new_ptr(); 594 599 } else { 595 ++* stats().map_lookups;600 ++* stats().map_lookups; 596 601 auto existing = enumTable->find( id ); 597 if ( existing != enumTable->end() 598 && existing->second.scope == scope 602 if ( existing != enumTable->end() 603 && existing->second.scope == scope 599 604 && addedDeclConflicts( existing->second.decl, decl ) ) return; 600 605 } 601 606 602 607 lazyInitScope(); 603 ++* stats().map_mutations;608 ++* stats().map_mutations; 604 609 enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } ); 605 610 } 606 611 607 void Indexer::addUnion( const std::string & id ) {612 void Indexer::addUnion( const std::string & id ) { 608 613 addUnion( new UnionDecl( id ) ); 609 614 } 610 615 611 void Indexer::addUnion( UnionDecl * decl ) {612 ++* stats().add_calls;613 const std::string & id = decl->name;616 void Indexer::addUnion( UnionDecl * decl ) { 617 ++* stats().add_calls; 618 const std::string & id = decl->name; 614 619 615 620 if ( ! unionTable ) { 616 621 unionTable = UnionTable::new_ptr(); 617 622 } else { 618 ++* stats().map_lookups;623 ++* stats().map_lookups; 619 624 auto existing = unionTable->find( id ); 620 if ( existing != unionTable->end() 621 && existing->second.scope == scope 625 if ( existing != unionTable->end() 626 && existing->second.scope == scope 622 627 && addedDeclConflicts( existing->second.decl, decl ) ) return; 623 628 } 624 629 625 630 lazyInitScope(); 626 ++* stats().map_mutations;631 ++* stats().map_mutations; 627 632 unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } ); 628 633 } 629 634 630 void Indexer::addTrait( TraitDecl * decl ) {631 ++* stats().add_calls;632 const std::string & id = decl->name;635 void Indexer::addTrait( TraitDecl * decl ) { 636 ++* stats().add_calls; 637 const std::string & id = decl->name; 633 638 634 639 if ( ! traitTable ) { 635 640 traitTable = TraitTable::new_ptr(); 636 641 } else { 637 ++* stats().map_lookups;642 ++* stats().map_lookups; 638 643 auto existing = traitTable->find( id ); 639 if ( existing != traitTable->end() 640 && existing->second.scope == scope 644 if ( existing != traitTable->end() 645 && existing->second.scope == scope 641 646 && addedDeclConflicts( existing->second.decl, decl ) ) return; 642 647 } 643 648 644 649 lazyInitScope(); 645 ++* stats().map_mutations;650 ++* stats().map_mutations; 646 651 traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } ); 647 652 } 648 653 649 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, 654 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, 650 655 OnConflict handleConflicts ) { 651 656 for ( Declaration * decl : aggr->members ) { … … 654 659 if ( dwt->name == "" ) { 655 660 Type * t = dwt->get_type()->stripReferences(); 656 if ( dynamic_cast<StructInstType *>( t ) || dynamic_cast<UnionInstType*>( t ) ) {661 if ( dynamic_cast<StructInstType *>( t ) || dynamic_cast<UnionInstType *>( t ) ) { 657 662 Expression * base = expr->clone(); 658 663 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost?
Note: See TracChangeset
for help on using the changeset viewer.