Changeset 698664b


Ignore:
Timestamp:
Oct 28, 2015, 3:41:07 PM (7 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, string, with_gc
Children:
d2ded3e7
Parents:
f6835e5
Message:

Improved handling of cast expression boxing

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    rf6835e5 r698664b  
    414414                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
    415415                                        InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() );
    416                                         assert( inferParam != appExpr->get_inferParams().end() );
     416                                        assert( inferParam != appExpr->get_inferParams().end() && "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" );
    417417                                        Expression *newExpr = inferParam->second.expr->clone();
    418418                                        addCast( newExpr, (*assert)->get_type(), tyVars );
  • src/GenPoly/Specialize.cc

    rf6835e5 r698664b  
    4545
    4646          private:
     47                Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams = 0 );
    4748                Expression *doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams = 0 );
    4849                void handleExplicitParams( ApplicationExpr *appExpr );
     
    6162        }
    6263
     64        /// Looks up open variables in actual type, returning true if any of them are bound in the environment or formal type.
    6365        bool needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
    6466                if ( env ) {
     
    8587        }
    8688
     89        /// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise
     90        FunctionType * getFunctionType( Type *ty ) {
     91                PointerType *ptrType;
     92                if ( ( ptrType = dynamic_cast< PointerType* >( ty ) ) ) {
     93                        return dynamic_cast< FunctionType* >( ptrType->get_base() ); // pointer if FunctionType, NULL otherwise
     94                } else {
     95                        return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise
     96                }
     97        }
     98
     99        /// Generates a thunk that calls `actual` with type `funType` and returns its address
     100        Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
     101                FunctionType *newType = funType->clone();
     102                if ( env ) {
     103                        TypeSubstitution newEnv( *env );
     104                        // it is important to replace only occurrences of type variables that occur free in the
     105                        // thunk's type
     106                        newEnv.applyFree( newType );
     107                } // if
     108                // create new thunk with same signature as formal type (C linkage, empty body)
     109                FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, newType, new CompoundStmt( std::list< std::string >() ), false, false );
     110                thunkFunc->fixUniqueId();
     111
     112                // thread thunk parameters into call to actual function, naming thunk parameters as we go
     113                UniqueName paramNamer( paramPrefix );
     114                ApplicationExpr *appExpr = new ApplicationExpr( actual );
     115                for ( std::list< DeclarationWithType* >::iterator param = thunkFunc->get_functionType()->get_parameters().begin(); param != thunkFunc->get_functionType()->get_parameters().end(); ++param ) {
     116                        (*param )->set_name( paramNamer.newName() );
     117                        appExpr->get_args().push_back( new VariableExpr( *param ) );
     118                } // for
     119                appExpr->set_env( maybeClone( env ) );
     120                if ( inferParams ) {
     121                        appExpr->get_inferParams() = *inferParams;
     122                } // if
     123
     124                // handle any specializations that may still be present
     125                std::string oldParamPrefix = paramPrefix;
     126                paramPrefix += "p";
     127                // save stmtsToAdd in oldStmts
     128                std::list< Statement* > oldStmts;
     129                oldStmts.splice( oldStmts.end(), stmtsToAdd );
     130                handleExplicitParams( appExpr );
     131                paramPrefix = oldParamPrefix;
     132                // write any statements added for recursive specializations into the thunk body
     133                thunkFunc->get_statements()->get_kids().splice( thunkFunc->get_statements()->get_kids().end(), stmtsToAdd );
     134                // restore oldStmts into stmtsToAdd
     135                stmtsToAdd.splice( stmtsToAdd.end(), oldStmts );
     136
     137                // add return (or valueless expression) to the thunk
     138                Statement *appStmt;
     139                if ( funType->get_returnVals().empty() ) {
     140                        appStmt = new ExprStmt( noLabels, appExpr );
     141                } else {
     142                        appStmt = new ReturnStmt( noLabels, appExpr );
     143                } // if
     144                thunkFunc->get_statements()->get_kids().push_back( appStmt );
     145
     146                // add thunk definition to queue of statements to add
     147                stmtsToAdd.push_back( new DeclStmt( noLabels, thunkFunc ) );
     148                // return address of thunk function as replacement expression
     149                return new AddressExpr( new VariableExpr( thunkFunc ) );
     150        }
     151       
    87152        Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
    88153                if ( needsSpecialization( formalType, actual->get_results().front(), env ) ) {
    89                         PointerType *ptrType;
    90154                        FunctionType *funType;
    91                         if ( ( ptrType = dynamic_cast< PointerType* >( formalType ) ) && ( funType = dynamic_cast< FunctionType* >( ptrType->get_base() ) ) ) {
    92                                 FunctionType *newType = funType->clone();
    93                                 if ( env ) {
    94                                         TypeSubstitution newEnv( *env );
    95                                         // it is important to replace only occurrences of type variables that occur free in the
    96                                         // thunk's type
    97                                         newEnv.applyFree( newType );
    98                                 } // if
    99                                 FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, newType, new CompoundStmt( std::list< std::string >() ), false, false );
    100                                 thunkFunc->fixUniqueId();
    101 
    102                                 UniqueName paramNamer( paramPrefix );
    103                                 ApplicationExpr *appExpr = new ApplicationExpr( actual );
    104                                 for ( std::list< DeclarationWithType* >::iterator param = thunkFunc->get_functionType()->get_parameters().begin(); param != thunkFunc->get_functionType()->get_parameters().end(); ++param ) {
    105                                         (*param )->set_name( paramNamer.newName() );
    106                                         appExpr->get_args().push_back( new VariableExpr( *param ) );
    107                                 } // for
    108                                 appExpr->set_env( maybeClone( env ) );
    109                                 if ( inferParams ) {
    110                                         appExpr->get_inferParams() = *inferParams;
    111                                 } // if
    112 
    113                                 // handle any specializations that may still be present
    114                                 std::string oldParamPrefix = paramPrefix;
    115                                 paramPrefix += "p";
    116                                 std::list< Statement* > oldStmts;
    117                                 oldStmts.splice( oldStmts.end(), stmtsToAdd );
    118                                 handleExplicitParams( appExpr );
    119                                 paramPrefix = oldParamPrefix;
    120                                 thunkFunc->get_statements()->get_kids().splice( thunkFunc->get_statements()->get_kids().end(), stmtsToAdd );
    121                                 stmtsToAdd.splice( stmtsToAdd.end(), oldStmts );
    122 
    123                                 Statement *appStmt;
    124                                 if ( funType->get_returnVals().empty() ) {
    125                                         appStmt = new ExprStmt( noLabels, appExpr );
     155                        if ( ( funType = getFunctionType( formalType ) ) ) {
     156                                ApplicationExpr *appExpr;
     157                                VariableExpr *varExpr;
     158                                if ( ( appExpr = dynamic_cast<ApplicationExpr*>( actual ) ) ) {
     159                                        return createThunkFunction( funType, appExpr->get_function(), inferParams );
     160                                } else if ( ( varExpr = dynamic_cast<VariableExpr*>( actual ) ) ) {
     161                                        return createThunkFunction( funType, varExpr, inferParams );
    126162                                } else {
    127                                         appStmt = new ReturnStmt( noLabels, appExpr );
    128                                 } // if
    129                                 thunkFunc->get_statements()->get_kids().push_back( appStmt );
    130                                 stmtsToAdd.push_back( new DeclStmt( noLabels, thunkFunc ) );
    131                                 return new AddressExpr( new VariableExpr( thunkFunc ) );
     163                                        // This likely won't work, as anything that could build an ApplicationExpr probably hit one of the previous two branches
     164                                        return createThunkFunction( funType, actual, inferParams );
     165                                }
    132166                        } else {
    133167                                return actual;
     
    141175                // create thunks for the explicit parameters
    142176                assert( ! appExpr->get_function()->get_results().empty() );
    143                 PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
    144                 assert( pointer );
    145                 FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
     177                FunctionType *function = getFunctionType( appExpr->get_function()->get_results().front() );
     178                assert( function );
    146179                std::list< DeclarationWithType* >::iterator formal;
    147180                std::list< Expression* >::iterator actual;
     
    173206        Expression * Specialize::mutate( CastExpr *castExpr ) {
    174207                castExpr->get_arg()->acceptMutator( *this );
    175                 castExpr->set_arg( doSpecialization( castExpr->get_results().front(), castExpr->get_arg() ) );
    176                 return castExpr;
     208                Expression *specialized = doSpecialization( castExpr->get_results().front(), castExpr->get_arg() );
     209                if ( specialized != castExpr->get_arg() ) {
     210                        // assume here that the specialization incorporates the cast
     211                        return specialized;
     212                } else {
     213                        return castExpr;
     214                }
    177215        }
    178216
  • src/main.cc

    rf6835e5 r698664b  
    271271                GenPoly::copyParams( translationUnit );
    272272                OPTPRINT( "convertSpecializations" )
    273                 GenPoly::convertSpecializations( translationUnit );             
     273                GenPoly::convertSpecializations( translationUnit );
    274274                OPTPRINT( "convertLvalue" )
    275275                GenPoly::convertLvalue( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.