Changeset 626dbc10
- Timestamp:
- Dec 21, 2016, 3:12:19 PM (8 years ago)
- 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:
- b940dc71
- Parents:
- e33f321
- git-author:
- Rob Schluntz <rschlunt@…> (12/21/16 15:07:41)
- git-committer:
- Rob Schluntz <rschlunt@…> (12/21/16 15:12:19)
- Location:
- src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/GenPoly/Specialize.cc ¶
re33f321 r626dbc10 34 34 35 35 namespace GenPoly { 36 const std::list<Label> noLabels; 37 36 class Specializer; 38 37 class Specialize final : public PolyMutator { 38 friend class Specializer; 39 39 public: 40 Specialize( std::string paramPrefix = "_p" );41 42 40 using PolyMutator::mutate; 43 41 virtual Expression * mutate( ApplicationExpr *applicationExpr ) override; … … 48 46 // virtual Expression * mutate( CommaExpr *commaExpr ); 49 47 50 private: 51 Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams = 0 ); 52 Expression *doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams = 0 ); 48 Specializer * specializer = nullptr; 53 49 void handleExplicitParams( ApplicationExpr *appExpr ); 54 55 UniqueName thunkNamer;56 std::string paramPrefix;57 50 }; 58 51 59 void convertSpecializations( std::list< Declaration* >& translationUnit ) { 60 Specialize specializer; 61 mutateAll( translationUnit, specializer ); 62 } 63 64 Specialize::Specialize( std::string paramPrefix ) 65 : thunkNamer( "_thunk" ), paramPrefix( paramPrefix ) { 66 } 52 class Specializer { 53 public: 54 Specializer( Specialize & spec ) : spec( spec ), env( spec.env ), stmtsToAdd( spec.stmtsToAdd ) {} 55 virtual bool needsSpecialization( Type * formalType, Type * actualType, TypeSubstitution * env ) = 0; 56 virtual Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) = 0; 57 virtual Expression *doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams = 0 ); 58 59 protected: 60 Specialize & spec; 61 std::string paramPrefix = "_p"; 62 TypeSubstitution *& env; 63 std::list< Statement * > & stmtsToAdd; 64 }; 65 66 // for normal polymorphic -> monomorphic function conversion 67 class PolySpecializer : public Specializer { 68 public: 69 PolySpecializer( Specialize & spec ) : Specializer( spec ) {} 70 virtual bool needsSpecialization( Type * formalType, Type * actualType, TypeSubstitution * env ) override; 71 virtual Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) override; 72 }; 73 74 // // for tuple -> non-tuple function conversion 75 class TupleSpecializer : public Specializer { 76 public: 77 TupleSpecializer( Specialize & spec ) : Specializer( spec ) {} 78 virtual bool needsSpecialization( Type * formalType, Type * actualType, TypeSubstitution * env ) override; 79 virtual Expression *createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) override; 80 }; 67 81 68 82 /// Looks up open variables in actual type, returning true if any of them are bound in the environment or formal type. 69 bool needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {83 bool PolySpecializer::needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) { 70 84 if ( env ) { 71 85 using namespace ResolvExpr; … … 92 106 93 107 /// Generates a thunk that calls `actual` with type `funType` and returns its address 94 Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) { 108 Expression * PolySpecializer::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) { 109 static UniqueName thunkNamer( "_thunk" ); 110 95 111 FunctionType *newType = funType->clone(); 96 112 if ( env ) { … … 125 141 std::list< Statement* > oldStmts; 126 142 oldStmts.splice( oldStmts.end(), stmtsToAdd ); 127 handleExplicitParams( appExpr );143 spec.handleExplicitParams( appExpr ); 128 144 paramPrefix = oldParamPrefix; 129 145 // write any statements added for recursive specializations into the thunk body … … 147 163 } 148 164 149 Expression * Specialize ::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {165 Expression * Specializer::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) { 150 166 assertf( actual->has_result(), "attempting to specialize an untyped expression" ); 151 167 if ( needsSpecialization( formalType, actual->get_result(), env ) ) { … … 170 186 } 171 187 188 bool TupleSpecializer::needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) { 189 // std::cerr << "asking if type needs tuple spec: " << formalType << std::endl; 190 if ( FunctionType * ftype = getFunctionType( formalType ) ) { 191 return ftype->isTtype(); 192 } 193 return false; 194 } 195 196 template< typename Iterator > 197 void fixLastArg( std::list< Expression * > & args, Iterator begin, Iterator end ) { 198 assertf( ! args.empty(), "Somehow args to tuple function are empty" ); // xxx - it's quite possible this will trigger for the nullary case... 199 Expression * last = args.back(); 200 // safe_dynamic_cast for the assertion 201 safe_dynamic_cast< TupleType * >( last->get_result() ); // xxx - it's quite possible this will trigger for the unary case... 202 args.pop_back(); // replace last argument in the call with 203 unsigned idx = 0; 204 for ( ; begin != end; ++begin ) { 205 // DeclarationWithType * formal = *begin; 206 // Type * formalType = formal->get_type(); 207 args.push_back( new TupleIndexExpr( last->clone(), idx++ ) ); 208 } 209 delete last; 210 } 211 212 Expression * TupleSpecializer::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) { 213 static UniqueName thunkNamer( "_tupleThunk" ); 214 // std::cerr << "creating tuple thunk for " << funType << std::endl; 215 216 FunctionType *newType = funType->clone(); 217 if ( env ) { 218 TypeSubstitution newEnv( *env ); 219 // it is important to replace only occurrences of type variables that occur free in the 220 // thunk's type 221 newEnv.applyFree( newType ); 222 } // if 223 // create new thunk with same signature as formal type (C linkage, empty body) 224 FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, newType, new CompoundStmt( noLabels ), false, false ); 225 thunkFunc->fixUniqueId(); 226 227 // thunks may be generated and not used - silence warning with attribute 228 thunkFunc->get_attributes().push_back( new Attribute( "unused" ) ); 229 230 // thread thunk parameters into call to actual function, naming thunk parameters as we go 231 UniqueName paramNamer( paramPrefix ); 232 ApplicationExpr *appExpr = new ApplicationExpr( actual ); 233 // std::cerr << actual << std::endl; 234 235 FunctionType * actualType = getFunctionType( actual->get_result() ); 236 std::list< DeclarationWithType * >::iterator begin = actualType->get_parameters().begin(); 237 std::list< DeclarationWithType * >::iterator end = actualType->get_parameters().end(); 238 239 for ( DeclarationWithType* param : thunkFunc->get_functionType()->get_parameters() ) { 240 ++begin; 241 assert( begin != end ); 242 243 // std::cerr << "thunk param: " << param << std::endl; 244 // last param will always be a tuple type... expand it into the actual type(?) 245 param->set_name( paramNamer.newName() ); 246 appExpr->get_args().push_back( new VariableExpr( param ) ); 247 } // for 248 fixLastArg( appExpr->get_args(), --begin, end ); 249 appExpr->set_env( maybeClone( env ) ); 250 if ( inferParams ) { 251 appExpr->get_inferParams() = *inferParams; 252 } // if 253 254 // handle any specializations that may still be present 255 std::string oldParamPrefix = paramPrefix; 256 paramPrefix += "p"; 257 // save stmtsToAdd in oldStmts 258 std::list< Statement* > oldStmts; 259 oldStmts.splice( oldStmts.end(), stmtsToAdd ); 260 spec.handleExplicitParams( appExpr ); 261 paramPrefix = oldParamPrefix; 262 // write any statements added for recursive specializations into the thunk body 263 thunkFunc->get_statements()->get_kids().splice( thunkFunc->get_statements()->get_kids().end(), stmtsToAdd ); 264 // restore oldStmts into stmtsToAdd 265 stmtsToAdd.splice( stmtsToAdd.end(), oldStmts ); 266 267 // add return (or valueless expression) to the thunk 268 Statement *appStmt; 269 if ( funType->get_returnVals().empty() ) { 270 appStmt = new ExprStmt( noLabels, appExpr ); 271 } else { 272 appStmt = new ReturnStmt( noLabels, appExpr ); 273 } // if 274 thunkFunc->get_statements()->get_kids().push_back( appStmt ); 275 276 // std::cerr << "thunkFunc is: " << thunkFunc << std::endl; 277 278 // add thunk definition to queue of statements to add 279 stmtsToAdd.push_back( new DeclStmt( noLabels, thunkFunc ) ); 280 // return address of thunk function as replacement expression 281 return new AddressExpr( new VariableExpr( thunkFunc ) ); 282 } 283 172 284 void Specialize::handleExplicitParams( ApplicationExpr *appExpr ) { 173 285 // create thunks for the explicit parameters … … 178 290 std::list< Expression* >::iterator actual; 179 291 for ( formal = function->get_parameters().begin(), actual = appExpr->get_args().begin(); formal != function->get_parameters().end() && actual != appExpr->get_args().end(); ++formal, ++actual ) { 180 *actual = doSpecialization( (*formal )->get_type(), *actual, &appExpr->get_inferParams() );292 *actual = specializer->doSpecialization( (*formal )->get_type(), *actual, &appExpr->get_inferParams() ); 181 293 } 182 294 } … … 190 302 // don't need to do this for intrinsic calls, because they aren't actually passed 191 303 for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) { 192 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );304 inferParam->second.expr = specializer->doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() ); 193 305 } 194 195 306 handleExplicitParams( appExpr ); 196 307 } 197 198 308 return appExpr; 199 309 } … … 202 312 addrExpr->get_arg()->acceptMutator( *this ); 203 313 assert( addrExpr->has_result() ); 204 addrExpr->set_arg( doSpecialization( addrExpr->get_result(), addrExpr->get_arg() ) );314 addrExpr->set_arg( specializer->doSpecialization( addrExpr->get_result(), addrExpr->get_arg() ) ); 205 315 return addrExpr; 206 316 } … … 212 322 return castExpr; 213 323 } 214 Expression *specialized = doSpecialization( castExpr->get_result(), castExpr->get_arg() );324 Expression *specialized = specializer->doSpecialization( castExpr->get_result(), castExpr->get_arg() ); 215 325 if ( specialized != castExpr->get_arg() ) { 216 326 // assume here that the specialization incorporates the cast … … 236 346 // return commaExpr; 237 347 // } 348 349 void convertSpecializations( std::list< Declaration* >& translationUnit ) { 350 Specialize spec; 351 352 TupleSpecializer tupleSpec( spec ); 353 spec.specializer = &tupleSpec; 354 mutateAll( translationUnit, spec ); 355 356 PolySpecializer polySpec( spec ); 357 spec.specializer = &polySpec; 358 mutateAll( translationUnit, spec ); 359 } 238 360 } // namespace GenPoly 239 361 -
TabularUnified src/main.cc ¶
re33f321 r626dbc10 69 69 symtabp = false, 70 70 treep = false, 71 tuplep = false, 71 72 validp = false, 72 73 errorp = false, … … 266 267 OPTPRINT( "expandUniqueExpr" ); // xxx - is this the right place for this? want to expand ASAP so that subsequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused 267 268 Tuples::expandUniqueExpr( translationUnit ); 269 270 OPTPRINT( "convertSpecializations" ) // needs to happen before tuple types are expanded 271 GenPoly::convertSpecializations( translationUnit ); 272 268 273 OPTPRINT( "expandTuples" ); // xxx - is this the right place for this? 269 274 Tuples::expandTuples( translationUnit ); 275 if ( tuplep ) { 276 dump( translationUnit ); 277 return 0; 278 } 270 279 271 280 OPTPRINT("instantiateGenerics") … … 273 282 OPTPRINT( "copyParams" ); 274 283 GenPoly::copyParams( translationUnit ); 275 OPTPRINT( "convertSpecializations" )276 GenPoly::convertSpecializations( translationUnit );277 284 OPTPRINT( "convertLvalue" ) 278 285 GenPoly::convertLvalue( translationUnit ); … … 327 334 328 335 void parse_cmdline( int argc, char * argv[], const char *& filename ) { 329 enum { Ast, Bbox, Bresolver, CtorInitFix, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, };336 enum { Ast, Bbox, Bresolver, CtorInitFix, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, TupleExpansion, Validate, }; 330 337 331 338 static struct option long_opts[] = { … … 344 351 { "symbol", no_argument, 0, Symbol }, 345 352 { "tree", no_argument, 0, Tree }, 353 { "tuple-expansion", no_argument, 0, TupleExpansion }, 346 354 { "validate", no_argument, 0, Validate }, 347 355 { 0, 0, 0, 0 } … … 352 360 353 361 int c; 354 while ( (c = getopt_long( argc, argv, "abBcefglnpqrst vyzD:F:", long_opts, &long_index )) != -1 ) {362 while ( (c = getopt_long( argc, argv, "abBcefglnpqrstTvyzD:F:", long_opts, &long_index )) != -1 ) { 355 363 switch ( c ) { 356 364 case Ast: … … 362 370 bresolvep = true; 363 371 break; 364 case 'B': // print before resolversteps372 case 'B': // print before box steps 365 373 bboxp = true; 366 374 break; … … 408 416 case 't': // build in tree 409 417 treep = true; 418 break; 419 case TupleExpansion: 420 case 'T': // print after tuple expansion 421 tuplep = true; 410 422 break; 411 423 case 'v': // dump AST after decl validation pass
Note: See TracChangeset
for help on using the changeset viewer.