Changeset cce9429 for src/GenPoly


Ignore:
Timestamp:
Dec 13, 2016, 6:42:39 PM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, 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
Message:

fix function return type in Validate and add single return decl, construct the return decl, fix polymorphic functions to use the return decl

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    r31f379c rcce9429  
    131131                        ScopedMap< std::string, DeclarationWithType* > adapters;     ///< Set of adapter functions in the current scope
    132132
     133                        std::map< ApplicationExpr *, Expression * > retVals;
     134
    133135                        DeclarationWithType *retval;
    134                         bool useRetval;
    135136                        UniqueName tempNamer;
    136137                };
     
    497498                }
    498499
    499                 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {}
     500                Pass1::Pass1() : tempNamer( "_temp" ) {}
    500501
    501502                /// Returns T if the given declaration is a function with parameter (T*) for some TypeInstType T, NULL otherwise
     
    667668
    668669                                DeclarationWithType *oldRetval = retval;
    669                                 bool oldUseRetval = useRetval;
    670670
    671671                                // 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 ) {
    674674                                        retval = functionDecl->get_functionType()->get_returnVals().front();
    675675
     
    700700                                        if ( adapters.find( mangleName ) == adapters.end() ) {
    701701                                                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 ) ) );
    703703                                        } // if
    704704                                } // for
     
    712712                                dtorOps.endScope();
    713713                                retval = oldRetval;
    714                                 useRetval = oldUseRetval;
    715714                                doEndScope();
    716715                        } // if
     
    724723
    725724                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
    728741                        commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) );
    729                         useRetval = oldUseRetval;
    730742                        commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) );
    731743                        return commaExpr;
     
    733745
    734746                Expression *Pass1::mutate( ConditionalExpr *condExpr ) {
    735                         bool oldUseRetval = useRetval;
    736                         useRetval = false;
    737747                        condExpr->set_arg1( maybeMutate( condExpr->get_arg1(), *this ) );
    738                         useRetval = oldUseRetval;
    739748                        condExpr->set_arg2( maybeMutate( condExpr->get_arg2(), *this ) );
    740749                        condExpr->set_arg3( maybeMutate( condExpr->get_arg3(), *this ) );
     
    783792                                        } else {
    784793                                                // 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 );
    786796                                        } // if
    787797                                } // if
     
    819829                Expression *Pass1::addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg ) {
    820830                        // 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.
    823832                        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();
    826843
    827844                        // If the type of the temporary is not polymorphic, box temporary by taking its address;
    828845                        // 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 ) ) {
    830847                                paramExpr = new AddressExpr( paramExpr );
    831848                        } // if
     
    833850                        arg++;
    834851                        // 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 );
    836853                        commaExpr->set_env( appExpr->get_env() );
    837854                        appExpr->set_env( 0 );
     
    851868                                Type *concrete = env->lookup( typeInst->get_name() );
    852869                                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 );
    854873                                } // if
    855874                                return concrete;
     
    12591278                        // }
    12601279                        // std::cerr << "\n";
    1261                         bool oldUseRetval = useRetval;
    1262                         useRetval = false;
    12631280                        appExpr->get_function()->acceptMutator( *this );
    12641281                        mutateAll( appExpr->get_args(), *this );
    1265                         useRetval = oldUseRetval;
    12661282
    12671283                        assert( appExpr->get_function()->has_result() );
     
    15451561                }
    15461562
     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
    15471570                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;
    15491589                }
    15501590
Note: See TracChangeset for help on using the changeset viewer.