Changes in / [490db327:c95b115]
- Location:
- src
- Files:
-
- 4 deleted
- 24 edited
-
Concurrency/Keywords.cc (modified) (1 diff)
-
InitTweak/GenInit.cc (modified) (3 diffs)
-
InitTweak/InitTweak.cc (modified) (3 diffs)
-
ResolvExpr/AlternativeFinder.cc (modified) (7 diffs)
-
ResolvExpr/AlternativeFinder.h (modified) (2 diffs)
-
ResolvExpr/TypeEnvironment.cc (modified) (1 diff)
-
ResolvExpr/TypeEnvironment.h (modified) (1 diff)
-
SymTab/Mangler.cc (modified) (3 diffs)
-
SymTab/Mangler.h (modified) (3 diffs)
-
Tuples/TupleAssignment.cc (modified) (11 diffs)
-
Tuples/Tuples.h (modified) (2 diffs)
-
benchmark/Makefile.am (modified) (2 diffs)
-
benchmark/Makefile.in (modified) (4 diffs)
-
benchmark/compile/empty.c (deleted)
-
benchmark/creation/cfa_cor.c (modified) (1 diff)
-
libcfa/Makefile.am (modified) (1 diff)
-
libcfa/Makefile.in (modified) (2 diffs)
-
libcfa/bits/containers.h (deleted)
-
libcfa/bits/defs.h (deleted)
-
libcfa/bits/locks.h (deleted)
-
libcfa/concurrency/alarm.c (modified) (3 diffs)
-
libcfa/concurrency/invoke.h (modified) (4 diffs)
-
libcfa/concurrency/kernel (modified) (3 diffs)
-
libcfa/concurrency/kernel.c (modified) (17 diffs)
-
libcfa/concurrency/kernel_private.h (modified) (2 diffs)
-
libcfa/concurrency/monitor.c (modified) (14 diffs)
-
libcfa/concurrency/preemption.c (modified) (1 diff)
-
prelude/builtins.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Concurrency/Keywords.cc
r490db327 rc95b115 553 553 ), 554 554 new ListInit( 555 map_range < std::list<Initializer*> > ( args, [ ](DeclarationWithType * var ){555 map_range < std::list<Initializer*> > ( args, [this](DeclarationWithType * var ){ 556 556 Type * type = var->get_type()->clone(); 557 557 type->set_mutex( false ); -
src/InitTweak/GenInit.cc
r490db327 rc95b115 214 214 } 215 215 // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable) 216 return managedTypes.find( SymTab::Mangler::mangle Concrete( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );216 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end() || GenPoly::isPolyType( type ); 217 217 } 218 218 … … 232 232 Type * type = InitTweak::getPointerBase( params.front()->get_type() ); 233 233 assert( type ); 234 managedTypes.insert( SymTab::Mangler::mangle Concrete( type ) );234 managedTypes.insert( SymTab::Mangler::mangle( type ) ); 235 235 } 236 236 } … … 242 242 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { 243 243 if ( isManaged( field ) ) { 244 // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that245 // polymorphic constructors make generic types managed types246 244 StructInstType inst( Type::Qualifiers(), aggregateDecl ); 247 managedTypes.insert( SymTab::Mangler::mangle Concrete( &inst ) );245 managedTypes.insert( SymTab::Mangler::mangle( &inst ) ); 248 246 break; 249 247 } -
src/InitTweak/InitTweak.cc
r490db327 rc95b115 98 98 class InitExpander::ExpanderImpl { 99 99 public: 100 virtual ~ExpanderImpl() = default;101 100 virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0; 102 101 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0; … … 106 105 public: 107 106 InitImpl( Initializer * init ) : init( init ) {} 108 virtual ~InitImpl() = default;109 107 110 108 virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) { … … 123 121 public: 124 122 ExprImpl( Expression * expr ) : arg( expr ) {} 125 virtual ~ExprImpl() { delete arg; } 123 124 ~ExprImpl() { delete arg; } 126 125 127 126 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { -
src/ResolvExpr/AlternativeFinder.cc
r490db327 rc95b115 22 22 #include <memory> // for allocator_traits<>::value_type 23 23 #include <utility> // for pair 24 #include <vector> // for vector25 24 26 25 #include "Alternative.h" // for AltList, Alternative … … 334 333 tmpCost.incPoly( -tmpCost.get_polyCost() ); 335 334 if ( tmpCost != Cost::zero ) { 335 // if ( convCost != Cost::zero ) { 336 336 Type *newType = formalType->clone(); 337 337 env.apply( newType ); … … 405 405 /// needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() ); 406 406 } 407 } 408 409 /// instantiate a single argument by matching actuals from [actualIt, actualEnd) against formalType, 410 /// producing expression(s) in out and their total cost in cost. 411 template< typename AltIterator, typename OutputIterator > 412 bool instantiateArgument( Type * formalType, Initializer * defaultValue, AltIterator & actualIt, AltIterator actualEnd, OpenVarSet & openVars, TypeEnvironment & resultEnv, AssertionSet & resultNeed, AssertionSet & resultHave, const SymTab::Indexer & indexer, Cost & cost, OutputIterator out ) { 413 if ( TupleType * tupleType = dynamic_cast< TupleType * >( formalType ) ) { 414 // formalType is a TupleType - group actuals into a TupleExpr whose type unifies with the TupleType 415 std::list< Expression * > exprs; 416 for ( Type * type : *tupleType ) { 417 if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( exprs ) ) ) { 418 deleteAll( exprs ); 419 return false; 420 } 421 } 422 *out++ = new TupleExpr( exprs ); 423 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) { 424 // xxx - mixing default arguments with variadic?? 425 std::list< Expression * > exprs; 426 for ( ; actualIt != actualEnd; ++actualIt ) { 427 exprs.push_back( actualIt->expr->clone() ); 428 cost += actualIt->cost; 429 } 430 Expression * arg = nullptr; 431 if ( exprs.size() == 1 && Tuples::isTtype( exprs.front()->get_result() ) ) { 432 // the case where a ttype value is passed directly is special, e.g. for argument forwarding purposes 433 // xxx - what if passing multiple arguments, last of which is ttype? 434 // xxx - what would happen if unify was changed so that unifying tuple types flattened both before unifying lists? then pass in TupleType(ttype) below. 435 arg = exprs.front(); 436 } else { 437 arg = new TupleExpr( exprs ); 438 } 439 assert( arg && arg->get_result() ); 440 if ( ! unify( ttype, arg->get_result(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 441 return false; 442 } 443 *out++ = arg; 444 } else if ( actualIt != actualEnd ) { 445 // both actualType and formalType are atomic (non-tuple) types - if they unify 446 // then accept actual as an argument, otherwise return false (fail to instantiate argument) 447 Expression * actual = actualIt->expr; 448 Type * actualType = actual->get_result(); 449 450 PRINT( 451 std::cerr << "formal type is "; 452 formalType->print( std::cerr ); 453 std::cerr << std::endl << "actual type is "; 454 actualType->print( std::cerr ); 455 std::cerr << std::endl; 456 ) 457 if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 458 // std::cerr << "unify failed" << std::endl; 459 return false; 460 } 461 // move the expression from the alternative to the output iterator 462 *out++ = actual; 463 actualIt->expr = nullptr; 464 cost += actualIt->cost; 465 ++actualIt; 466 } else { 467 // End of actuals - Handle default values 468 if ( SingleInit *si = dynamic_cast<SingleInit *>( defaultValue )) { 469 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( si->get_value() ) ) { 470 // so far, only constant expressions are accepted as default values 471 if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( castExpr->get_arg() ) ) { 472 if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) ) { 473 if ( unify( formalType, cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 474 *out++ = cnstexpr->clone(); 475 return true; 476 } // if 477 } // if 478 } // if 479 } 480 } // if 481 return false; 482 } // if 483 return true; 484 } 485 486 bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out ) { 487 simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv ); 488 // make sure we don't widen any existing bindings 489 for ( TypeEnvironment::iterator i = resultEnv.begin(); i != resultEnv.end(); ++i ) { 490 i->allowWidening = false; 491 } 492 resultEnv.extractOpenVars( openVars ); 493 494 // flatten actuals so that each actual has an atomic (non-tuple) type 495 AltList exploded; 496 Tuples::explode( actuals, indexer, back_inserter( exploded ) ); 497 498 AltList::iterator actualExpr = exploded.begin(); 499 AltList::iterator actualEnd = exploded.end(); 500 for ( DeclarationWithType * formal : formals ) { 501 // match flattened actuals with formal parameters - actuals will be grouped to match 502 // with formals as appropriate 503 Cost cost = Cost::zero; 504 std::list< Expression * > newExprs; 505 ObjectDecl * obj = strict_dynamic_cast< ObjectDecl * >( formal ); 506 if ( ! instantiateArgument( obj->get_type(), obj->get_init(), actualExpr, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( newExprs ) ) ) { 507 deleteAll( newExprs ); 508 return false; 509 } 510 // success - produce argument as a new alternative 511 assert( newExprs.size() == 1 ); 512 out.push_back( Alternative( newExprs.front(), resultEnv, cost ) ); 513 } 514 if ( actualExpr != actualEnd ) { 515 // there are still actuals remaining, but we've run out of formal parameters to match against 516 // this is okay only if the function is variadic 517 if ( ! isVarArgs ) { 518 return false; 519 } 520 out.splice( out.end(), exploded, actualExpr, actualEnd ); 521 } 522 return true; 407 523 } 408 524 … … 559 675 } 560 676 561 /// Gets a default value from an initializer, nullptr if not present 562 ConstantExpr* getDefaultValue( Initializer* init ) { 563 if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) { 564 if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) { 565 return dynamic_cast<ConstantExpr*>( ce->get_arg() ); 566 } 567 } 568 return nullptr; 569 } 570 571 /// State to iteratively build a match of parameter expressions to arguments 572 struct ArgPack { 573 AltList actuals; ///< Arguments included in this pack 574 TypeEnvironment env; ///< Environment for this pack 575 AssertionSet need; ///< Assertions outstanding for this pack 576 AssertionSet have; ///< Assertions found for this pack 577 OpenVarSet openVars; ///< Open variables for this pack 578 unsigned nextArg; ///< Index of next argument in arguments list 579 std::vector<Alternative> expls; ///< Exploded actuals left over from last match 580 unsigned nextExpl; ///< Index of next exploded alternative to use 581 std::vector<unsigned> tupleEls; /// Number of elements in current tuple element(s) 582 583 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 584 const OpenVarSet& openVars) 585 : actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0), 586 expls(), nextExpl(0), tupleEls() {} 587 588 /// Starts a new tuple expression 589 void beginTuple() { 590 if ( ! tupleEls.empty() ) ++tupleEls.back(); 591 tupleEls.push_back(0); 592 } 593 594 /// Ends a tuple expression, consolidating the appropriate actuals 595 void endTuple() { 596 // set up new Tuple alternative 597 std::list<Expression*> exprs; 598 Cost cost = Cost::zero; 599 600 // transfer elements into alternative 601 for (unsigned i = 0; i < tupleEls.back(); ++i) { 602 exprs.push_front( actuals.back().expr ); 603 actuals.back().expr = nullptr; 604 cost += actuals.back().cost; 605 actuals.pop_back(); 606 } 607 tupleEls.pop_back(); 608 609 // build new alternative 610 actuals.emplace_back( new TupleExpr( exprs ), this->env, cost ); 611 } 612 613 /// Clones and adds an actual, returns this 614 ArgPack& withArg( Expression* expr, Cost cost = Cost::zero ) { 615 actuals.emplace_back( expr->clone(), this->env, cost ); 616 if ( ! tupleEls.empty() ) ++tupleEls.back(); 617 return *this; 618 } 619 }; 620 621 /// Instantiates an argument to match a formal, returns false if no results left 622 bool instantiateArgument( Type* formalType, Initializer* initializer, 623 const std::vector< AlternativeFinder >& args, 624 std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults, 625 const SymTab::Indexer& indexer ) { 626 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) { 627 // formalType is a TupleType - group actuals into a TupleExpr 628 for ( ArgPack& result : results ) { result.beginTuple(); } 629 for ( Type* type : *tupleType ) { 630 // xxx - dropping initializer changes behaviour from previous, but seems correct 631 if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) ) 632 return false; 633 } 634 for ( ArgPack& result : results ) { result.endTuple(); } 635 return true; 636 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) { 637 // formalType is a ttype, consumes all remaining arguments 638 // xxx - mixing default arguments with variadic?? 639 std::vector<ArgPack> finalResults{}; /// list of completed tuples 640 // start tuples 641 for ( ArgPack& result : results ) { 642 result.beginTuple(); 643 644 // use rest of exploded tuple if present 645 while ( result.nextExpl < result.expls.size() ) { 646 const Alternative& actual = result.expls[result.nextExpl]; 647 result.env.addActual( actual.env, result.openVars ); 648 result.withArg( actual.expr ); 649 ++result.nextExpl; 650 } 651 } 652 // iterate until all results completed 653 while ( ! results.empty() ) { 654 // add another argument to results 655 for ( ArgPack& result : results ) { 656 // finish result when out of arguments 657 if ( result.nextArg >= args.size() ) { 658 Type* argType = result.actuals.back().expr->get_result(); 659 if ( result.tupleEls.back() == 1 && Tuples::isTtype( argType ) ) { 660 // the case where a ttype value is passed directly is special, e.g. for 661 // argument forwarding purposes 662 // xxx - what if passing multiple arguments, last of which is ttype? 663 // xxx - what would happen if unify was changed so that unifying tuple 664 // types flattened both before unifying lists? then pass in TupleType 665 // (ttype) below. 666 result.tupleEls.pop_back(); 667 } else { 668 // collapse leftover arguments into tuple 669 result.endTuple(); 670 argType = result.actuals.back().expr->get_result(); 671 } 672 // check unification for ttype before adding to final 673 if ( unify( ttype, argType, result.env, result.need, result.have, 674 result.openVars, indexer ) ) { 675 finalResults.push_back( std::move(result) ); 676 } 677 continue; 678 } 679 680 // add each possible next argument 681 for ( const Alternative& actual : args[result.nextArg] ) { 682 ArgPack aResult = result; // copy to clone everything 683 // add details of actual to result 684 aResult.env.addActual( actual.env, aResult.openVars ); 685 Cost cost = actual.cost; 686 687 // explode argument 688 std::vector<Alternative> exploded; 689 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 690 691 // add exploded argument to tuple 692 for ( Alternative& aActual : exploded ) { 693 aResult.withArg( aActual.expr, cost ); 694 cost = Cost::zero; 695 } 696 ++aResult.nextArg; 697 nextResults.push_back( std::move(aResult) ); 698 } 699 } 700 701 // reset for next round 702 results.swap( nextResults ); 703 nextResults.clear(); 704 } 705 results.swap( finalResults ); 706 return ! results.empty(); 707 } 708 709 // iterate each current subresult 710 for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) { 711 ArgPack& result = results[iResult]; 712 713 if ( result.nextExpl < result.expls.size() ) { 714 // use remainder of exploded tuple if present 715 const Alternative& actual = result.expls[result.nextExpl]; 716 result.env.addActual( actual.env, result.openVars ); 717 Type* actualType = actual.expr->get_result(); 718 719 PRINT( 720 std::cerr << "formal type is "; 721 formalType->print( std::cerr ); 722 std::cerr << std::endl << "actual type is "; 723 actualType->print( std::cerr ); 724 std::cerr << std::endl; 725 ) 726 727 if ( unify( formalType, actualType, result.env, result.need, result.have, 728 result.openVars, indexer ) ) { 729 ++result.nextExpl; 730 nextResults.push_back( std::move(result.withArg( actual.expr )) ); 731 } 732 733 continue; 734 } else if ( result.nextArg >= args.size() ) { 735 // use default initializers if out of arguments 736 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) { 737 if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) { 738 if ( unify( formalType, cnst->get_type(), result.env, result.need, 739 result.have, result.openVars, indexer ) ) { 740 nextResults.push_back( std::move(result.withArg( cnstExpr )) ); 741 } 742 } 743 } 744 continue; 745 } 746 747 // Check each possible next argument 748 for ( const Alternative& actual : args[result.nextArg] ) { 749 ArgPack aResult = result; // copy to clone everything 750 // add details of actual to result 751 aResult.env.addActual( actual.env, aResult.openVars ); 752 753 // explode argument 754 std::vector<Alternative> exploded; 755 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 756 if ( exploded.empty() ) { 757 // skip empty tuple arguments 758 ++aResult.nextArg; 759 results.push_back( std::move(aResult) ); 760 continue; 761 } 762 763 // consider only first exploded actual 764 const Alternative& aActual = exploded.front(); 765 Type* actualType = aActual.expr->get_result()->clone(); 766 767 PRINT( 768 std::cerr << "formal type is "; 769 formalType->print( std::cerr ); 770 std::cerr << std::endl << "actual type is "; 771 actualType->print( std::cerr ); 772 std::cerr << std::endl; 773 ) 774 775 // attempt to unify types 776 if ( unify( formalType, actualType, aResult.env, aResult.need, aResult.have, aResult.openVars, indexer ) ) { 777 // add argument 778 aResult.withArg( aActual.expr, actual.cost ); 779 ++aResult.nextArg; 780 if ( exploded.size() > 1 ) { 781 // other parts of tuple left over 782 aResult.expls = std::move( exploded ); 783 aResult.nextExpl = 1; 784 } 785 nextResults.push_back( std::move(aResult) ); 786 } 787 } 788 } 789 790 // reset for next parameter 791 results.swap( nextResults ); 792 nextResults.clear(); 793 794 return ! results.empty(); 795 } 796 797 template<typename OutputIterator> 798 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 799 FunctionType *funcType, const std::vector< AlternativeFinder > &args, 800 OutputIterator out ) { 801 OpenVarSet funcOpenVars; 802 AssertionSet funcNeed, funcHave; 803 TypeEnvironment funcEnv( func.env ); 804 makeUnifiableVars( funcType, funcOpenVars, funcNeed ); 805 // add all type variables as open variables now so that those not used in the parameter 806 // list are still considered open. 807 funcEnv.add( funcType->get_forall() ); 808 677 template< typename OutputIterator > 678 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out ) { 679 OpenVarSet openVars; 680 AssertionSet resultNeed, resultHave; 681 TypeEnvironment resultEnv( func.env ); 682 makeUnifiableVars( funcType, openVars, resultNeed ); 683 resultEnv.add( funcType->get_forall() ); // add all type variables as open variables now so that those not used in the parameter list are still considered open 684 AltList instantiatedActuals; // filled by instantiate function 809 685 if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) { 810 686 // attempt to narrow based on expected target type 811 687 Type * returnType = funcType->get_returnVals().front()->get_type(); 812 if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 813 indexer ) ) { 814 // unification failed, don't pursue this function alternative 688 if ( ! unify( returnType, targetType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 689 // unification failed, don't pursue this alternative 815 690 return; 816 691 } 817 692 } 818 693 819 // iteratively build matches, one parameter at a time 820 std::vector<ArgPack> results{ ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } }; 821 std::vector<ArgPack> nextResults{}; 822 for ( DeclarationWithType* formal : funcType->get_parameters() ) { 823 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 824 if ( ! instantiateArgument( 825 obj->get_type(), obj->get_init(), args, results, nextResults, indexer ) ) 826 return; 827 } 828 829 // filter out results that don't use all the arguments, and aren't variadic 830 std::vector<ArgPack> finalResults{}; 831 if ( funcType->get_isVarArgs() ) { 832 for ( ArgPack& result : results ) { 833 // use rest of exploded tuple if present 834 while ( result.nextExpl < result.expls.size() ) { 835 const Alternative& actual = result.expls[result.nextExpl]; 836 result.env.addActual( actual.env, result.openVars ); 837 result.withArg( actual.expr ); 838 ++result.nextExpl; 839 } 840 } 841 842 while ( ! results.empty() ) { 843 // build combinations for all remaining arguments 844 for ( ArgPack& result : results ) { 845 // keep if used all arguments 846 if ( result.nextArg >= args.size() ) { 847 finalResults.push_back( std::move(result) ); 848 continue; 849 } 850 851 // add each possible next argument 852 for ( const Alternative& actual : args[result.nextArg] ) { 853 ArgPack aResult = result; // copy to clone everything 854 // add details of actual to result 855 aResult.env.addActual( actual.env, aResult.openVars ); 856 Cost cost = actual.cost; 857 858 // explode argument 859 std::vector<Alternative> exploded; 860 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 861 862 // add exploded argument to arg list 863 for ( Alternative& aActual : exploded ) { 864 aResult.withArg( aActual.expr, cost ); 865 cost = Cost::zero; 866 } 867 ++aResult.nextArg; 868 nextResults.push_back( std::move(aResult) ); 869 } 870 } 871 872 // reset for next round 873 results.swap( nextResults ); 874 nextResults.clear(); 875 } 876 } else { 877 // filter out results that don't use all the arguments 878 for ( ArgPack& result : results ) { 879 if ( result.nextExpl >= result.expls.size() && result.nextArg >= args.size() ) { 880 finalResults.push_back( std::move(result) ); 881 } 882 } 883 } 884 885 // validate matching combos, add to final result list 886 for ( ArgPack& result : finalResults ) { 694 if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) { 887 695 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 888 Alternative newAlt( appExpr, result .env, sumCost( result.actuals ) );889 makeExprList( result.actuals, appExpr->get_args() );696 Alternative newAlt( appExpr, resultEnv, sumCost( instantiatedActuals ) ); 697 makeExprList( instantiatedActuals, appExpr->get_args() ); 890 698 PRINT( 891 699 std::cerr << "instantiate function success: " << appExpr << std::endl; 892 700 std::cerr << "need assertions:" << std::endl; 893 printAssertionSet( result .need, std::cerr, 8 );701 printAssertionSet( resultNeed, std::cerr, 8 ); 894 702 ) 895 inferParameters( result .need, result.have, newAlt, result.openVars, out );703 inferParameters( resultNeed, resultHave, newAlt, openVars, out ); 896 704 } 897 705 } … … 903 711 if ( funcFinder.alternatives.empty() ) return; 904 712 905 std::vector< AlternativeFinder > argAlternatives; 906 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 907 back_inserter( argAlternatives ) ); 713 std::list< AlternativeFinder > argAlternatives; 714 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), back_inserter( argAlternatives ) ); 715 716 std::list< AltList > possibilities; 717 combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) ); 908 718 909 719 // take care of possible tuple assignments 910 720 // if not tuple assignment, assignment is taken care of as a normal function call 911 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );721 Tuples::handleTupleAssignment( *this, untypedExpr, possibilities ); 912 722 913 723 // find function operators … … 934 744 Alternative newFunc( *func ); 935 745 referenceToRvalueConversion( newFunc.expr ); 936 makeFunctionAlternatives( newFunc, function, argAlternatives, 937 std::back_inserter( candidates ) ); 746 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 747 // XXX 748 //Designators::check_alternative( function, *actualAlt ); 749 makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) ); 750 } 938 751 } 939 752 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) … … 943 756 Alternative newFunc( *func ); 944 757 referenceToRvalueConversion( newFunc.expr ); 945 makeFunctionAlternatives( newFunc, function, argAlternatives, 946 std::back_inserter( candidates ) ); 758 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 759 makeFunctionAlternatives( newFunc, function, *actualAlt, std::back_inserter( candidates ) ); 760 } // for 947 761 } // if 948 762 } // if 949 } 763 } 764 765 // try each function operator ?() with the current function alternative and each of the argument combinations 766 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 767 // check if the type is pointer to function 768 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) { 769 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 770 Alternative newFunc( *funcOp ); 771 referenceToRvalueConversion( newFunc.expr ); 772 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 773 AltList currentAlt; 774 currentAlt.push_back( *func ); 775 currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() ); 776 makeFunctionAlternatives( newFunc, function, currentAlt, std::back_inserter( candidates ) ); 777 } // for 778 } // if 779 } // if 780 } // for 950 781 } catch ( SemanticError &e ) { 951 782 errors.append( e ); 952 783 } 953 784 } // for 954 955 // try each function operator ?() with each function alternative956 if ( ! funcOpFinder.alternatives.empty() ) {957 // add function alternatives to front of argument list958 argAlternatives.insert( argAlternatives.begin(), std::move(funcFinder) );959 960 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin();961 funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {962 try {963 // check if type is a pointer to function964 if ( PointerType* pointer = dynamic_cast<PointerType*>(965 funcOp->expr->get_result()->stripReferences() ) ) {966 if ( FunctionType* function =967 dynamic_cast<FunctionType*>( pointer->get_base() ) ) {968 Alternative newFunc( *funcOp );969 referenceToRvalueConversion( newFunc.expr );970 makeFunctionAlternatives( newFunc, function, argAlternatives,971 std::back_inserter( candidates ) );972 }973 }974 } catch ( SemanticError &e ) {975 errors.append( e );976 }977 }978 }979 785 980 786 // Implement SFINAE; resolution errors are only errors if there aren't any non-erroneous resolutions -
src/ResolvExpr/AlternativeFinder.h
r490db327 rc95b115 34 34 public: 35 35 AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env ); 36 37 AlternativeFinder( const AlternativeFinder& o )38 : indexer(o.indexer), alternatives(o.alternatives), env(o.env),39 targetType(o.targetType) {}40 41 AlternativeFinder( AlternativeFinder&& o )42 : indexer(o.indexer), alternatives(std::move(o.alternatives)), env(o.env),43 targetType(o.targetType) {}44 45 AlternativeFinder& operator= ( const AlternativeFinder& o ) {46 if (&o == this) return *this;47 48 // horrific nasty hack to rebind references...49 alternatives.~AltList();50 new(this) AlternativeFinder(o);51 return *this;52 }53 54 AlternativeFinder& operator= ( AlternativeFinder&& o ) {55 if (&o == this) return *this;56 57 // horrific nasty hack to rebind references...58 alternatives.~AltList();59 new(this) AlternativeFinder(std::move(o));60 return *this;61 }62 63 36 void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true ); 64 37 /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types … … 126 99 /// Adds alternatives for offsetof expressions, given the base type and name of the member 127 100 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 128 template<typename OutputIterator> 129 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const std::vector< AlternativeFinder >& args, OutputIterator out ); 101 bool instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out ); 102 template< typename OutputIterator > 103 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out ); 130 104 template< typename OutputIterator > 131 105 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); -
src/ResolvExpr/TypeEnvironment.cc
r490db327 rc95b115 201 201 } 202 202 203 void TypeEnvironment::addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ) {204 for ( const EqvClass& c : actualEnv ) {205 EqvClass c2 = c;206 c2.allowWidening = false;207 for ( const std::string& var : c2.vars ) {208 openVars[ var ] = c2.data;209 }210 env.push_back( std::move(c2) );211 }212 }213 214 203 } // namespace ResolvExpr 215 204 -
src/ResolvExpr/TypeEnvironment.h
r490db327 rc95b115 86 86 TypeEnvironment *clone() const { return new TypeEnvironment( *this ); } 87 87 88 /// Iteratively adds the environment of a new actual (with allowWidening = false),89 /// and extracts open variables.90 void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );91 92 88 typedef std::list< EqvClass >::iterator iterator; 93 89 iterator begin() { return env.begin(); } -
src/SymTab/Mangler.cc
r490db327 rc95b115 32 32 namespace SymTab { 33 33 std::string Mangler::mangleType( Type * ty ) { 34 Mangler mangler( false, true , true);34 Mangler mangler( false, true ); 35 35 maybeAccept( ty, mangler ); 36 36 return mangler.get_mangleName(); 37 37 } 38 38 39 std::string Mangler::mangleConcrete( Type* ty ) { 40 Mangler mangler( false, false, false ); 41 maybeAccept( ty, mangler ); 42 return mangler.get_mangleName(); 43 } 44 45 Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) 46 : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ), mangleGenericParams( mangleGenericParams ) {} 39 Mangler::Mangler( bool mangleOverridable, bool typeMode ) 40 : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ) {} 47 41 48 42 Mangler::Mangler( const Mangler &rhs ) : mangleName() { … … 172 166 173 167 mangleName << ( refType->get_name().length() + prefix.length() ) << prefix << refType->get_name(); 174 175 if ( mangleGenericParams ) { 176 std::list< Expression* >& params = refType->get_parameters(); 177 if ( ! params.empty() ) { 178 mangleName << "_"; 179 for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) { 180 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 181 assertf(paramType, "Aggregate parameters should be type expressions: %s", toString(*param).c_str()); 182 maybeAccept( paramType->get_type(), *this ); 183 } 184 mangleName << "_"; 168 } 169 170 void Mangler::mangleGenericRef( ReferenceToType * refType, std::string prefix ) { 171 printQualifiers( refType ); 172 173 std::ostringstream oldName( mangleName.str() ); 174 mangleName.clear(); 175 176 mangleName << prefix << refType->get_name(); 177 178 std::list< Expression* >& params = refType->get_parameters(); 179 if ( ! params.empty() ) { 180 mangleName << "_"; 181 for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) { 182 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); 183 assertf(paramType, "Aggregate parameters should be type expressions: %s", toString(*param).c_str()); 184 maybeAccept( paramType->get_type(), *this ); 185 185 } 186 mangleName << "_"; 186 187 } 188 189 oldName << mangleName.str().length() << mangleName.str(); 190 mangleName.str( oldName.str() ); 187 191 } 188 192 189 193 void Mangler::visit( StructInstType * aggregateUseType ) { 190 mangleRef( aggregateUseType, "s" ); 194 if ( typeMode ) mangleGenericRef( aggregateUseType, "s" ); 195 else mangleRef( aggregateUseType, "s" ); 191 196 } 192 197 193 198 void Mangler::visit( UnionInstType * aggregateUseType ) { 194 mangleRef( aggregateUseType, "u" ); 199 if ( typeMode ) mangleGenericRef( aggregateUseType, "u" ); 200 else mangleRef( aggregateUseType, "u" ); 195 201 } 196 202 … … 279 285 varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() ); 280 286 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) { 281 Mangler sub_mangler( mangleOverridable, typeMode , mangleGenericParams);287 Mangler sub_mangler( mangleOverridable, typeMode ); 282 288 sub_mangler.nextVarNum = nextVarNum; 283 289 sub_mangler.isTopLevel = false; -
src/SymTab/Mangler.h
r490db327 rc95b115 30 30 /// Mangle syntax tree object; primary interface to clients 31 31 template< typename SynTreeClass > 32 static std::string mangle( SynTreeClass *decl, bool mangleOverridable = true, bool typeMode = false , bool mangleGenericParams = true);32 static std::string mangle( SynTreeClass *decl, bool mangleOverridable = true, bool typeMode = false ); 33 33 /// Mangle a type name; secondary interface 34 34 static std::string mangleType( Type* ty ); 35 /// Mangle ignoring generic type parameters36 static std::string mangleConcrete( Type* ty );37 38 35 39 36 virtual void visit( ObjectDecl *declaration ); … … 65 62 bool mangleOverridable; ///< Specially mangle overridable built-in methods 66 63 bool typeMode; ///< Produce a unique mangled name for a type 67 bool mangleGenericParams; ///< Include generic parameters in name mangling if true68 64 69 Mangler( bool mangleOverridable, bool typeMode , bool mangleGenericParams);65 Mangler( bool mangleOverridable, bool typeMode ); 70 66 Mangler( const Mangler & ); 71 67 72 68 void mangleDecl( DeclarationWithType *declaration ); 73 69 void mangleRef( ReferenceToType *refType, std::string prefix ); 70 void mangleGenericRef( ReferenceToType *refType, std::string prefix ); 74 71 75 72 void printQualifiers( Type *type ); … … 77 74 78 75 template< typename SynTreeClass > 79 std::string Mangler::mangle( SynTreeClass *decl, bool mangleOverridable, bool typeMode , bool mangleGenericParams) {80 Mangler mangler( mangleOverridable, typeMode , mangleGenericParams);76 std::string Mangler::mangle( SynTreeClass *decl, bool mangleOverridable, bool typeMode ) { 77 Mangler mangler( mangleOverridable, typeMode ); 81 78 maybeAccept( decl, mangler ); 82 79 return mangler.get_mangleName(); -
src/Tuples/TupleAssignment.cc
r490db327 rc95b115 20 20 #include <memory> // for unique_ptr, allocator_trai... 21 21 #include <string> // for string 22 #include <vector>23 22 24 23 #include "CodeGen/OperatorTable.h" … … 34 33 #include "ResolvExpr/Resolver.h" // for resolveCtorInit 35 34 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 36 #include "ResolvExpr/typeops.h" // for combos37 35 #include "SynTree/Declaration.h" // for ObjectDecl 38 36 #include "SynTree/Expression.h" // for Expression, CastExpr, Name... … … 54 52 // dispatcher for Tuple (multiple and mass) assignment operations 55 53 TupleAssignSpotter( ResolvExpr::AlternativeFinder & ); 56 void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args );54 void spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ); 57 55 58 56 private: … … 61 59 struct Matcher { 62 60 public: 63 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const 64 ResolvExpr::AltList& rhs ); 61 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 65 62 virtual ~Matcher() {} 66 63 virtual void match( std::list< Expression * > &out ) = 0; … … 75 72 struct MassAssignMatcher : public Matcher { 76 73 public: 77 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 78 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 74 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 79 75 virtual void match( std::list< Expression * > &out ); 80 76 }; … … 82 78 struct MultipleAssignMatcher : public Matcher { 83 79 public: 84 MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 85 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 80 MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts ); 86 81 virtual void match( std::list< Expression * > &out ); 87 82 }; … … 119 114 } 120 115 121 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, 122 std::vector<ResolvExpr::AlternativeFinder> &args ) { 116 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 123 117 TupleAssignSpotter spotter( currentFinder ); 124 spotter.spot( expr, args );118 spotter.spot( expr, possibilities ); 125 119 } 126 120 … … 128 122 : currentFinder(f) {} 129 123 130 void TupleAssignSpotter::spot( UntypedExpr * expr, 131 std::vector<ResolvExpr::AlternativeFinder> &args ) { 124 void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 132 125 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { 133 126 if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) { 134 fname = op->get_name(); 135 136 // AlternativeFinder will naturally handle this case case, if it's legal 137 if ( args.size() == 0 ) return; 138 139 // if an assignment only takes 1 argument, that's odd, but maybe someone wrote 140 // the function, in which case AlternativeFinder will handle it normally 141 if ( args.size() == 1 && CodeGen::isAssignment( fname ) ) return; 142 143 // look over all possible left-hand-sides 144 for ( ResolvExpr::Alternative& lhsAlt : args[0] ) { 145 // skip non-tuple LHS 146 if ( ! refToTuple(lhsAlt.expr) ) continue; 147 148 // explode is aware of casts - ensure every LHS expression is sent into explode 149 // with a reference cast 150 // xxx - this seems to change the alternatives before the normal 151 // AlternativeFinder flow; maybe this is desired? 152 if ( ! dynamic_cast<CastExpr*>( lhsAlt.expr ) ) { 153 lhsAlt.expr = new CastExpr( lhsAlt.expr, 154 new ReferenceType( Type::Qualifiers(), 155 lhsAlt.expr->get_result()->clone() ) ); 127 fname = op->get_name(); 128 PRINT( std::cerr << "TupleAssignment: " << fname << std::endl; ) 129 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 130 if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal 131 if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) { 132 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it 133 continue; 156 134 } 157 135 158 // explode the LHS so that each field of a tuple-valued-expr is assigned 159 ResolvExpr::AltList lhs; 160 explode( lhsAlt, currentFinder.get_indexer(), back_inserter(lhs), true ); 161 for ( ResolvExpr::Alternative& alt : lhs ) { 162 // each LHS value must be a reference - some come in with a cast expression, 163 // if not just cast to reference here 164 if ( ! dynamic_cast<ReferenceType*>( alt.expr->get_result() ) ) { 165 alt.expr = new CastExpr( alt.expr, 166 new ReferenceType( Type::Qualifiers(), 167 alt.expr->get_result()->clone() ) ); 136 assert( ! ali->empty() ); 137 // grab args 2-N and group into a TupleExpr 138 const ResolvExpr::Alternative & alt1 = ali->front(); 139 auto begin = std::next(ali->begin(), 1), end = ali->end(); 140 PRINT( std::cerr << "alt1 is " << alt1.expr << std::endl; ) 141 if ( refToTuple(alt1.expr) ) { 142 PRINT( std::cerr << "and is reference to tuple" << std::endl; ) 143 if ( isMultAssign( begin, end ) ) { 144 PRINT( std::cerr << "possible multiple assignment" << std::endl; ) 145 matcher.reset( new MultipleAssignMatcher( *this, *ali ) ); 146 } else { 147 // mass assignment 148 PRINT( std::cerr << "possible mass assignment" << std::endl; ) 149 matcher.reset( new MassAssignMatcher( *this, *ali ) ); 168 150 } 169 }170 171 if ( args.size() == 1 ) {172 // mass default-initialization/destruction173 ResolvExpr::AltList rhs{};174 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );175 151 match(); 176 } else if ( args.size() > 2 ) {177 // expand all possible RHS possibilities178 // TODO build iterative version of this instead of using combos179 std::vector< ResolvExpr::AltList > rhsAlts;180 combos( std::next(args.begin(), 1), args.end(),181 std::back_inserter( rhsAlts ) );182 for ( const ResolvExpr::AltList& rhsAlt : rhsAlts ) {183 // multiple assignment184 ResolvExpr::AltList rhs;185 explode( rhsAlt, currentFinder.get_indexer(),186 std::back_inserter(rhs), true );187 matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );188 match();189 }190 } else {191 for ( const ResolvExpr::Alternative& rhsAlt : args[1] ) {192 ResolvExpr::AltList rhs;193 if ( isTuple(rhsAlt.expr) ) {194 // multiple assignment195 explode( rhsAlt, currentFinder.get_indexer(),196 std::back_inserter(rhs), true );197 matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );198 } else {199 // mass assignment200 rhs.push_back( rhsAlt );201 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );202 }203 match();204 }205 152 } 206 153 } … … 222 169 ResolvExpr::AltList current; 223 170 // now resolve new assignments 224 for ( std::list< Expression * >::iterator i = new_assigns.begin(); 225 i != new_assigns.end(); ++i ) { 171 for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) { 226 172 PRINT( 227 173 std::cerr << "== resolving tuple assign ==" << std::endl; … … 229 175 ) 230 176 231 ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(), 232 currentFinder.get_environ() }; 177 ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() ); 233 178 try { 234 179 finder.findWithAdjustment(*i); … … 251 196 // combine assignment environments into combined expression environment 252 197 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv ); 253 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative( 254 new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 255 ResolvExpr::sumCost( current ) + matcher->baseCost ) ); 256 } 257 258 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, 259 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs ) 260 : lhs(lhs), rhs(rhs), spotter(spotter), 261 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) { 262 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv ); 263 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv ); 198 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, ResolvExpr::sumCost( current ) + matcher->baseCost ) ); 199 } 200 201 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter), baseCost( ResolvExpr::sumCost( alts ) ) { 202 assert( ! alts.empty() ); 203 // combine argument environments into combined expression environment 204 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 205 206 ResolvExpr::Alternative lhsAlt = alts.front(); 207 // explode is aware of casts - ensure every LHS expression is sent into explode with a reference cast 208 if ( ! dynamic_cast< CastExpr * >( lhsAlt.expr ) ) { 209 lhsAlt.expr = new CastExpr( lhsAlt.expr, new ReferenceType( Type::Qualifiers(), lhsAlt.expr->get_result()->clone() ) ); 210 } 211 212 // explode the lhs so that each field of the tuple-valued-expr is assigned. 213 explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs), true ); 214 215 for ( ResolvExpr::Alternative & alt : lhs ) { 216 // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here. 217 if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) { 218 alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) ); 219 } 220 } 221 } 222 223 TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) { 224 assert( alts.size() == 1 || alts.size() == 2 ); 225 if ( alts.size() == 2 ) { 226 rhs.push_back( alts.back() ); 227 } 228 } 229 230 TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) { 231 // explode the rhs so that each field of the tuple-valued-expr is assigned. 232 explode( std::next(alts.begin(), 1), alts.end(), spotter.currentFinder.get_indexer(), back_inserter(rhs), true ); 264 233 } 265 234 -
src/Tuples/Tuples.h
r490db327 rc95b115 17 17 18 18 #include <string> 19 #include <vector>20 19 21 20 #include "SynTree/Expression.h" … … 27 26 namespace Tuples { 28 27 // TupleAssignment.cc 29 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, 30 std::vector< ResolvExpr::AlternativeFinder >& args ); 31 28 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, const std::list<ResolvExpr::AltList> & possibilities ); 29 32 30 // TupleExpansion.cc 33 31 /// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate -
src/benchmark/Makefile.am
r490db327 rc95b115 133 133 ## ========================================================================================================= 134 134 creation$(EXEEXT) :\ 135 creation-pthread.run \ 136 creation-cfa_coroutine.run \ 137 creation-cfa_coroutine_eager.run \ 138 creation-cfa_thread.run \ 139 creation-upp_coroutine.run \ 135 creation-pthread.run \ 136 creation-cfa_coroutine.run \ 137 creation-cfa_thread.run \ 138 creation-upp_coroutine.run \ 140 139 creation-upp_thread.run 141 140 142 141 creation-cfa_coroutine$(EXEEXT): 143 142 ${CC} creation/cfa_cor.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} 144 145 creation-cfa_coroutine_eager$(EXEEXT):146 ${CC} creation/cfa_cor.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} -DEAGER147 143 148 144 creation-cfa_thread$(EXEEXT): … … 160 156 ## ========================================================================================================= 161 157 162 compile$(EXEEXT) :\163 compile-array$(EXEEXT) \164 compile-attributes$(EXEEXT) \165 compile-empty$(EXEEXT) \166 compile-expression$(EXEEXT) \167 compile-io$(EXEEXT) \168 compile-monitor$(EXEEXT) \169 compile-operators$(EXEEXT) \170 compile-thread$(EXEEXT) \171 compile-typeof$(EXEEXT)172 173 174 compile-array$(EXEEXT):175 @printf '%20s\t' $(subst compile-,,$@)176 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/array.c177 178 compile-attributes$(EXEEXT):179 @printf '%20s\t' $(subst compile-,,$@)180 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/attributes.c181 182 compile-empty$(EXEEXT):183 @printf '%20s\t' $(subst compile-,,$@)184 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w compile/empty.c185 186 compile-expression$(EXEEXT):187 @printf '%20s\t' $(subst compile-,,$@)188 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/expression.c189 190 compile-io$(EXEEXT):191 @printf '%20s\t' $(subst compile-,,$@)192 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/io.c193 194 compile-monitor$(EXEEXT):195 @printf '%20s\t' $(subst compile-,,$@)196 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/monitor.c197 198 compile-operators$(EXEEXT):199 @printf '%20s\t' $(subst compile-,,$@)200 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/operators.c201 202 compile-thread$(EXEEXT):203 @printf '%20s\t' $(subst compile-,,$@)204 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/thread.c205 206 compile-typeof$(EXEEXT):207 @printf '%20s\t' $(subst compile-,,$@)208 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/typeof.c209 210 211 ## =========================================================================================================212 213 158 %.run : %$(EXEEXT) ${REPEAT} 214 159 @rm -f .result.log -
src/benchmark/Makefile.in
r490db327 rc95b115 124 124 esac 125 125 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) 126 am__DIST_COMMON = $(srcdir)/Makefile.in compile126 am__DIST_COMMON = $(srcdir)/Makefile.in 127 127 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 128 128 ACLOCAL = @ACLOCAL@ … … 544 544 545 545 creation$(EXEEXT) :\ 546 creation-pthread.run \ 547 creation-cfa_coroutine.run \ 548 creation-cfa_coroutine_eager.run \ 549 creation-cfa_thread.run \ 550 creation-upp_coroutine.run \ 546 creation-pthread.run \ 547 creation-cfa_coroutine.run \ 548 creation-cfa_thread.run \ 549 creation-upp_coroutine.run \ 551 550 creation-upp_thread.run 552 551 … … 554 553 ${CC} creation/cfa_cor.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} 555 554 556 creation-cfa_coroutine_eager$(EXEEXT):557 ${CC} creation/cfa_cor.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} -DEAGER558 559 555 creation-cfa_thread$(EXEEXT): 560 556 ${CC} creation/cfa_thrd.c -DBENCH_N=10000000 -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} … … 568 564 creation-pthread$(EXEEXT): 569 565 @BACKEND_CC@ creation/pthreads.c -DBENCH_N=250000 -I. -lrt -pthread ${AM_CFLAGS} ${CFLAGS} ${ccflags} 570 571 compile$(EXEEXT) :\572 compile-array$(EXEEXT) \573 compile-attributes$(EXEEXT) \574 compile-empty$(EXEEXT) \575 compile-expression$(EXEEXT) \576 compile-io$(EXEEXT) \577 compile-monitor$(EXEEXT) \578 compile-operators$(EXEEXT) \579 compile-thread$(EXEEXT) \580 compile-typeof$(EXEEXT) \581 compile-vector_test$(EXEEXT)582 583 compile-array$(EXEEXT):584 @printf '%20s\t' $(subst compile-,,$@)585 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/array.c586 587 compile-attributes$(EXEEXT):588 @printf '%20s\t' $(subst compile-,,$@)589 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/attributes.c590 591 compile-empty$(EXEEXT):592 @printf '%20s\t' $(subst compile-,,$@)593 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w compile/empty.c594 595 compile-expression$(EXEEXT):596 @printf '%20s\t' $(subst compile-,,$@)597 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/expression.c598 599 compile-io$(EXEEXT):600 @printf '%20s\t' $(subst compile-,,$@)601 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/io.c602 603 compile-monitor$(EXEEXT):604 @printf '%20s\t' $(subst compile-,,$@)605 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/monitor.c606 607 compile-operators$(EXEEXT):608 @printf '%20s\t' $(subst compile-,,$@)609 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/operators.c610 611 compile-thread$(EXEEXT):612 @printf '%20s\t' $(subst compile-,,$@)613 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/thread.c614 615 compile-typeof$(EXEEXT):616 @printf '%20s\t' $(subst compile-,,$@)617 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/typeof.c618 619 compile-vector_test$(EXEEXT):620 @printf '%20s\t' $(subst compile-,,$@)621 @/usr/bin/time -f "%E" ${CC} -quiet -fsyntax-only -w ../tests/vector_test.c622 566 623 567 %.run : %$(EXEEXT) ${REPEAT} -
src/benchmark/creation/cfa_cor.c
r490db327 rc95b115 5 5 6 6 coroutine MyCoroutine {}; 7 void ?{} (MyCoroutine & this) { 8 #ifdef EAGER 9 prime(this); 10 #endif 11 } 7 void ?{} (MyCoroutine & this) { prime(this); } 12 8 void main(MyCoroutine & this) {} 13 9 -
src/libcfa/Makefile.am
r490db327 rc95b115 95 95 96 96 cfa_includedir = $(CFA_INCDIR) 97 nobase_cfa_include_HEADERS = \ 98 ${headers} \ 99 ${stdhdr} \ 100 math \ 101 gmp \ 102 bits/defs.h \ 103 bits/locks.h \ 104 concurrency/invoke.h \ 105 libhdr.h \ 106 libhdr/libalign.h \ 107 libhdr/libdebug.h \ 108 libhdr/libtools.h 97 nobase_cfa_include_HEADERS = ${headers} ${stdhdr} math gmp concurrency/invoke.h 109 98 110 99 CLEANFILES = libcfa-prelude.c -
src/libcfa/Makefile.in
r490db327 rc95b115 264 264 containers/result containers/vector concurrency/coroutine \ 265 265 concurrency/thread concurrency/kernel concurrency/monitor \ 266 ${shell echo stdhdr/*} math gmp bits/defs.h bits/locks.h \ 267 concurrency/invoke.h libhdr.h libhdr/libalign.h \ 268 libhdr/libdebug.h libhdr/libtools.h 266 ${shell echo stdhdr/*} math gmp concurrency/invoke.h 269 267 HEADERS = $(nobase_cfa_include_HEADERS) 270 268 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) … … 432 430 stdhdr = ${shell echo stdhdr/*} 433 431 cfa_includedir = $(CFA_INCDIR) 434 nobase_cfa_include_HEADERS = \ 435 ${headers} \ 436 ${stdhdr} \ 437 math \ 438 gmp \ 439 bits/defs.h \ 440 bits/locks.h \ 441 concurrency/invoke.h \ 442 libhdr.h \ 443 libhdr/libalign.h \ 444 libhdr/libdebug.h \ 445 libhdr/libtools.h 446 432 nobase_cfa_include_HEADERS = ${headers} ${stdhdr} math gmp concurrency/invoke.h 447 433 CLEANFILES = libcfa-prelude.c 448 434 all: all-am -
src/libcfa/concurrency/alarm.c
r490db327 rc95b115 186 186 187 187 disable_interrupts(); 188 lock( event_kernel->lock DEBUG_CTX2 );188 lock( &event_kernel->lock DEBUG_CTX2 ); 189 189 { 190 190 verify( validate( alarms ) ); … … 196 196 } 197 197 } 198 unlock( event_kernel->lock );198 unlock( &event_kernel->lock ); 199 199 this->set = true; 200 200 enable_interrupts( DEBUG_CTX ); … … 203 203 void unregister_self( alarm_node_t * this ) { 204 204 disable_interrupts(); 205 lock( event_kernel->lock DEBUG_CTX2 );205 lock( &event_kernel->lock DEBUG_CTX2 ); 206 206 { 207 207 verify( validate( &event_kernel->alarms ) ); 208 208 remove( &event_kernel->alarms, this ); 209 209 } 210 unlock( event_kernel->lock );210 unlock( &event_kernel->lock ); 211 211 enable_interrupts( DEBUG_CTX ); 212 212 this->set = false; -
src/libcfa/concurrency/invoke.h
r490db327 rc95b115 14 14 // 15 15 16 #include "bits/defs.h"17 #include "bits/locks.h"16 #include <stdbool.h> 17 #include <stdint.h> 18 18 19 19 #ifdef __CFORALL__ … … 25 25 #define _INVOKE_H_ 26 26 27 #define unlikely(x) __builtin_expect(!!(x), 0) 28 #define thread_local _Thread_local 29 27 30 typedef void (*fptr_t)(); 28 31 typedef int_fast16_t __lock_size_t; 32 33 struct spinlock { 34 volatile int lock; 35 #ifdef __CFA_DEBUG__ 36 const char * prev_name; 37 void* prev_thrd; 38 #endif 39 }; 29 40 30 41 struct __thread_queue_t { … … 47 58 void push( struct __condition_stack_t &, struct __condition_criterion_t * ); 48 59 struct __condition_criterion_t * pop( struct __condition_stack_t & ); 60 61 void ?{}(spinlock & this); 62 void ^?{}(spinlock & this); 49 63 } 50 64 #endif … … 108 122 struct monitor_desc { 109 123 // spinlock to protect internal data 110 struct __spinlock_tlock;124 struct spinlock lock; 111 125 112 126 // current owner of the monitor -
src/libcfa/concurrency/kernel
r490db327 rc95b115 26 26 //----------------------------------------------------------------------------- 27 27 // Locks 28 // //Lock the spinlock, spin if already acquired29 //void lock ( spinlock * DEBUG_CTX_PARAM2 );28 // Lock the spinlock, spin if already acquired 29 void lock ( spinlock * DEBUG_CTX_PARAM2 ); 30 30 31 // //Lock the spinlock, yield repeatedly if already acquired32 //void lock_yield( spinlock * DEBUG_CTX_PARAM2 );31 // Lock the spinlock, yield repeatedly if already acquired 32 void lock_yield( spinlock * DEBUG_CTX_PARAM2 ); 33 33 34 // //Lock the spinlock, return false if already acquired35 //bool try_lock ( spinlock * DEBUG_CTX_PARAM2 );34 // Lock the spinlock, return false if already acquired 35 bool try_lock ( spinlock * DEBUG_CTX_PARAM2 ); 36 36 37 // //Unlock the spinlock38 //void unlock ( spinlock * );37 // Unlock the spinlock 38 void unlock ( spinlock * ); 39 39 40 40 struct semaphore { 41 __spinlock_tlock;41 spinlock lock; 42 42 int count; 43 43 __thread_queue_t waiting; … … 54 54 struct cluster { 55 55 // Ready queue locks 56 __spinlock_tready_queue_lock;56 spinlock ready_queue_lock; 57 57 58 58 // Ready queue for threads … … 74 74 FinishOpCode action_code; 75 75 thread_desc * thrd; 76 __spinlock_t* lock;77 __spinlock_t** locks;76 spinlock * lock; 77 spinlock ** locks; 78 78 unsigned short lock_count; 79 79 thread_desc ** thrds; -
src/libcfa/concurrency/kernel.c
r490db327 rc95b115 242 242 void finishRunning(processor * this) { 243 243 if( this->finish.action_code == Release ) { 244 unlock( *this->finish.lock );244 unlock( this->finish.lock ); 245 245 } 246 246 else if( this->finish.action_code == Schedule ) { … … 248 248 } 249 249 else if( this->finish.action_code == Release_Schedule ) { 250 unlock( *this->finish.lock );250 unlock( this->finish.lock ); 251 251 ScheduleThread( this->finish.thrd ); 252 252 } 253 253 else if( this->finish.action_code == Release_Multi ) { 254 254 for(int i = 0; i < this->finish.lock_count; i++) { 255 unlock( *this->finish.locks[i] );255 unlock( this->finish.locks[i] ); 256 256 } 257 257 } 258 258 else if( this->finish.action_code == Release_Multi_Schedule ) { 259 259 for(int i = 0; i < this->finish.lock_count; i++) { 260 unlock( *this->finish.locks[i] );260 unlock( this->finish.locks[i] ); 261 261 } 262 262 for(int i = 0; i < this->finish.thrd_count; i++) { … … 334 334 verifyf( thrd->next == NULL, "Expected null got %p", thrd->next ); 335 335 336 lock( this_processor->cltr->ready_queue_lock DEBUG_CTX2 );336 lock( &this_processor->cltr->ready_queue_lock DEBUG_CTX2 ); 337 337 append( this_processor->cltr->ready_queue, thrd ); 338 unlock( this_processor->cltr->ready_queue_lock );338 unlock( &this_processor->cltr->ready_queue_lock ); 339 339 340 340 verify( disable_preempt_count > 0 ); … … 343 343 thread_desc * nextThread(cluster * this) { 344 344 verify( disable_preempt_count > 0 ); 345 lock( this->ready_queue_lock DEBUG_CTX2 );345 lock( &this->ready_queue_lock DEBUG_CTX2 ); 346 346 thread_desc * head = pop_head( this->ready_queue ); 347 unlock( this->ready_queue_lock );347 unlock( &this->ready_queue_lock ); 348 348 verify( disable_preempt_count > 0 ); 349 349 return head; … … 358 358 } 359 359 360 void BlockInternal( __spinlock_t* lock ) {360 void BlockInternal( spinlock * lock ) { 361 361 disable_interrupts(); 362 362 this_processor->finish.action_code = Release; … … 384 384 } 385 385 386 void BlockInternal( __spinlock_t* lock, thread_desc * thrd ) {386 void BlockInternal( spinlock * lock, thread_desc * thrd ) { 387 387 assert(thrd); 388 388 disable_interrupts(); … … 398 398 } 399 399 400 void BlockInternal( __spinlock_t* locks [], unsigned short count) {400 void BlockInternal(spinlock * locks [], unsigned short count) { 401 401 disable_interrupts(); 402 402 this_processor->finish.action_code = Release_Multi; … … 411 411 } 412 412 413 void BlockInternal( __spinlock_t* locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {413 void BlockInternal(spinlock * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) { 414 414 disable_interrupts(); 415 415 this_processor->finish.action_code = Release_Multi_Schedule; … … 426 426 } 427 427 428 void LeaveThread( __spinlock_t* lock, thread_desc * thrd) {428 void LeaveThread(spinlock * lock, thread_desc * thrd) { 429 429 verify( disable_preempt_count > 0 ); 430 430 this_processor->finish.action_code = thrd ? Release_Schedule : Release; … … 516 516 } 517 517 518 static __spinlock_tkernel_abort_lock;519 static __spinlock_tkernel_debug_lock;518 static spinlock kernel_abort_lock; 519 static spinlock kernel_debug_lock; 520 520 static bool kernel_abort_called = false; 521 521 … … 523 523 // abort cannot be recursively entered by the same or different processors because all signal handlers return when 524 524 // the globalAbort flag is true. 525 lock( kernel_abort_lock DEBUG_CTX2 );525 lock( &kernel_abort_lock DEBUG_CTX2 ); 526 526 527 527 // first task to abort ? 528 528 if ( !kernel_abort_called ) { // not first task to abort ? 529 529 kernel_abort_called = true; 530 unlock( kernel_abort_lock );530 unlock( &kernel_abort_lock ); 531 531 } 532 532 else { 533 unlock( kernel_abort_lock );533 unlock( &kernel_abort_lock ); 534 534 535 535 sigset_t mask; … … 561 561 extern "C" { 562 562 void __lib_debug_acquire() { 563 lock( kernel_debug_lock DEBUG_CTX2 );563 lock( &kernel_debug_lock DEBUG_CTX2 ); 564 564 } 565 565 566 566 void __lib_debug_release() { 567 unlock( kernel_debug_lock );567 unlock( &kernel_debug_lock ); 568 568 } 569 569 } … … 574 574 //----------------------------------------------------------------------------- 575 575 // Locks 576 void ?{}( spinlock & this ) { 577 this.lock = 0; 578 } 579 void ^?{}( spinlock & this ) { 580 581 } 582 583 bool try_lock( spinlock * this DEBUG_CTX_PARAM2 ) { 584 return this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0; 585 } 586 587 void lock( spinlock * this DEBUG_CTX_PARAM2 ) { 588 for ( unsigned int i = 1;; i += 1 ) { 589 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; } 590 } 591 LIB_DEBUG_DO( 592 this->prev_name = caller; 593 this->prev_thrd = this_thread; 594 ) 595 } 596 597 void lock_yield( spinlock * this DEBUG_CTX_PARAM2 ) { 598 for ( unsigned int i = 1;; i += 1 ) { 599 if ( this->lock == 0 && __sync_lock_test_and_set_4( &this->lock, 1 ) == 0 ) { break; } 600 yield(); 601 } 602 LIB_DEBUG_DO( 603 this->prev_name = caller; 604 this->prev_thrd = this_thread; 605 ) 606 } 607 608 609 void unlock( spinlock * this ) { 610 __sync_lock_release_4( &this->lock ); 611 } 612 576 613 void ?{}( semaphore & this, int count = 1 ) { 577 614 (this.lock){}; … … 582 619 583 620 void P(semaphore & this) { 584 lock( this.lock DEBUG_CTX2 );621 lock( &this.lock DEBUG_CTX2 ); 585 622 this.count -= 1; 586 623 if ( this.count < 0 ) { … … 592 629 } 593 630 else { 594 unlock( this.lock );631 unlock( &this.lock ); 595 632 } 596 633 } … … 598 635 void V(semaphore & this) { 599 636 thread_desc * thrd = NULL; 600 lock( this.lock DEBUG_CTX2 );637 lock( &this.lock DEBUG_CTX2 ); 601 638 this.count += 1; 602 639 if ( this.count <= 0 ) { … … 605 642 } 606 643 607 unlock( this.lock );644 unlock( &this.lock ); 608 645 609 646 // make new owner -
src/libcfa/concurrency/kernel_private.h
r490db327 rc95b115 45 45 //Block current thread and release/wake-up the following resources 46 46 void BlockInternal(void); 47 void BlockInternal( __spinlock_t* lock);47 void BlockInternal(spinlock * lock); 48 48 void BlockInternal(thread_desc * thrd); 49 void BlockInternal( __spinlock_t* lock, thread_desc * thrd);50 void BlockInternal( __spinlock_t* locks [], unsigned short count);51 void BlockInternal( __spinlock_t* locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count);52 void LeaveThread( __spinlock_t* lock, thread_desc * thrd);49 void BlockInternal(spinlock * lock, thread_desc * thrd); 50 void BlockInternal(spinlock * locks [], unsigned short count); 51 void BlockInternal(spinlock * locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count); 52 void LeaveThread(spinlock * lock, thread_desc * thrd); 53 53 54 54 //----------------------------------------------------------------------------- … … 66 66 struct event_kernel_t { 67 67 alarm_list_t alarms; 68 __spinlock_tlock;68 spinlock lock; 69 69 }; 70 70 -
src/libcfa/concurrency/monitor.c
r490db327 rc95b115 34 34 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & monitors ); 35 35 36 static inline void lock_all ( __spinlock_t* locks [], __lock_size_t count );37 static inline void lock_all ( monitor_desc * source [], __spinlock_t* /*out*/ locks [], __lock_size_t count );38 static inline void unlock_all( __spinlock_t* locks [], __lock_size_t count );36 static inline void lock_all ( spinlock * locks [], __lock_size_t count ); 37 static inline void lock_all ( monitor_desc * source [], spinlock * /*out*/ locks [], __lock_size_t count ); 38 static inline void unlock_all( spinlock * locks [], __lock_size_t count ); 39 39 static inline void unlock_all( monitor_desc * locks [], __lock_size_t count ); 40 40 41 static inline void save ( monitor_desc * ctx [], __lock_size_t count, __spinlock_t* locks [], unsigned int /*out*/ recursions [], __waitfor_mask_t /*out*/ masks [] );42 static inline void restore( monitor_desc * ctx [], __lock_size_t count, __spinlock_t* locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks [] );41 static inline void save ( monitor_desc * ctx [], __lock_size_t count, spinlock * locks [], unsigned int /*out*/ recursions [], __waitfor_mask_t /*out*/ masks [] ); 42 static inline void restore( monitor_desc * ctx [], __lock_size_t count, spinlock * locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks [] ); 43 43 44 44 static inline void init ( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ); … … 53 53 static inline __lock_size_t count_max ( const __waitfor_mask_t & mask ); 54 54 static inline __lock_size_t aggregate ( monitor_desc * storage [], const __waitfor_mask_t & mask ); 55 56 #ifndef __CFA_LOCK_NO_YIELD57 #define DO_LOCK lock_yield58 #else59 #define DO_LOCK lock60 #endif61 55 62 56 //----------------------------------------------------------------------------- … … 77 71 unsigned int recursions[ count ]; /* Save the current recursion levels to restore them later */ \ 78 72 __waitfor_mask_t masks [ count ]; /* Save the current waitfor masks to restore them later */ \ 79 __spinlock_t * locks[ count ]; /* We need to pass-in an array of locks to BlockInternal */ \73 spinlock * locks [ count ]; /* We need to pass-in an array of locks to BlockInternal */ \ 80 74 81 75 #define monitor_save save ( monitors, count, locks, recursions, masks ) … … 90 84 // Enter single monitor 91 85 static void __enter_monitor_desc( monitor_desc * this, const __monitor_group_t & group ) { 92 // Lock the monitor spinlock 93 DO_LOCK(this->lock DEBUG_CTX2 );86 // Lock the monitor spinlock, lock_yield to reduce contention 87 lock_yield( &this->lock DEBUG_CTX2 ); 94 88 thread_desc * thrd = this_thread; 95 89 … … 133 127 134 128 // Release the lock and leave 135 unlock( this->lock );129 unlock( &this->lock ); 136 130 return; 137 131 } 138 132 139 133 static void __enter_monitor_dtor( monitor_desc * this, fptr_t func ) { 140 // Lock the monitor spinlock 141 DO_LOCK(this->lock DEBUG_CTX2 );134 // Lock the monitor spinlock, lock_yield to reduce contention 135 lock_yield( &this->lock DEBUG_CTX2 ); 142 136 thread_desc * thrd = this_thread; 143 137 … … 151 145 set_owner( this, thrd ); 152 146 153 unlock( this->lock );147 unlock( &this->lock ); 154 148 return; 155 149 } … … 202 196 // Leave single monitor 203 197 void __leave_monitor_desc( monitor_desc * this ) { 204 // Lock the monitor spinlock, DO_LOCKto reduce contention205 DO_LOCK(this->lock DEBUG_CTX2 );198 // Lock the monitor spinlock, lock_yield to reduce contention 199 lock_yield( &this->lock DEBUG_CTX2 ); 206 200 207 201 LIB_DEBUG_PRINT_SAFE("Kernel : %10p Leaving mon %p (%p)\n", this_thread, this, this->owner); … … 216 210 if( this->recursion != 0) { 217 211 LIB_DEBUG_PRINT_SAFE("Kernel : recursion still %d\n", this->recursion); 218 unlock( this->lock );212 unlock( &this->lock ); 219 213 return; 220 214 } … … 224 218 225 219 // We can now let other threads in safely 226 unlock( this->lock );220 unlock( &this->lock ); 227 221 228 222 //We need to wake-up the thread … … 249 243 250 244 // Lock the monitor now 251 DO_LOCK(this->lock DEBUG_CTX2 );245 lock_yield( &this->lock DEBUG_CTX2 ); 252 246 253 247 disable_interrupts(); … … 736 730 } 737 731 738 static inline void lock_all( __spinlock_t* locks [], __lock_size_t count ) {732 static inline void lock_all( spinlock * locks [], __lock_size_t count ) { 739 733 for( __lock_size_t i = 0; i < count; i++ ) { 740 DO_LOCK( *locks[i] DEBUG_CTX2 );741 } 742 } 743 744 static inline void lock_all( monitor_desc * source [], __spinlock_t* /*out*/ locks [], __lock_size_t count ) {734 lock_yield( locks[i] DEBUG_CTX2 ); 735 } 736 } 737 738 static inline void lock_all( monitor_desc * source [], spinlock * /*out*/ locks [], __lock_size_t count ) { 745 739 for( __lock_size_t i = 0; i < count; i++ ) { 746 __spinlock_t* l = &source[i]->lock;747 DO_LOCK( *l DEBUG_CTX2 );740 spinlock * l = &source[i]->lock; 741 lock_yield( l DEBUG_CTX2 ); 748 742 if(locks) locks[i] = l; 749 743 } 750 744 } 751 745 752 static inline void unlock_all( __spinlock_t* locks [], __lock_size_t count ) {746 static inline void unlock_all( spinlock * locks [], __lock_size_t count ) { 753 747 for( __lock_size_t i = 0; i < count; i++ ) { 754 unlock( *locks[i] );748 unlock( locks[i] ); 755 749 } 756 750 } … … 758 752 static inline void unlock_all( monitor_desc * locks [], __lock_size_t count ) { 759 753 for( __lock_size_t i = 0; i < count; i++ ) { 760 unlock( locks[i]->lock );754 unlock( &locks[i]->lock ); 761 755 } 762 756 } … … 765 759 monitor_desc * ctx [], 766 760 __lock_size_t count, 767 __attribute((unused)) __spinlock_t* locks [],761 __attribute((unused)) spinlock * locks [], 768 762 unsigned int /*out*/ recursions [], 769 763 __waitfor_mask_t /*out*/ masks [] … … 778 772 monitor_desc * ctx [], 779 773 __lock_size_t count, 780 __spinlock_t* locks [],774 spinlock * locks [], 781 775 unsigned int /*out*/ recursions [], 782 776 __waitfor_mask_t /*out*/ masks [] -
src/libcfa/concurrency/preemption.c
r490db327 rc95b115 355 355 case SI_KERNEL: 356 356 // LIB_DEBUG_PRINT_SAFE("Kernel : Preemption thread tick\n"); 357 lock( event_kernel->lock DEBUG_CTX2 );357 lock( &event_kernel->lock DEBUG_CTX2 ); 358 358 tick_preemption(); 359 unlock( event_kernel->lock );359 unlock( &event_kernel->lock ); 360 360 break; 361 361 // Signal was not sent by the kernel but by an other thread -
src/prelude/builtins.c
r490db327 rc95b115 80 80 } // ?\? 81 81 82 // FIXME (x \ (unsigned long int)y) relies on X ?\?(T, unsigned long) a function that is neither 83 // defined, nor passed as an assertion parameter. Without user-defined conversions, cannot specify 84 // X as a type that casts to double, yet it doesn't make sense to write functions with that type 85 // signature where X is double. 86 87 // static inline forall( otype T | { void ?{}( T & this, one_t ); T ?*?( T, T ); double ?/?( double, T ); } ) 88 // double ?\?( T x, signed long int y ) { 89 // if ( y >= 0 ) return (double)(x \ (unsigned long int)y); 90 // else return 1.0 / x \ (unsigned long int)(-y); 91 // } // ?\? 82 static inline forall( otype T | { void ?{}( T & this, one_t ); T ?*?( T, T ); double ?/?( double, T ); } ) 83 double ?\?( T x, signed long int y ) { 84 if ( y >= 0 ) return (double)(x \ (unsigned long int)y); 85 else return 1.0 / x \ (unsigned long int)(-y); 86 } // ?\? 92 87 93 88 static inline long int ?\=?( long int & x, unsigned long int y ) { x = x \ y; return x; }
Note:
See TracChangeset
for help on using the changeset viewer.