Changeset b3ed43a3
- Timestamp:
- Nov 25, 2020, 12:25:06 PM (3 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 6f1e695
- Parents:
- 04994aa (diff), 5e82d56 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 17 added
- 12 edited
- 9 moved
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/kernel.cfa
r04994aa rb3ed43a3 379 379 380 380 ready_schedule_lock(); 381 push( thrd->curr_cluster, thrd ); 382 __wake_one(thrd->curr_cluster); 381 // Dereference the thread now because once we push it, there is not guaranteed it's still valid. 382 struct cluster * cl = thrd->curr_cluster; 383 384 // push the thread to the cluster ready-queue 385 push( cl, thrd ); 386 387 // variable thrd is no longer safe to use 388 389 // wake the cluster using the save variable. 390 __wake_one( cl ); 383 391 ready_schedule_unlock(); 384 392 -
src/AST/Expr.hpp
r04994aa rb3ed43a3 299 299 }; 300 300 301 /// Whether a cast existed in the program source or not 301 /// Inidicates whether the cast is introduced by the CFA type system. 302 /// GeneratedCast for casts that the resolver introduces to force a return type 303 /// ExplicitCast for casts from user code 304 /// ExplicitCast for casts from desugaring advanced CFA features into simpler CFA 305 /// example 306 /// int * p; // declaration 307 /// (float *) p; // use, with subject cast 308 /// subject cast being GeneratedCast means we are considering an interpretation with a type mismatch 309 /// subject cast being ExplicitCast means someone in charge wants it that way 302 310 enum GeneratedFlag { ExplicitCast, GeneratedCast }; 303 311 -
src/AST/SymbolTable.cpp
r04994aa rb3ed43a3 95 95 } 96 96 97 SymbolTable::SpecialFunctionKind SymbolTable::getSpecialFunctionKind(const std::string & name) { 98 if (name == "?{}") return CTOR; 99 if (name == "^?{}") return DTOR; 100 if (name == "?=?") return ASSIGN; 101 return NUMBER_OF_KINDS; 102 } 103 97 104 std::vector<SymbolTable::IdData> SymbolTable::lookupId( const std::string &id ) const { 105 static Stats::Counters::CounterGroup * name_lookup_stats = Stats::Counters::build<Stats::Counters::CounterGroup>("Name Lookup Stats"); 106 static std::map<std::string, Stats::Counters::SimpleCounter *> lookups_by_name; 107 static std::map<std::string, Stats::Counters::SimpleCounter *> candidates_by_name; 108 109 SpecialFunctionKind kind = getSpecialFunctionKind(id); 110 if (kind != NUMBER_OF_KINDS) return specialLookupId(kind); 111 98 112 ++*stats().lookup_calls; 99 113 if ( ! idTable ) return {}; … … 107 121 out.push_back( decl.second ); 108 122 } 123 124 if (Stats::Counters::enabled) { 125 if (! lookups_by_name.count(id)) { 126 // leaks some strings, but it is because Counters do not hold them 127 auto lookupCounterName = new std::string(id + "%count"); 128 auto candidatesCounterName = new std::string(id + "%candidate"); 129 lookups_by_name.emplace(id, new Stats::Counters::SimpleCounter(lookupCounterName->c_str(), name_lookup_stats)); 130 candidates_by_name.emplace(id, new Stats::Counters::SimpleCounter(candidatesCounterName->c_str(), name_lookup_stats)); 131 } 132 (*lookups_by_name[id]) ++; 133 *candidates_by_name[id] += out.size(); 134 } 135 136 return out; 137 } 138 139 std::vector<SymbolTable::IdData> SymbolTable::specialLookupId( SymbolTable::SpecialFunctionKind kind, const std::string & otypeKey ) const { 140 static Stats::Counters::CounterGroup * special_stats = Stats::Counters::build<Stats::Counters::CounterGroup>("Special Lookups"); 141 static Stats::Counters::SimpleCounter * stat_counts[3] = { 142 Stats::Counters::build<Stats::Counters::SimpleCounter>("constructor - count", special_stats), 143 Stats::Counters::build<Stats::Counters::SimpleCounter>("destructor - count", special_stats), 144 Stats::Counters::build<Stats::Counters::SimpleCounter>("assignment - count", special_stats) 145 }; 146 147 static Stats::Counters::SimpleCounter * stat_candidates[3] = { 148 Stats::Counters::build<Stats::Counters::SimpleCounter>("constructor - candidates", special_stats), 149 Stats::Counters::build<Stats::Counters::SimpleCounter>("destructor - candidates", special_stats), 150 Stats::Counters::build<Stats::Counters::SimpleCounter>("assignment - candidates", special_stats) 151 }; 152 153 static Stats::Counters::SimpleCounter * num_lookup_with_key 154 = Stats::Counters::build<Stats::Counters::SimpleCounter>("keyed lookups", special_stats); 155 static Stats::Counters::SimpleCounter * num_lookup_without_key 156 = Stats::Counters::build<Stats::Counters::SimpleCounter>("unkeyed lookups", special_stats); 157 158 assert (kind != NUMBER_OF_KINDS); 159 ++*stats().lookup_calls; 160 if ( ! specialFunctionTable[kind] ) return {}; 161 162 std::vector<IdData> out; 163 164 if (otypeKey.empty()) { // returns everything 165 ++*num_lookup_without_key; 166 for (auto & table : *specialFunctionTable[kind]) { 167 for (auto & decl : *table.second) { 168 out.push_back(decl.second); 169 } 170 } 171 } 172 else { 173 ++*num_lookup_with_key; 174 ++*stats().map_lookups; 175 auto decls = specialFunctionTable[kind]->find(otypeKey); 176 if (decls == specialFunctionTable[kind]->end()) return {}; 177 178 for (auto decl : *(decls->second)) { 179 out.push_back(decl.second); 180 } 181 } 182 183 ++*stat_counts[kind]; 184 *stat_candidates[kind] += out.size(); 185 109 186 return out; 110 187 } … … 366 443 namespace { 367 444 /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function 368 std::string getOtypeKey( const Function Decl * function) {369 const auto & params = f unction->type->params;445 std::string getOtypeKey( const FunctionType * ftype, bool stripParams = true ) { 446 const auto & params = ftype->params; 370 447 assert( ! params.empty() ); 371 448 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 372 449 const Type * base = InitTweak::getPointerBase( params.front() ); 373 450 assert( base ); 374 return Mangle::mangle( base ); 451 if (stripParams) { 452 if (dynamic_cast<const PointerType *>(base)) return Mangle::Encoding::pointer; 453 return Mangle::mangle( base, Mangle::Type | Mangle::NoGenericParams ); 454 } 455 else 456 return Mangle::mangle( base ); 375 457 } 376 458 … … 380 462 const DeclWithType * decl, const std::string & otypeKey ) { 381 463 auto func = dynamic_cast< const FunctionDecl * >( decl ); 382 if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr;464 if ( ! func || otypeKey != getOtypeKey( func->type, false ) ) return nullptr; 383 465 return func; 384 466 } … … 405 487 bool dataIsUserDefinedFunc = ! function->linkage.is_overrideable; 406 488 bool dataIsCopyFunc = InitTweak::isCopyFunction( function ); 407 std::string dataOtypeKey = getOtypeKey( function );489 std::string dataOtypeKey = getOtypeKey( function->type, false ); // requires exact match to override autogen 408 490 409 491 if ( dataIsUserDefinedFunc && dataIsCopyFunc ) { … … 577 659 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 578 660 const Decl * deleter ) { 661 SpecialFunctionKind kind = getSpecialFunctionKind(decl->name); 662 if (kind == NUMBER_OF_KINDS) { // not a special decl 663 addId(decl, decl->name, idTable, handleConflicts, baseExpr, deleter); 664 } 665 else { 666 std::string key; 667 if (auto func = dynamic_cast<const FunctionDecl *>(decl)) { 668 key = getOtypeKey(func->type); 669 } 670 else if (auto obj = dynamic_cast<const ObjectDecl *>(decl)) { 671 key = getOtypeKey(obj->type.strict_as<PointerType>()->base.strict_as<FunctionType>()); 672 } 673 else { 674 assertf(false, "special decl with non-function type"); 675 } 676 addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 677 } 678 } 679 680 void SymbolTable::addId( 681 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 682 const Decl * deleter ) { 579 683 ++*stats().add_calls; 580 684 const std::string &name = decl->name; … … 607 711 // ensure tables exist and add identifier 608 712 MangleTable::Ptr mangleTable; 609 if ( ! idTable ) {610 idTable = IdTable::new_ptr();713 if ( ! table ) { 714 table = IdTable::new_ptr(); 611 715 mangleTable = MangleTable::new_ptr(); 612 716 } else { 613 717 ++*stats().map_lookups; 614 auto decls = idTable->find( name);615 if ( decls == idTable->end() ) {718 auto decls = table->find( lookupKey ); 719 if ( decls == table->end() ) { 616 720 mangleTable = MangleTable::new_ptr(); 617 721 } else { … … 628 732 lazyInitScope(); 629 733 *stats().map_mutations += 2; 630 idTable = idTable->set(631 name,734 table = table->set( 735 lookupKey, 632 736 mangleTable->set( 633 737 mangleName, … … 644 748 IdData data{ decl, baseExpr, deleter, scope }; 645 749 // Ensure that auto-generated ctor/dtor/assignment are deleted if necessary 646 if ( ! removeSpecialOverrides( data, mangleTable ) ) return; 750 if (table != idTable) { // adding to special table 751 if ( ! removeSpecialOverrides( data, mangleTable ) ) return; 752 } 647 753 *stats().map_mutations += 2; 648 idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) );754 table = table->set( lookupKey, mangleTable->set( mangleName, std::move(data) ) ); 649 755 } 650 756 -
src/AST/SymbolTable.hpp
r04994aa rb3ed43a3 33 33 class SymbolTable final : public std::enable_shared_from_this<ast::SymbolTable> { 34 34 public: 35 /// special functions stored in dedicated tables, with different lookup keys 36 enum SpecialFunctionKind {CTOR, DTOR, ASSIGN, NUMBER_OF_KINDS}; 37 static SpecialFunctionKind getSpecialFunctionKind(const std::string & name); 38 35 39 /// Stored information about a declaration 36 40 struct IdData { … … 77 81 UnionTable::Ptr unionTable; ///< union namespace 78 82 TraitTable::Ptr traitTable; ///< trait namespace 83 IdTable::Ptr specialFunctionTable[NUMBER_OF_KINDS]; 84 85 // using SpecialFuncTable = PersistentMap< std::string, IdTable::Ptr >; // fname (ctor/dtor/assign) - otypekey 86 // SpecialFuncTable::Ptr specialFuncTable; 79 87 80 88 using Ptr = std::shared_ptr<const SymbolTable>; … … 95 103 /// Gets all declarations with the given ID 96 104 std::vector<IdData> lookupId( const std::string &id ) const; 105 /// Gets special functions associated with a type; if no key is given, returns everything 106 std::vector<IdData> specialLookupId( SpecialFunctionKind kind, const std::string & otypeKey = "" ) const; 97 107 /// Gets the top-most type declaration with the given ID 98 108 const NamedTypeDecl * lookupType( const std::string &id ) const; … … 186 196 const Decl * deleter = nullptr ); 187 197 198 /// common code for addId when special decls are placed into separate tables 199 void addId( 200 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts, 201 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr); 202 188 203 /// adds all of the members of the Aggregate (addWith helper) 189 204 void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts ); -
src/AST/Type.cpp
r04994aa rb3ed43a3 216 216 } 217 217 218 bool isUnboundType(const Type * type) { 219 if (auto typeInst = dynamic_cast<const TypeInstType *>(type)) { 220 // xxx - look for a type name produced by renameTyVars. 221 222 // TODO: once TypeInstType representation is updated, it should properly check 223 // if the context id is filled. this is a temporary hack for now 224 if (std::count(typeInst->name.begin(), typeInst->name.end(), '_') >= 3) { 225 return true; 226 } 227 } 228 return false; 229 } 230 218 231 } 219 232 -
src/AST/Type.hpp
r04994aa rb3ed43a3 535 535 }; 536 536 537 bool isUnboundType(const Type * type); 538 537 539 } 538 540 -
src/InitTweak/FixInit.h
r04994aa rb3ed43a3 21 21 class Declaration; 22 22 namespace ast { 23 classTranslationUnit;23 struct TranslationUnit; 24 24 } 25 25 -
src/Parser/ParseNode.h
r04994aa rb3ed43a3 37 37 class Attribute; 38 38 class Declaration; 39 classDeclarationNode;39 struct DeclarationNode; 40 40 class DeclarationWithType; 41 41 class ExpressionNode; 42 42 class Initializer; 43 classStatementNode;43 struct StatementNode; 44 44 45 45 //############################################################################## -
src/ResolvExpr/CandidateFinder.cpp
r04994aa rb3ed43a3 43 43 #include "SymTab/Validate.h" // for validateType 44 44 #include "Tuples/Tuples.h" // for handleTupleAssignment 45 #include "InitTweak/InitTweak.h" // for getPointerBase 46 47 #include "Common/Stats/Counter.h" 45 48 46 49 #define PRINT( text ) if ( resolvep ) { text } … … 864 867 865 868 void postvisit( const ast::UntypedExpr * untypedExpr ) { 866 CandidateFinder funcFinder{ symtab, tenv };867 funcFinder.find( untypedExpr->func, ResolvMode::withAdjustment() );868 // short-circuit if no candidates869 if ( funcFinder.candidates.empty() ) return;870 871 reason.code = NoMatch;872 873 869 std::vector< CandidateFinder > argCandidates = 874 870 selfFinder.findSubExprs( untypedExpr->args ); … … 877 873 // if not tuple assignment, handled as normal function call 878 874 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates ); 875 876 CandidateFinder funcFinder{ symtab, tenv }; 877 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) { 878 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 879 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { 880 assertf(!argCandidates.empty(), "special function call without argument"); 881 for (auto & firstArgCand: argCandidates[0]) { 882 ast::ptr<ast::Type> argType = firstArgCand->expr->result; 883 firstArgCand->env.apply(argType); 884 // strip references 885 // xxx - is this correct? 886 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base; 887 888 // convert 1-tuple to plain type 889 if (auto tuple = argType.as<ast::TupleType>()) { 890 if (tuple->size() == 1) { 891 argType = tuple->types[0]; 892 } 893 } 894 895 // if argType is an unbound type parameter, all special functions need to be searched. 896 if (isUnboundType(argType)) { 897 funcFinder.otypeKeys.clear(); 898 break; 899 } 900 901 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer); 902 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type)); 903 } 904 } 905 } 906 // if candidates are already produced, do not fail 907 // xxx - is it possible that handleTupleAssignment and main finder both produce candidates? 908 // this means there exists ctor/assign functions with a tuple as first parameter. 909 funcFinder.find( untypedExpr->func, selfFinder.candidates.empty() ? ResolvMode::withAdjustment() : ResolvMode::withoutFailFast() ); 910 // short-circuit if no candidates 911 // if ( funcFinder.candidates.empty() ) return; 912 913 reason.code = NoMatch; 879 914 880 915 // find function operators … … 1066 1101 // unification run for side-effects 1067 1102 unify( toType, cand->expr->result, cand->env, need, have, open, symtab ); 1068 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1069 symtab, cand->env ); 1103 Cost thisCost = 1104 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast) 1105 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ) 1106 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ); 1107 1070 1108 PRINT( 1071 1109 std::cerr << "working on cast with result: " << toType << std::endl; … … 1187 1225 1188 1226 void postvisit( const ast::NameExpr * nameExpr ) { 1189 std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name ); 1227 std::vector< ast::SymbolTable::IdData > declList; 1228 if (!selfFinder.otypeKeys.empty()) { 1229 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 1230 assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str()); 1231 1232 for (auto & otypeKey: selfFinder.otypeKeys) { 1233 auto result = symtab.specialLookupId(kind, otypeKey); 1234 declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end())); 1235 } 1236 } 1237 else { 1238 declList = symtab.lookupId( nameExpr->name ); 1239 } 1190 1240 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1241 1191 1242 if( declList.empty() ) return; 1192 1243 … … 1543 1594 1544 1595 // unification run for side-effects 1545 unify( toType, cand->expr->result, env, need, have, open, symtab ); 1596 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab ); 1597 (void) canUnify; 1546 1598 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1599 symtab, env ); 1600 PRINT( 1601 Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1547 1602 symtab, env ); 1548 1603 std::cerr << "Considering initialization:"; 1604 std::cerr << std::endl << " FROM: " << cand->expr->result << std::endl; 1605 std::cerr << std::endl << " TO: " << toType << std::endl; 1606 std::cerr << std::endl << " Unification " << (canUnify ? "succeeded" : "failed"); 1607 std::cerr << std::endl << " Legacy cost " << legacyCost; 1608 std::cerr << std::endl << " New cost " << thisCost; 1609 std::cerr << std::endl; 1610 ) 1549 1611 if ( thisCost != Cost::infinity ) { 1550 1612 // count one safe conversion for each value that is thrown away … … 1558 1620 } 1559 1621 } 1622 1560 1623 } 1561 1624 -
src/ResolvExpr/CandidateFinder.hpp
r04994aa rb3ed43a3 31 31 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 32 32 ast::ptr< ast::Type > targetType; ///< Target type for resolution 33 std::set< std::string > otypeKeys; /// different type may map to same key 33 34 34 35 CandidateFinder( -
src/ResolvExpr/Resolver.h
r04994aa rb3ed43a3 35 35 class StmtExpr; 36 36 class SymbolTable; 37 classTranslationUnit;37 struct TranslationUnit; 38 38 class Type; 39 39 class TypeEnvironment; … … 63 63 ast::ptr< ast::Expr > resolveInVoidContext( 64 64 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env ); 65 /// Resolve `untyped` to the single expression whose candidate is the best match for the 65 /// Resolve `untyped` to the single expression whose candidate is the best match for the 66 66 /// given type. 67 67 ast::ptr< ast::Expr > findSingleExpression( -
src/ResolvExpr/SatisfyAssertions.cpp
r04994aa rb3ed43a3 167 167 // find candidates that unify with the desired type 168 168 AssnCandidateList matches; 169 for ( const ast::SymbolTable::IdData & cdata : sat.symtab.lookupId( assn.first->name ) ) { 169 170 std::vector<ast::SymbolTable::IdData> candidates; 171 auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->name); 172 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { 173 // prefilter special decls by argument type, if already known 174 ast::ptr<ast::Type> thisArgType = strict_dynamic_cast<const ast::PointerType *>(assn.first->get_type())->base 175 .strict_as<ast::FunctionType>()->params[0] 176 .strict_as<ast::ReferenceType>()->base; 177 sat.cand->env.apply(thisArgType); 178 179 std::string otypeKey = ""; 180 if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer; 181 else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams); 182 183 candidates = sat.symtab.specialLookupId(kind, otypeKey); 184 } 185 else { 186 candidates = sat.symtab.lookupId(assn.first->name); 187 } 188 for ( const ast::SymbolTable::IdData & cdata : candidates ) { 170 189 const ast::DeclWithType * candidate = cdata.id; 171 190
Note: See TracChangeset
for help on using the changeset viewer.