Changes in src/GenPoly/Specialize.cc [8cbf8cd:aedfd91]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Specialize.cc
r8cbf8cd raedfd91 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Specialize.cc -- 7 // Specialize.cc -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : T ue Sep 22 14:04:13 201513 // Update Count : 1512 // Last Modified On : Thu Apr 28 15:17:45 2016 13 // Update Count : 24 14 14 // 15 15 … … 17 17 18 18 #include "Specialize.h" 19 #include "GenPoly.h" 19 20 #include "PolyMutator.h" 20 21 … … 24 25 #include "SynTree/Statement.h" 25 26 #include "SynTree/Type.h" 27 #include "SynTree/Attribute.h" 26 28 #include "SynTree/TypeSubstitution.h" 27 29 #include "SynTree/Mutator.h" 28 30 #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" 31 34 32 35 namespace GenPoly { … … 40 43 virtual Expression * mutate( AddressExpr *castExpr ); 41 44 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 ); 45 48 46 49 private: 50 Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams = 0 ); 47 51 Expression *doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams = 0 ); 48 52 void handleExplicitParams( ApplicationExpr *appExpr ); … … 61 65 } 62 66 67 /// Looks up open variables in actual type, returning true if any of them are bound in the environment or formal type. 63 68 bool needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) { 64 69 if ( env ) { … … 85 90 } 86 91 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 87 148 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 89 150 if ( needsSpecialization( formalType, actual->get_results().front(), env ) ) { 90 PointerType *ptrType;91 151 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 ); 127 159 } 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 } 133 163 } else { 134 164 return actual; … … 142 172 // create thunks for the explicit parameters 143 173 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 ); 147 176 std::list< DeclarationWithType* >::iterator formal; 148 177 std::list< Expression* >::iterator actual; … … 156 185 mutateAll( appExpr->get_args(), *this ); 157 186 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 } 164 196 165 197 return appExpr; … … 175 207 Expression * Specialize::mutate( CastExpr *castExpr ) { 176 208 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 // } 196 237 } // namespace GenPoly 197 238
Note:
See TracChangeset
for help on using the changeset viewer.