Changeset c6b4432 for src/GenPoly
- Timestamp:
- Nov 8, 2023, 2:01:11 PM (23 months ago)
- Branches:
- master
- Children:
- 3e4bf0d, f5ec35a
- Parents:
- 790d835
- Location:
- src/GenPoly
- Files:
-
- 4 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/FindFunction.cc
r790d835 rc6b4432 20 20 #include "AST/Pass.hpp" // for Pass 21 21 #include "AST/Type.hpp" 22 #include "Common/PassVisitor.h" // for PassVisitor23 22 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::iterator 24 23 #include "GenPoly/GenPoly.h" // for TyVarMap 25 24 #include "ScrubTyVars.h" // for ScrubTyVars 26 #include "SynTree/Declaration.h" // for DeclarationWithType, TypeDecl27 #include "SynTree/Mutator.h" // for Mutator, mutateAll28 #include "SynTree/Type.h" // for FunctionType, Type, Type::For...29 25 30 26 namespace GenPoly { 31 class FindFunction : public WithGuards, public WithVisitorRef<FindFunction>, public WithShortCircuiting {32 public:33 FindFunction( std::list< FunctionType const* > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate );34 35 void premutate( FunctionType * functionType );36 Type * postmutate( FunctionType * functionType );37 void premutate( PointerType * pointerType );38 private:39 void handleForall( const Type::ForallList &forall );40 41 std::list< FunctionType const * > & functions;42 TyVarMap tyVars;43 bool replaceMode;44 FindFunctionPredicate predicate;45 };46 47 void findFunction( Type *type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {48 PassVisitor<FindFunction> finder( functions, tyVars, false, predicate );49 type->acceptMutator( finder );50 }51 52 void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {53 PassVisitor<FindFunction> finder( functions, tyVars, true, predicate );54 type = type->acceptMutator( finder );55 }56 57 FindFunction::FindFunction( std::list< FunctionType const * > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate )58 : functions( functions ), tyVars( tyVars ), replaceMode( replaceMode ), predicate( predicate ) {59 }60 61 void FindFunction::handleForall( const Type::ForallList &forall ) {62 for ( const Declaration * td : forall ) {63 TyVarMap::iterator var = tyVars.find( td->name );64 if ( var != tyVars.end() ) {65 tyVars.erase( var->first );66 } // if67 } // for68 }69 70 void FindFunction::premutate( FunctionType * functionType ) {71 visit_children = false;72 GuardScope( tyVars );73 handleForall( functionType->get_forall() );74 mutateAll( functionType->get_returnVals(), *visitor );75 }76 77 Type * FindFunction::postmutate( FunctionType * functionType ) {78 Type *ret = functionType;79 if ( predicate( functionType, tyVars ) ) {80 functions.push_back( functionType );81 if ( replaceMode ) {82 // replace type parameters in function type with void*83 ret = ScrubTyVars::scrub( functionType->clone(), tyVars );84 } // if85 } // if86 return ret;87 }88 89 void FindFunction::premutate( PointerType * pointerType ) {90 GuardScope( tyVars );91 handleForall( pointerType->get_forall() );92 }93 27 94 28 namespace { … … 154 88 void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) { 155 89 GuardScope( typeVars ); 156 //handleForall( type->forall );157 90 } 158 91 … … 164 97 ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, false ); 165 98 type->accept( pass ); 166 //(void)type;167 //(void)functions;168 //(void)typeVars;169 //(void)predicate;170 99 } 171 100 … … 175 104 ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, true ); 176 105 return type->accept( pass ); 177 //(void)functions;178 //(void)typeVars;179 //(void)predicate;180 //return type;181 106 } 182 107 -
src/GenPoly/FindFunction.h
r790d835 rc6b4432 16 16 #pragma once 17 17 18 #include <list> // for list19 20 18 #include "GenPoly.h" // for TyVarMap 21 19 22 class FunctionType;23 class Type;24 25 20 namespace GenPoly { 26 typedef bool (*FindFunctionPredicate)( FunctionType*, const TyVarMap& );27 28 /// recursively walk `type`, placing all functions that match `predicate` under `tyVars` into `functions`29 void findFunction( Type *type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );30 /// like `findFunction`, but also replaces the function type with void ()(void)31 void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );32 21 33 22 typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & ); -
src/GenPoly/GenPoly.cc
r790d835 rc6b4432 29 29 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::const_it... 30 30 #include "ResolvExpr/typeops.h" // for flatten 31 #include "SynTree/Constant.h" // for Constant32 #include "SynTree/Expression.h" // for Expression, TypeExpr, Constan...33 #include "SynTree/Type.h" // for Type, StructInstType, UnionIn...34 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution35 31 36 32 using namespace std; … … 39 35 namespace { 40 36 /// Checks a parameter list for polymorphic parameters; will substitute according to env if present 41 bool hasPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {42 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {43 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );44 assertf(paramType, "Aggregate parameters should be type expressions");45 if ( isPolyType( paramType->get_type(), env ) ) return true;46 }47 return false;48 }49 50 37 bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env ) { 51 38 for ( auto ¶m : params ) { … … 58 45 59 46 /// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present 60 bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {61 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {62 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );63 assertf(paramType, "Aggregate parameters should be type expressions");64 if ( isPolyType( paramType->get_type(), tyVars, env ) ) return true;65 }66 return false;67 }68 69 47 bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TypeVarMap & typeVars, const ast::TypeSubstitution * env ) { 70 48 for ( auto & param : params ) { … … 77 55 78 56 /// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present 79 bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {80 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {81 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );82 assertf(paramType, "Aggregate parameters should be type expressions");83 if ( isDynType( paramType->get_type(), tyVars, env ) ) return true;84 }85 return false;86 }87 88 57 bool hasDynParams( 89 58 const std::vector<ast::ptr<ast::Expr>> & params, … … 99 68 return false; 100 69 } 101 102 /// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present103 bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {104 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {105 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );106 assertf(paramType, "Aggregate parameters should be type expressions");107 if ( includesPolyType( paramType->get_type(), env ) ) return true;108 }109 return false;110 }111 112 /// Checks a parameter list for inclusion of polymorphic parameters from tyVars; will substitute according to env if present113 bool includesPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {114 for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {115 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );116 assertf(paramType, "Aggregate parameters should be type expressions");117 if ( includesPolyType( paramType->get_type(), tyVars, env ) ) return true;118 }119 return false;120 }121 }122 123 Type* replaceTypeInst( Type* type, const TypeSubstitution* env ) {124 if ( ! env ) return type;125 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {126 Type *newType = env->lookup( typeInst->get_name() );127 if ( newType ) return newType;128 }129 return type;130 }131 132 const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env ) {133 if ( ! env ) return type;134 if ( auto typeInst = dynamic_cast< const TypeInstType* >( type ) ) {135 Type *newType = env->lookup( typeInst->get_name() );136 if ( newType ) return newType;137 }138 return type;139 70 } 140 71 … … 146 77 } 147 78 return type; 148 }149 150 Type *isPolyType( Type *type, const TypeSubstitution *env ) {151 type = replaceTypeInst( type, env );152 153 if ( dynamic_cast< TypeInstType * >( type ) ) {154 return type;155 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {156 return isPolyType( arrayType->base, env );157 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {158 if ( hasPolyParams( structType->get_parameters(), env ) ) return type;159 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {160 if ( hasPolyParams( unionType->get_parameters(), env ) ) return type;161 }162 return 0;163 79 } 164 80 … … 178 94 } 179 95 180 Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {181 type = replaceTypeInst( type, env );182 183 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {184 if ( tyVars.contains( typeInst->get_name() ) ) {185 return type;186 }187 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {188 return isPolyType( arrayType->base, tyVars, env );189 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {190 if ( hasPolyParams( structType->get_parameters(), tyVars, env ) ) return type;191 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {192 if ( hasPolyParams( unionType->get_parameters(), tyVars, env ) ) return type;193 }194 return 0;195 }196 197 96 const ast::Type * isPolyType( const ast::Type * type, 198 97 const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ) { … … 211 110 } 212 111 213 ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {214 type = replaceTypeInst( type, env );215 216 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {217 auto var = tyVars.find( typeInst->get_name() );218 if ( var != tyVars.end() && var->second.isComplete ) {219 return typeInst;220 }221 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {222 if ( hasDynParams( structType->get_parameters(), tyVars, env ) ) return structType;223 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {224 if ( hasDynParams( unionType->get_parameters(), tyVars, env ) ) return unionType;225 }226 return 0;227 }228 229 112 const ast::BaseInstType * isDynType( 230 113 const ast::Type * type, const TypeVarMap & typeVars, … … 249 132 } 250 133 251 ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &forallTypes ) {252 if ( function->get_returnVals().empty() ) return 0;253 254 return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );255 }256 257 134 const ast::BaseInstType *isDynRet( 258 135 const ast::FunctionType * type, const TypeVarMap & typeVars ) { … … 262 139 } 263 140 264 ReferenceToType *isDynRet( FunctionType *function ) {265 if ( function->get_returnVals().empty() ) return 0;266 267 TyVarMap forallTypes( TypeDecl::Data{} );268 makeTyVarMap( function, forallTypes );269 return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );270 }271 272 141 const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) { 273 142 if ( func->returns.empty() ) return nullptr; … … 278 147 } 279 148 280 bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {281 // if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {282 // return true;283 // } // if284 if ( isDynRet( adaptee, tyVars ) ) return true;285 286 for ( std::list< DeclarationWithType* >::const_iterator innerArg = adaptee->get_parameters().begin(); innerArg != adaptee->get_parameters().end(); ++innerArg ) {287 // if ( isPolyType( (*innerArg)->get_type(), tyVars ) ) {288 if ( isDynType( (*innerArg)->get_type(), tyVars ) ) {289 return true;290 } // if291 } // for292 return false;293 }294 295 149 bool needsAdapter( 296 150 ast::FunctionType const * adaptee, const TypeVarMap & typeVars ) { … … 304 158 return false; 305 159 } 306 307 Type *isPolyPtr( Type *type, const TypeSubstitution *env ) {308 type = replaceTypeInst( type, env );309 310 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {311 return isPolyType( ptr->get_base(), env );312 }313 return 0;314 }315 316 Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {317 type = replaceTypeInst( type, env );318 319 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {320 return isPolyType( ptr->get_base(), tyVars, env );321 }322 return 0;323 }324 160 325 161 const ast::Type * isPolyPtr( … … 333 169 return nullptr; 334 170 } 335 336 Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {337 int dummy;338 if ( ! levels ) { levels = &dummy; }339 *levels = 0;340 341 while ( true ) {342 type = replaceTypeInst( type, env );343 344 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {345 type = ptr->get_base();346 ++(*levels);347 } else break;348 }349 350 return isPolyType( type, env );351 }352 353 Type * hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels, const TypeSubstitution *env ) {354 int dummy;355 if ( ! levels ) { levels = &dummy; }356 *levels = 0;357 358 while ( true ) {359 type = replaceTypeInst( type, env );360 361 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {362 type = ptr->get_base();363 ++(*levels);364 } else break;365 }366 367 return isPolyType( type, tyVars, env );368 }369 171 370 172 ast::Type const * hasPolyBase( … … 388 190 } 389 191 390 bool includesPolyType( Type *type, const TypeSubstitution *env ) {391 type = replaceTypeInst( type, env );392 393 if ( dynamic_cast< TypeInstType * >( type ) ) {394 return true;395 } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {396 if ( includesPolyType( pointerType->get_base(), env ) ) return true;397 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {398 if ( includesPolyParams( structType->get_parameters(), env ) ) return true;399 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {400 if ( includesPolyParams( unionType->get_parameters(), env ) ) return true;401 }402 return false;403 }404 405 bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {406 type = replaceTypeInst( type, env );407 408 if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {409 if ( tyVars.contains( typeInstType->get_name() ) ) {410 return true;411 }412 } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {413 if ( includesPolyType( pointerType->get_base(), tyVars, env ) ) return true;414 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {415 if ( includesPolyParams( structType->get_parameters(), tyVars, env ) ) return true;416 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {417 if ( includesPolyParams( unionType->get_parameters(), tyVars, env ) ) return true;418 }419 return false;420 }421 422 FunctionType * getFunctionType( Type *ty ) {423 PointerType *ptrType;424 if ( ( ptrType = dynamic_cast< PointerType* >( ty ) ) ) {425 return dynamic_cast< FunctionType* >( ptrType->get_base() ); // pointer if FunctionType, NULL otherwise426 } else {427 return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise428 }429 }430 431 192 const ast::FunctionType * getFunctionType( const ast::Type * ty ) { 432 193 if ( auto pty = dynamic_cast< const ast::PointerType * >( ty ) ) { … … 437 198 } 438 199 439 VariableExpr * getBaseVar( Expression *expr, int *levels ) {440 int dummy;441 if ( ! levels ) { levels = &dummy; }442 *levels = 0;443 444 while ( true ) {445 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( expr ) ) {446 return varExpr;447 } else if ( MemberExpr *memberExpr = dynamic_cast< MemberExpr* >( expr ) ) {448 expr = memberExpr->get_aggregate();449 } else if ( AddressExpr *addressExpr = dynamic_cast< AddressExpr* >( expr ) ) {450 expr = addressExpr->get_arg();451 } else if ( UntypedExpr *untypedExpr = dynamic_cast< UntypedExpr* >( expr ) ) {452 // look for compiler-inserted dereference operator453 NameExpr *fn = dynamic_cast< NameExpr* >( untypedExpr->get_function() );454 if ( ! fn || fn->get_name() != std::string("*?") ) return 0;455 expr = *untypedExpr->begin_args();456 } else if ( CommaExpr *commaExpr = dynamic_cast< CommaExpr* >( expr ) ) {457 // copy constructors insert comma exprs, look at second argument which contains the variable458 expr = commaExpr->get_arg2();459 continue;460 } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( expr ) ) {461 int lvl1;462 int lvl2;463 VariableExpr * var1 = getBaseVar( condExpr->get_arg2(), &lvl1 );464 VariableExpr * var2 = getBaseVar( condExpr->get_arg3(), &lvl2 );465 if ( lvl1 == lvl2 && var1 && var2 && var1->get_var() == var2->get_var() ) {466 *levels = lvl1;467 return var1;468 }469 break;470 } else break;471 472 ++(*levels);473 }474 475 return 0;476 }477 478 200 namespace { 479 201 /// Checks if is a pointer to D … … 488 210 inline D const * as( B const * p ) { 489 211 return reinterpret_cast<D const *>( p ); 490 }491 492 /// Flattens a declaration list493 template<typename Output>494 void flattenList( list< DeclarationWithType* > src, Output out ) {495 for ( DeclarationWithType* decl : src ) {496 ResolvExpr::flatten( decl->get_type(), out );497 }498 }499 500 /// Flattens a list of types501 template<typename Output>502 void flattenList( list< Type* > src, Output out ) {503 for ( Type* ty : src ) {504 ResolvExpr::flatten( ty, out );505 }506 212 } 507 213 … … 515 221 } 516 222 517 /// Checks if two lists of parameters are equal up to polymorphic substitution.518 bool paramListsPolyCompatible( const list< Expression* >& aparams, const list< Expression* >& bparams ) {519 if ( aparams.size() != bparams.size() ) return false;520 521 for ( list< Expression* >::const_iterator at = aparams.begin(), bt = bparams.begin();522 at != aparams.end(); ++at, ++bt ) {523 TypeExpr *aparam = dynamic_cast< TypeExpr* >(*at);524 assertf(aparam, "Aggregate parameters should be type expressions");525 TypeExpr *bparam = dynamic_cast< TypeExpr* >(*bt);526 assertf(bparam, "Aggregate parameters should be type expressions");527 528 // xxx - might need to let VoidType be a wildcard here too; could have some voids529 // stuffed in for dtype-statics.530 // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;531 if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false;532 }533 534 return true;535 }536 537 223 bool paramListsPolyCompatible( 538 224 std::vector<ast::ptr<ast::Expr>> const & lparams, … … 559 245 return true; 560 246 } 561 }562 563 bool typesPolyCompatible( Type *a, Type *b ) {564 type_index aid{ typeid(*a) };565 // polymorphic types always match566 if ( aid == type_index{typeid(TypeInstType)} ) return true;567 568 type_index bid{ typeid(*b) };569 // polymorphic types always match570 if ( bid == type_index{typeid(TypeInstType)} ) return true;571 572 // can't match otherwise if different types573 if ( aid != bid ) return false;574 575 // recurse through type structure (conditions borrowed from Unify.cc)576 if ( aid == type_index{typeid(BasicType)} ) {577 return as<BasicType>(a)->get_kind() == as<BasicType>(b)->get_kind();578 } else if ( aid == type_index{typeid(PointerType)} ) {579 PointerType *ap = as<PointerType>(a), *bp = as<PointerType>(b);580 581 // void pointers should match any other pointer type582 return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )583 || typesPolyCompatible( ap->get_base(), bp->get_base() );584 } else if ( aid == type_index{typeid(ReferenceType)} ) {585 ReferenceType *ap = as<ReferenceType>(a), *bp = as<ReferenceType>(b);586 return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )587 || typesPolyCompatible( ap->get_base(), bp->get_base() );588 } else if ( aid == type_index{typeid(ArrayType)} ) {589 ArrayType *aa = as<ArrayType>(a), *ba = as<ArrayType>(b);590 591 if ( aa->get_isVarLen() ) {592 if ( ! ba->get_isVarLen() ) return false;593 } else {594 if ( ba->get_isVarLen() ) return false;595 596 ConstantExpr *ad = dynamic_cast<ConstantExpr*>( aa->get_dimension() );597 ConstantExpr *bd = dynamic_cast<ConstantExpr*>( ba->get_dimension() );598 if ( ad && bd599 && ad->get_constant()->get_value() != bd->get_constant()->get_value() )600 return false;601 }602 603 return typesPolyCompatible( aa->get_base(), ba->get_base() );604 } else if ( aid == type_index{typeid(FunctionType)} ) {605 FunctionType *af = as<FunctionType>(a), *bf = as<FunctionType>(b);606 607 vector<Type*> aparams, bparams;608 flattenList( af->get_parameters(), back_inserter( aparams ) );609 flattenList( bf->get_parameters(), back_inserter( bparams ) );610 if ( aparams.size() != bparams.size() ) return false;611 612 vector<Type*> areturns, breturns;613 flattenList( af->get_returnVals(), back_inserter( areturns ) );614 flattenList( bf->get_returnVals(), back_inserter( breturns ) );615 if ( areturns.size() != breturns.size() ) return false;616 617 for ( unsigned i = 0; i < aparams.size(); ++i ) {618 if ( ! typesPolyCompatible( aparams[i], bparams[i] ) ) return false;619 }620 for ( unsigned i = 0; i < areturns.size(); ++i ) {621 if ( ! typesPolyCompatible( areturns[i], breturns[i] ) ) return false;622 }623 return true;624 } else if ( aid == type_index{typeid(StructInstType)} ) {625 StructInstType *aa = as<StructInstType>(a), *ba = as<StructInstType>(b);626 627 if ( aa->get_name() != ba->get_name() ) return false;628 return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );629 } else if ( aid == type_index{typeid(UnionInstType)} ) {630 UnionInstType *aa = as<UnionInstType>(a), *ba = as<UnionInstType>(b);631 632 if ( aa->get_name() != ba->get_name() ) return false;633 return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );634 } else if ( aid == type_index{typeid(EnumInstType)} ) {635 return as<EnumInstType>(a)->get_name() == as<EnumInstType>(b)->get_name();636 } else if ( aid == type_index{typeid(TraitInstType)} ) {637 return as<TraitInstType>(a)->get_name() == as<TraitInstType>(b)->get_name();638 } else if ( aid == type_index{typeid(TupleType)} ) {639 TupleType *at = as<TupleType>(a), *bt = as<TupleType>(b);640 641 vector<Type*> atypes, btypes;642 flattenList( at->get_types(), back_inserter( atypes ) );643 flattenList( bt->get_types(), back_inserter( btypes ) );644 if ( atypes.size() != btypes.size() ) return false;645 646 for ( unsigned i = 0; i < atypes.size(); ++i ) {647 if ( ! typesPolyCompatible( atypes[i], btypes[i] ) ) return false;648 }649 return true;650 } else return true; // VoidType, VarArgsType, ZeroType & OneType just need the same type651 247 } 652 248 … … 763 359 } 764 360 765 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {766 // is parameter is not polymorphic, don't need to box767 if ( ! isPolyType( param, exprTyVars ) ) return false;768 Type * newType = arg->clone();769 if ( env ) env->apply( newType );770 std::unique_ptr<Type> manager( newType );771 // if the argument's type is polymorphic, we don't need to box again!772 return ! isPolyType( newType );773 }774 775 361 bool needsBoxing( const ast::Type * param, const ast::Type * arg, 776 362 const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ) { … … 786 372 return !isPolyType( newType ); 787 373 } 788 789 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {790 FunctionType * function = getFunctionType( appExpr->function->result );791 assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );792 TyVarMap exprTyVars( TypeDecl::Data{} );793 makeTyVarMap( function, exprTyVars );794 return needsBoxing( param, arg, exprTyVars, env );795 }796 374 797 375 bool needsBoxing( … … 806 384 } 807 385 808 void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {809 tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } );810 }811 812 386 void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) { 813 387 typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) ); … … 817 391 typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) ); 818 392 } 819 820 void makeTyVarMap( Type *type, TyVarMap &tyVarMap ) {821 for ( Type::ForallList::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {822 assert( *tyVar );823 addToTyVarMap( *tyVar, tyVarMap );824 }825 if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {826 makeTyVarMap( pointer->get_base(), tyVarMap );827 }828 }829 393 830 394 void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ) { … … 846 410 } 847 411 848 void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {849 for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {850 os << i->first << " (" << i->second << ") ";851 } // for852 os << std::endl;853 }854 855 412 } // namespace GenPoly 856 413 -
src/GenPoly/GenPoly.h
r790d835 rc6b4432 23 23 #include "AST/Fwd.hpp" // for ApplicationExpr, BaseInstType, Func... 24 24 #include "SymTab/Mangler.h" // for Mangler 25 #include "SynTree/Declaration.h" // for TypeDecl::Data, AggregateDecl, Type...26 #include "SynTree/SynTree.h" // for Visitor Nodes27 25 28 26 namespace ast { … … 32 30 namespace GenPoly { 33 31 34 typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;35 32 struct TypeVarMap : public ErasableScopedMap<ast::TypeEnvKey, ast::TypeData> { 36 33 TypeVarMap() : ErasableScopedMap( ast::TypeData() ) {} … … 38 35 39 36 /// Replaces a TypeInstType by its referrent in the environment, if applicable 40 Type* replaceTypeInst( Type* type, const TypeSubstitution* env );41 const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env );42 37 const ast::Type * replaceTypeInst( const ast::Type *, const ast::TypeSubstitution * ); 43 38 44 39 /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided 45 Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );46 40 const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env = nullptr); 47 41 48 42 /// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided 49 Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );50 43 const ast::Type * isPolyType( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst = nullptr ); 51 44 52 45 /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided 53 ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );54 46 const ast::BaseInstType *isDynType( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst = 0 ); 55 47 56 48 /// true iff function has dynamic-layout return type under the given type variable map 57 ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &tyVars );58 49 const ast::BaseInstType *isDynRet( const ast::FunctionType * type, const TypeVarMap & typeVars ); 59 50 60 51 /// true iff function has dynamic-layout return type under the type variable map generated from its forall-parameters 61 ReferenceToType *isDynRet( FunctionType *function );62 52 const ast::BaseInstType *isDynRet( const ast::FunctionType * func ); 63 53 64 54 /// A function needs an adapter if it returns a dynamic-layout value or if any of its parameters have dynamic-layout type 65 bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVarr );66 55 bool needsAdapter( ast::FunctionType const * adaptee, const TypeVarMap & typeVars ); 67 56 68 /// returns polymorphic type if is pointer to polymorphic type, NULL otherwise; will look up substitution in env if provided69 Type *isPolyPtr( Type *type, const TypeSubstitution *env = 0 );70 71 57 /// returns polymorphic type if is pointer to polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided 72 Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );73 58 const ast::Type * isPolyPtr( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * env = 0 ); 74 75 /// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type, returns the base type, NULL otherwise;76 /// N will be stored in levels, if provided, will look up substitution in env if provided77 Type *hasPolyBase( Type *type, int *levels = 0, const TypeSubstitution *env = 0 );78 59 79 60 /// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type in tyVars, returns the base type, NULL otherwise; 80 61 /// N will be stored in levels, if provided, will look up substitution in env if provided 81 Type *hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels = 0, const TypeSubstitution *env = 0 );82 62 const ast::Type * hasPolyBase( const ast::Type * type, const TypeVarMap & typeVars, int * levels = 0, const ast::TypeSubstitution * env = 0 ); 83 63 84 /// true iff this type or some base of this type after dereferencing pointers is either polymorphic or a generic type with at least one85 /// polymorphic parameter; will look up substitution in env if provided.86 bool includesPolyType( Type *type, const TypeSubstitution *env = 0 );87 88 /// true iff this type or some base of this type after dereferencing pointers is either polymorphic in tyVars, or a generic type with89 /// at least one polymorphic parameter in tyVars; will look up substitution in env if provided.90 bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );91 92 64 /// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise 93 FunctionType *getFunctionType( Type *ty );94 65 const ast::FunctionType * getFunctionType( const ast::Type * ty ); 95 66 96 /// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise;97 /// N will be stored in levels, if provided98 VariableExpr *getBaseVar( Expression *expr, int *levels = 0 );99 100 67 /// true iff types are structurally identical, where TypeInstType's match any type. 101 bool typesPolyCompatible( Type *aty, Type *bty );102 68 bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs ); 103 69 104 70 /// true if arg requires boxing given exprTyVars 105 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );106 71 bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ); 107 72 108 73 /// true if arg requires boxing in the call to appExpr 109 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );110 74 bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * expr, const ast::TypeSubstitution * subst ); 111 75 112 76 /// Adds the type variable `tyVar` to `tyVarMap` 113 void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );114 77 void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars ); 115 78 void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ); 116 79 117 80 /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap` 118 void makeTyVarMap( Type *type, TyVarMap &tyVarMap );119 81 void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ); 120 82 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ); 121 122 /// Prints type variable map123 void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );124 125 /// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().126 inline std::string mangleType( const Type *ty ) { return SymTab::Mangler::mangleType( ty ); }127 83 128 84 /// Gets the name of the sizeof parameter for the type, given its mangled name … … 136 92 137 93 /// Gets the name of the layout function for a given aggregate type, given its declaration 138 inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }139 94 inline std::string layoutofName( ast::AggregateDecl const * decl ) { 140 95 return std::string( "_layoutof_" ) + decl->name; -
src/GenPoly/ScrubTyVars.cc
r790d835 rc6b4432 21 21 #include "ScrubTyVars.h" 22 22 #include "SymTab/Mangler.h" // for mangleType 23 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data, Typ...24 #include "SynTree/Expression.h" // for Expression (ptr only), NameExpr25 #include "SynTree/Mutator.h" // for Mutator26 #include "SynTree/Type.h" // for PointerType, TypeInstType, Type27 23 28 24 namespace GenPoly { 29 Type * ScrubTyVars::postmutate( TypeInstType * typeInst ) {30 if ( ! tyVars ) {31 if ( typeInst->get_isFtype() ) {32 delete typeInst;33 return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );34 } else {35 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );36 delete typeInst;37 return ret;38 }39 }40 41 TyVarMap::const_iterator tyVar = tyVars->find( typeInst->name );42 if ( tyVar != tyVars->end() ) {43 switch ( tyVar->second.kind ) {44 case TypeDecl::Dtype:45 case TypeDecl::Ttype:46 {47 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );48 delete typeInst;49 return ret;50 }51 case TypeDecl::Ftype:52 delete typeInst;53 return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );54 default:55 assertf(false, "Unhandled tyvar kind: %d", tyVar->second.kind);56 } // switch57 } // if58 return typeInst;59 }60 61 Type * ScrubTyVars::mutateAggregateType( Type * ty ) {62 if ( shouldScrub( ty ) ) {63 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );64 delete ty;65 return ret;66 }67 return ty;68 }69 70 Type * ScrubTyVars::postmutate( StructInstType * structInst ) {71 return mutateAggregateType( structInst );72 }73 74 Type * ScrubTyVars::postmutate( UnionInstType * unionInst ) {75 return mutateAggregateType( unionInst );76 }77 78 void ScrubTyVars::primeBaseScrub( Type * type ) {79 // need to determine whether type needs to be scrubbed to determine whether80 // automatic recursion is necessary81 if ( Type * t = shouldScrub( type ) ) {82 visit_children = false;83 GuardValue( dynType );84 dynType = t;85 }86 }87 88 Expression * ScrubTyVars::postmutate( SizeofExpr * szeof ) {89 // sizeof( T ) => _sizeof_T parameter, which is the size of T90 if ( dynType ) {91 Expression *expr = new NameExpr( sizeofName( mangleType( dynType ) ) );92 return expr;93 } // if94 return szeof;95 }96 97 Expression * ScrubTyVars::postmutate( AlignofExpr * algnof ) {98 // alignof( T ) => _alignof_T parameter, which is the alignment of T99 if ( dynType ) {100 Expression *expr = new NameExpr( alignofName( mangleType( dynType ) ) );101 return expr;102 } // if103 return algnof;104 }105 106 Type * ScrubTyVars::postmutate( PointerType * pointer ) {107 if ( dynType ) {108 Type * ret = dynType->acceptMutator( *visitor );109 ret->get_qualifiers() |= pointer->get_qualifiers();110 pointer->base = nullptr;111 delete pointer;112 return ret;113 }114 return pointer;115 }116 25 117 26 namespace { -
src/GenPoly/ScrubTyVars.h
r790d835 rc6b4432 19 19 20 20 #include "AST/Fwd.hpp" // for Node 21 #include "Common/PassVisitor.h"22 21 #include "GenPoly.h" // for TyVarMap, isPolyType, isDynType 23 #include "SynTree/Mutator.h" // for Mutator24 #include "SynTree/Type.h" // for Type (ptr only), PointerType (ptr only)25 26 class AlignofExpr;27 class Expression;28 class SizeofExpr;29 22 30 23 namespace GenPoly { 31 struct ScrubTyVars : public WithVisitorRef<ScrubTyVars>, public WithShortCircuiting, public WithGuards {32 /// Whether to scrub all type variables from the provided map, dynamic type variables from the provided map, or all type variables33 enum ScrubMode { FromMap, DynamicFromMap, All };34 35 ScrubTyVars() : tyVars(nullptr), mode( All ) {}36 37 ScrubTyVars( const TyVarMap &tyVars, ScrubMode mode = FromMap ): tyVars( &tyVars ), mode( mode ) {}38 39 public:40 /// For all polymorphic types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,41 /// and sizeof/alignof expressions with the proper variable42 template< typename SynTreeClass >43 static SynTreeClass *scrub( SynTreeClass *target, const TyVarMap &tyVars );44 45 /// For all dynamic-layout types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,46 /// and sizeof/alignof expressions with the proper variable47 template< typename SynTreeClass >48 static SynTreeClass *scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars );49 50 /// For all polymorphic types, replaces generic types, dtypes, and ftypes with the appropriate void type,51 /// and sizeof/alignof expressions with the proper variable52 template< typename SynTreeClass >53 static SynTreeClass *scrubAll( SynTreeClass *target );54 55 /// determine if children should be visited based on whether base type should be scrubbed.56 void primeBaseScrub( Type * );57 58 void premutate( TypeInstType * ) { visit_children = false; }59 void premutate( StructInstType * ) { visit_children = false; }60 void premutate( UnionInstType * ) { visit_children = false; }61 void premutate( SizeofExpr * szeof ) { primeBaseScrub( szeof->type ); }62 void premutate( AlignofExpr * algnof ) { primeBaseScrub( algnof->type ); }63 void premutate( PointerType * pointer ) { primeBaseScrub( pointer->base ); }64 65 Type * postmutate( TypeInstType * typeInst );66 Type * postmutate( StructInstType * structInst );67 Type * postmutate( UnionInstType * unionInst );68 Expression * postmutate( SizeofExpr * szeof );69 Expression * postmutate( AlignofExpr * algnof );70 Type * postmutate( PointerType * pointer );71 72 private:73 /// Returns the type if it should be scrubbed, NULL otherwise.74 Type* shouldScrub( Type *ty ) {75 switch ( mode ) {76 case FromMap: return isPolyType( ty, *tyVars );77 case DynamicFromMap: return isDynType( ty, *tyVars );78 case All: return isPolyType( ty );79 }80 assert(false); return nullptr; // unreachable81 // return dynamicOnly ? isDynType( ty, tyVars ) : isPolyType( ty, tyVars );82 }83 84 /// Mutates (possibly generic) aggregate types appropriately85 Type* mutateAggregateType( Type *ty );86 87 const TyVarMap *tyVars; ///< Type variables to scrub88 ScrubMode mode; ///< which type variables to scrub? [FromMap]89 90 Type * dynType = nullptr; ///< result of shouldScrub91 };92 93 template< typename SynTreeClass >94 SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target, const TyVarMap &tyVars ) {95 PassVisitor<ScrubTyVars> scrubber( tyVars );96 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );97 }98 99 template< typename SynTreeClass >100 SynTreeClass * ScrubTyVars::scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars ) {101 PassVisitor<ScrubTyVars> scrubber( tyVars, ScrubTyVars::DynamicFromMap );102 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );103 }104 105 template< typename SynTreeClass >106 SynTreeClass * ScrubTyVars::scrubAll( SynTreeClass *target ) {107 PassVisitor<ScrubTyVars> scrubber;108 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );109 }110 24 111 25 // ScrubMode and scrubTypeVarsBase are internal. -
src/GenPoly/SpecializeNew.cpp
r790d835 rc6b4432 23 23 #include "GenPoly/GenPoly.h" // for getFunctionType 24 24 #include "ResolvExpr/FindOpenVars.h" // for findOpenVars 25 #include "ResolvExpr/TypeEnvironment.h" // for FirstOpen, FirstClosed26 25 27 26 namespace GenPoly { -
src/GenPoly/module.mk
r790d835 rc6b4432 23 23 SRC += $(SRC_GENPOLY) \ 24 24 GenPoly/BoxNew.cpp \ 25 GenPoly/Box.cc \26 25 GenPoly/Box.h \ 27 26 GenPoly/ErasableScopedMap.h \ … … 29 28 GenPoly/FindFunction.h \ 30 29 GenPoly/InstantiateGenericNew.cpp \ 31 GenPoly/InstantiateGeneric.cc \32 30 GenPoly/InstantiateGeneric.h \ 33 31 GenPoly/LvalueNew.cpp \ 34 GenPoly/Lvalue.cc \35 32 GenPoly/ScopedSet.h \ 36 33 GenPoly/ScrubTyVars.cc \ 37 34 GenPoly/ScrubTyVars.h \ 38 GenPoly/Specialize.cc \39 35 GenPoly/SpecializeNew.cpp \ 40 36 GenPoly/Specialize.h
Note:
See TracChangeset
for help on using the changeset viewer.