Changeset cce9429 for src/GenPoly/Box.cc
- Timestamp:
- Dec 13, 2016, 6:42:39 PM (6 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 1aa4b71
- Parents:
- 31f379c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Box.cc
r31f379c rcce9429 131 131 ScopedMap< std::string, DeclarationWithType* > adapters; ///< Set of adapter functions in the current scope 132 132 133 std::map< ApplicationExpr *, Expression * > retVals; 134 133 135 DeclarationWithType *retval; 134 bool useRetval;135 136 UniqueName tempNamer; 136 137 }; … … 497 498 } 498 499 499 Pass1::Pass1() : useRetval( false ),tempNamer( "_temp" ) {}500 Pass1::Pass1() : tempNamer( "_temp" ) {} 500 501 501 502 /// Returns T if the given declaration is a function with parameter (T*) for some TypeInstType T, NULL otherwise … … 667 668 668 669 DeclarationWithType *oldRetval = retval; 669 bool oldUseRetval = useRetval;670 670 671 671 // process polymorphic return value 672 retval = 0;673 if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall) {672 retval = nullptr; 673 if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() != LinkageSpec::C ) { 674 674 retval = functionDecl->get_functionType()->get_returnVals().front(); 675 675 … … 700 700 if ( adapters.find( mangleName ) == adapters.end() ) { 701 701 std::string adapterName = makeAdapterName( mangleName ); 702 adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0) ) );702 adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), nullptr ) ) ); 703 703 } // if 704 704 } // for … … 712 712 dtorOps.endScope(); 713 713 retval = oldRetval; 714 useRetval = oldUseRetval;715 714 doEndScope(); 716 715 } // if … … 724 723 725 724 Expression *Pass1::mutate( CommaExpr *commaExpr ) { 726 bool oldUseRetval = useRetval; 727 useRetval = false; 725 // Attempting to find application expressions that were mutated by the copy constructor passes 726 // to use an explicit return variable, so that the variable can be reused as a parameter to the 727 // call rather than creating a new temp variable. Previously this step was an optimization, but 728 // with the introduction of tuples and UniqueExprs, it is necessary to ensure that they use the same variable. 729 // Essentially, looking for pattern: (x=f(...), x) 730 // To compound the issue, the right side can be *x, etc. because of lvalue-returning functions 731 if ( UntypedExpr * assign = dynamic_cast< UntypedExpr * >( commaExpr->get_arg1() ) ) { 732 if ( InitTweak::isAssignment( InitTweak::getFunctionName( assign ) ) ) { 733 assert( assign->get_args().size() == 2 ); 734 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( assign->get_args().back() ) ) { 735 // first argument is assignable, so it must be an lvalue, so it should be legal to take its address. 736 retVals[appExpr] = assign->get_args().front(); 737 } 738 } 739 } 740 728 741 commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) ); 729 useRetval = oldUseRetval;730 742 commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) ); 731 743 return commaExpr; … … 733 745 734 746 Expression *Pass1::mutate( ConditionalExpr *condExpr ) { 735 bool oldUseRetval = useRetval;736 useRetval = false;737 747 condExpr->set_arg1( maybeMutate( condExpr->get_arg1(), *this ) ); 738 useRetval = oldUseRetval;739 748 condExpr->set_arg2( maybeMutate( condExpr->get_arg2(), *this ) ); 740 749 condExpr->set_arg3( maybeMutate( condExpr->get_arg3(), *this ) ); … … 783 792 } else { 784 793 // xxx - should this be an assertion? 785 throw SemanticError( "unbound type variable: " + tyParm->first + " in application ", appExpr ); 794 std::string x = env ? toString( *env ) : "missing env"; 795 throw SemanticError( x + "\n" + "unbound type variable: " + tyParm->first + " in application ", appExpr ); 786 796 } // if 787 797 } // if … … 819 829 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) { 820 830 // Create temporary to hold return value of polymorphic function and produce that temporary as a result 821 // using a comma expression. Possibly change comma expression into statement expression "{}" for multiple 822 // return values. 831 // using a comma expression. 823 832 assert( retType ); 824 ObjectDecl *newObj = makeTemporary( retType->clone() ); 825 Expression *paramExpr = new VariableExpr( newObj ); 833 834 Expression * paramExpr = nullptr; 835 // try to use existing return value parameter if it exists, otherwise create a new temporary 836 if ( retVals.count( appExpr ) ) { 837 paramExpr = retVals[appExpr]->clone(); 838 } else { 839 ObjectDecl *newObj = makeTemporary( retType->clone() ); 840 paramExpr = new VariableExpr( newObj ); 841 } 842 Expression * retExpr = paramExpr->clone(); 826 843 827 844 // If the type of the temporary is not polymorphic, box temporary by taking its address; 828 845 // otherwise the temporary is already boxed and can be used directly. 829 if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) {846 if ( ! isPolyType( paramExpr->get_result(), scopeTyVars, env ) ) { 830 847 paramExpr = new AddressExpr( paramExpr ); 831 848 } // if … … 833 850 arg++; 834 851 // Build a comma expression to call the function and emulate a normal return. 835 CommaExpr *commaExpr = new CommaExpr( appExpr, new VariableExpr( newObj ));852 CommaExpr *commaExpr = new CommaExpr( appExpr, retExpr ); 836 853 commaExpr->set_env( appExpr->get_env() ); 837 854 appExpr->set_env( 0 ); … … 851 868 Type *concrete = env->lookup( typeInst->get_name() ); 852 869 if ( concrete == 0 ) { 853 throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr ); 870 // xxx - should this be an assertion? 871 std::string x = env ? toString( *env ) : "missing env"; 872 throw SemanticError( x + "\n" + "Unbound type variable " + typeInst->get_name() + " in ", appExpr ); 854 873 } // if 855 874 return concrete; … … 1259 1278 // } 1260 1279 // std::cerr << "\n"; 1261 bool oldUseRetval = useRetval;1262 useRetval = false;1263 1280 appExpr->get_function()->acceptMutator( *this ); 1264 1281 mutateAll( appExpr->get_args(), *this ); 1265 useRetval = oldUseRetval;1266 1282 1267 1283 assert( appExpr->get_function()->has_result() ); … … 1545 1561 } 1546 1562 1563 /// determines if `pref` is a prefix of `str` 1564 bool isPrefix( const std::string & str, const std::string & pref ) { 1565 if ( pref.size() > str.size() ) return false; 1566 auto its = std::mismatch( pref.begin(), pref.end(), str.begin() ); 1567 return its.first == pref.end(); 1568 } 1569 1547 1570 DeclarationWithType * Pass2::mutate( FunctionDecl *functionDecl ) { 1548 return handleDecl( functionDecl, functionDecl->get_functionType() ); 1571 if ( ! LinkageSpec::isBuiltin( functionDecl->get_linkage() ) ) { 1572 // std::cerr << "mutating function: " << functionDecl->get_name() << std::endl; 1573 } 1574 functionDecl = safe_dynamic_cast< FunctionDecl * > ( handleDecl( functionDecl, functionDecl->get_functionType() ) ); 1575 FunctionType * ftype = functionDecl->get_functionType(); 1576 if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) { 1577 if ( functionDecl->get_name() != "?=?" && ! isPrefix( functionDecl->get_name(), "_thunk" ) ) { // xxx - remove check for ?=? once reference types are in; remove check for prefix once thunks properly use ctor/dtors 1578 assert( ftype->get_returnVals().size() == 1 ); 1579 DeclarationWithType * retval = ftype->get_returnVals().front(); 1580 if ( retval->get_name() == "" ) { 1581 retval->set_name( "_retval" ); 1582 } 1583 functionDecl->get_statements()->get_kids().push_front( new DeclStmt( noLabels, retval ) ); 1584 DeclarationWithType * newRet = retval->clone(); // for ownership purposes 1585 ftype->get_returnVals().front() = newRet; 1586 } 1587 } 1588 return functionDecl; 1549 1589 } 1550 1590
Note: See TracChangeset
for help on using the changeset viewer.