Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Specialize.cc

    r8cbf8cd raedfd91  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Specialize.cc -- 
     7// Specialize.cc --
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Rob Schluntz
    12 // Last Modified On : Tue Sep 22 14:04:13 2015
    13 // Update Count     : 15
     12// Last Modified On : Thu Apr 28 15:17:45 2016
     13// Update Count     : 24
    1414//
    1515
     
    1717
    1818#include "Specialize.h"
     19#include "GenPoly.h"
    1920#include "PolyMutator.h"
    2021
     
    2425#include "SynTree/Statement.h"
    2526#include "SynTree/Type.h"
     27#include "SynTree/Attribute.h"
    2628#include "SynTree/TypeSubstitution.h"
    2729#include "SynTree/Mutator.h"
    2830#include "ResolvExpr/FindOpenVars.h"
    29 #include "UniqueName.h"
    30 #include "utility.h"
     31#include "Common/UniqueName.h"
     32#include "Common/utility.h"
     33#include "InitTweak/InitTweak.h"
    3134
    3235namespace GenPoly {
     
    4043                virtual Expression * mutate( AddressExpr *castExpr );
    4144                virtual Expression * mutate( CastExpr *castExpr );
    42                 virtual Expression * mutate( LogicalExpr *logicalExpr );
    43                 virtual Expression * mutate( ConditionalExpr *conditionalExpr );
    44                 virtual Expression * mutate( CommaExpr *commaExpr );
     45                // virtual Expression * mutate( LogicalExpr *logicalExpr );
     46                // virtual Expression * mutate( ConditionalExpr *conditionalExpr );
     47                // virtual Expression * mutate( CommaExpr *commaExpr );
    4548
    4649          private:
     50                Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams = 0 );
    4751                Expression *doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams = 0 );
    4852                void handleExplicitParams( ApplicationExpr *appExpr );
     
    6165        }
    6266
     67        /// Looks up open variables in actual type, returning true if any of them are bound in the environment or formal type.
    6368        bool needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
    6469                if ( env ) {
     
    8590        }
    8691
     92        /// Generates a thunk that calls `actual` with type `funType` and returns its address
     93        Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
     94                FunctionType *newType = funType->clone();
     95                if ( env ) {
     96                        TypeSubstitution newEnv( *env );
     97                        // it is important to replace only occurrences of type variables that occur free in the
     98                        // thunk's type
     99                        newEnv.applyFree( newType );
     100                } // if
     101                // create new thunk with same signature as formal type (C linkage, empty body)
     102                FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, newType, new CompoundStmt( noLabels ), false, false );
     103                thunkFunc->fixUniqueId();
     104
     105                // thunks may be generated and not used - silence warning with attribute
     106                thunkFunc->get_attributes().push_back( new Attribute( "unused" ) );
     107
     108                // thread thunk parameters into call to actual function, naming thunk parameters as we go
     109                UniqueName paramNamer( paramPrefix );
     110                ApplicationExpr *appExpr = new ApplicationExpr( actual );
     111                for ( std::list< DeclarationWithType* >::iterator param = thunkFunc->get_functionType()->get_parameters().begin(); param != thunkFunc->get_functionType()->get_parameters().end(); ++param ) {
     112                        (*param )->set_name( paramNamer.newName() );
     113                        appExpr->get_args().push_back( new VariableExpr( *param ) );
     114                } // for
     115                appExpr->set_env( maybeClone( env ) );
     116                if ( inferParams ) {
     117                        appExpr->get_inferParams() = *inferParams;
     118                } // if
     119
     120                // handle any specializations that may still be present
     121                std::string oldParamPrefix = paramPrefix;
     122                paramPrefix += "p";
     123                // save stmtsToAdd in oldStmts
     124                std::list< Statement* > oldStmts;
     125                oldStmts.splice( oldStmts.end(), stmtsToAdd );
     126                handleExplicitParams( appExpr );
     127                paramPrefix = oldParamPrefix;
     128                // write any statements added for recursive specializations into the thunk body
     129                thunkFunc->get_statements()->get_kids().splice( thunkFunc->get_statements()->get_kids().end(), stmtsToAdd );
     130                // restore oldStmts into stmtsToAdd
     131                stmtsToAdd.splice( stmtsToAdd.end(), oldStmts );
     132
     133                // add return (or valueless expression) to the thunk
     134                Statement *appStmt;
     135                if ( funType->get_returnVals().empty() ) {
     136                        appStmt = new ExprStmt( noLabels, appExpr );
     137                } else {
     138                        appStmt = new ReturnStmt( noLabels, appExpr );
     139                } // if
     140                thunkFunc->get_statements()->get_kids().push_back( appStmt );
     141
     142                // add thunk definition to queue of statements to add
     143                stmtsToAdd.push_back( new DeclStmt( noLabels, thunkFunc ) );
     144                // return address of thunk function as replacement expression
     145                return new AddressExpr( new VariableExpr( thunkFunc ) );
     146        }
     147
    87148        Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
    88                 assert( ! actual->get_results().empty() );
     149                assert( ! actual->get_results().empty() ); // using front, should have this assert
    89150                if ( needsSpecialization( formalType, actual->get_results().front(), env ) ) {
    90                         PointerType *ptrType;
    91151                        FunctionType *funType;
    92                         if ( ( ptrType = dynamic_cast< PointerType* >( formalType ) ) && ( funType = dynamic_cast< FunctionType* >( ptrType->get_base() ) ) ) {
    93                                 FunctionType *newType = funType->clone();
    94                                 if ( env ) {
    95                                         TypeSubstitution newEnv( *env );
    96                                         // it is important to replace only occurrences of type variables that occur free in the
    97                                         // thunk's type
    98                                         newEnv.applyFree( newType );
    99                                 } // if
    100                                 FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, newType, new CompoundStmt( std::list< std::string >() ), false, false );
    101                                 thunkFunc->fixUniqueId();
    102 
    103                                 UniqueName paramNamer( paramPrefix );
    104                                 ApplicationExpr *appExpr = new ApplicationExpr( actual );
    105                                 for ( std::list< DeclarationWithType* >::iterator param = thunkFunc->get_functionType()->get_parameters().begin(); param != thunkFunc->get_functionType()->get_parameters().end(); ++param ) {
    106                                         (*param )->set_name( paramNamer.newName() );
    107                                         appExpr->get_args().push_back( new VariableExpr( *param ) );
    108                                 } // for
    109                                 appExpr->set_env( maybeClone( env ) );
    110                                 if ( inferParams ) {
    111                                         appExpr->get_inferParams() = *inferParams;
    112                                 } // if
    113 
    114                                 // handle any specializations that may still be present
    115                                 std::string oldParamPrefix = paramPrefix;
    116                                 paramPrefix += "p";
    117                                 std::list< Statement* > oldStmts;
    118                                 oldStmts.splice( oldStmts.end(), stmtsToAdd );
    119                                 handleExplicitParams( appExpr );
    120                                 paramPrefix = oldParamPrefix;
    121                                 thunkFunc->get_statements()->get_kids().splice( thunkFunc->get_statements()->get_kids().end(), stmtsToAdd );
    122                                 stmtsToAdd.splice( stmtsToAdd.end(), oldStmts );
    123 
    124                                 Statement *appStmt;
    125                                 if ( funType->get_returnVals().empty() ) {
    126                                         appStmt = new ExprStmt( noLabels, appExpr );
     152                        if ( ( funType = getFunctionType( formalType ) ) ) {
     153                                ApplicationExpr *appExpr;
     154                                VariableExpr *varExpr;
     155                                if ( ( appExpr = dynamic_cast<ApplicationExpr*>( actual ) ) ) {
     156                                        return createThunkFunction( funType, appExpr->get_function(), inferParams );
     157                                } else if ( ( varExpr = dynamic_cast<VariableExpr*>( actual ) ) ) {
     158                                        return createThunkFunction( funType, varExpr, inferParams );
    127159                                } else {
    128                                         appStmt = new ReturnStmt( noLabels, appExpr );
    129                                 } // if
    130                                 thunkFunc->get_statements()->get_kids().push_back( appStmt );
    131                                 stmtsToAdd.push_back( new DeclStmt( noLabels, thunkFunc ) );
    132                                 return new AddressExpr( new VariableExpr( thunkFunc ) );
     160                                        // This likely won't work, as anything that could build an ApplicationExpr probably hit one of the previous two branches
     161                                        return createThunkFunction( funType, actual, inferParams );
     162                                }
    133163                        } else {
    134164                                return actual;
     
    142172                // create thunks for the explicit parameters
    143173                assert( ! appExpr->get_function()->get_results().empty() );
    144                 PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
    145                 assert( pointer );
    146                 FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
     174                FunctionType *function = getFunctionType( appExpr->get_function()->get_results().front() );
     175                assert( function );
    147176                std::list< DeclarationWithType* >::iterator formal;
    148177                std::list< Expression* >::iterator actual;
     
    156185                mutateAll( appExpr->get_args(), *this );
    157186
    158                 // create thunks for the inferred parameters
    159                 for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
    160                         inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
    161                 }
    162 
    163                 handleExplicitParams( appExpr );
     187                if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) {
     188                        // create thunks for the inferred parameters
     189                        // don't need to do this for intrinsic calls, because they aren't actually passed
     190                        for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
     191                                inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
     192                        }
     193
     194                        handleExplicitParams( appExpr );
     195                }
    164196
    165197                return appExpr;
     
    175207        Expression * Specialize::mutate( CastExpr *castExpr ) {
    176208                castExpr->get_arg()->acceptMutator( *this );
    177                 if ( ! castExpr->get_results().empty() ) {
    178                         // this may not be the correct condition, but previously the next statement
    179                         // was happening unchecked, causing a crash on a cast to void
    180                         castExpr->set_arg( doSpecialization( castExpr->get_results().front(), castExpr->get_arg() ) );         
    181                 }
    182                 return castExpr;
    183         }
    184 
    185         Expression * Specialize::mutate( LogicalExpr *logicalExpr ) {
    186                 return logicalExpr;
    187         }
    188 
    189         Expression * Specialize::mutate( ConditionalExpr *condExpr ) {
    190                 return condExpr;
    191         }
    192 
    193         Expression * Specialize::mutate( CommaExpr *commaExpr ) {
    194                 return commaExpr;
    195         }
     209                if ( castExpr->get_results().empty() ) {
     210                        // can't specialize if we don't have a return value
     211                        return castExpr;
     212                }
     213                Expression *specialized = doSpecialization( castExpr->get_results().front(), castExpr->get_arg() );
     214                if ( specialized != castExpr->get_arg() ) {
     215                        // assume here that the specialization incorporates the cast
     216                        return specialized;
     217                } else {
     218                        return castExpr;
     219                }
     220        }
     221
     222        // Removing these for now. Richard put these in for some reason, but it's not clear why.
     223        // In particular, copy constructors produce a comma expression, and with this code the parts
     224        // of that comma expression are not specialized, which causes problems.
     225
     226        // Expression * Specialize::mutate( LogicalExpr *logicalExpr ) {
     227        //      return logicalExpr;
     228        // }
     229
     230        // Expression * Specialize::mutate( ConditionalExpr *condExpr ) {
     231        //      return condExpr;
     232        // }
     233
     234        // Expression * Specialize::mutate( CommaExpr *commaExpr ) {
     235        //      return commaExpr;
     236        // }
    196237} // namespace GenPoly
    197238
Note: See TracChangeset for help on using the changeset viewer.