Changeset fc12f05 for src/GenPoly
- Timestamp:
- Nov 13, 2023, 3:43:43 AM (2 years ago)
- Branches:
- master
- Children:
- 25f2798
- Parents:
- 0030b508 (diff), 2174191 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src/GenPoly
- Files:
-
- 4 deleted
- 9 edited
-
Box.cc (deleted)
-
BoxNew.cpp (modified) (26 diffs)
-
FindFunction.cc (modified) (4 diffs)
-
FindFunction.h (modified) (1 diff)
-
GenPoly.cc (modified) (22 diffs)
-
GenPoly.h (modified) (3 diffs)
-
InstantiateGeneric.cc (deleted)
-
Lvalue.cc (deleted)
-
ScrubTyVars.cc (modified) (1 diff)
-
ScrubTyVars.h (modified) (1 diff)
-
Specialize.cc (deleted)
-
SpecializeNew.cpp (modified) (2 diffs)
-
module.mk (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/BoxNew.cpp
r0030b508 rfc12f05 39 39 40 40 namespace { 41 42 /// Common field of several sub-passes of box.43 struct BoxPass {44 TypeVarMap scopeTypeVars;45 BoxPass() : scopeTypeVars( ast::TypeData() ) {}46 };47 48 // TODO: Could this be a common helper somewhere?49 ast::FunctionType * makeFunctionType( ast::FunctionDecl const * decl ) {50 ast::FunctionType * type = new ast::FunctionType(51 decl->type->isVarArgs, decl->type->qualifiers52 );53 for ( auto type_param : decl->type_params ) {54 type->forall.emplace_back( new ast::TypeInstType( type_param ) );55 }56 for ( auto assertion : decl->assertions ) {57 type->assertions.emplace_back( new ast::VariableExpr(58 assertion->location, assertion ) );59 }60 for ( auto param : decl->params ) {61 type->params.emplace_back( param->get_type() );62 }63 for ( auto retval : decl->returns ) {64 type->returns.emplace_back( retval->get_type() );65 }66 return type;67 }68 41 69 42 // -------------------------------------------------------------------------- … … 359 332 /// * Adds appropriate type variables to the function calls. 360 333 struct CallAdapter final : 361 public BoxPass,362 334 public ast::WithConstTypeSubstitution, 363 335 public ast::WithGuards, … … 376 348 ast::Expr const * postvisit( ast::AddressExpr const * expr ); 377 349 ast::ReturnStmt const * previsit( ast::ReturnStmt const * stmt ); 378 void previsit( ast::PointerType const * type );379 void previsit( ast::FunctionType const * type );380 350 381 351 void beginScope(); … … 440 410 CodeLocation const & location, ast::Type const * type ); 441 411 442 /// Set of adapter functions in the current scope.412 TypeVarMap scopeTypeVars; 443 413 ScopedMap< std::string, ast::DeclWithType const * > adapters; 444 414 std::map< ast::ApplicationExpr const *, ast::Expr const * > retVals; … … 553 523 554 524 ast::FunctionDecl const * CallAdapter::previsit( ast::FunctionDecl const * decl ) { 525 // Prevent type declaration information from leaking out. 526 GuardScope( scopeTypeVars ); 527 555 528 if ( nullptr == decl->stmts ) { 556 // This may keep TypeDecls we don't ever want from sneaking in.557 // Not visiting child nodes might just be faster.558 GuardScope( scopeTypeVars );559 529 return decl; 560 530 } 561 531 562 GuardScope( scopeTypeVars );563 532 GuardValue( retval ); 564 533 … … 662 631 ptrdiff_t initArgCount = mutExpr->args.size(); 663 632 664 TypeVarMap exprTypeVars = { ast::TypeData() };633 TypeVarMap exprTypeVars; 665 634 // TODO: Should this take into account the variables already bound in 666 635 // scopeTypeVars ([ex] remove them from exprTypeVars)? … … 687 656 688 657 assert( typeSubs ); 689 ast::Type const * concRetType = replaceWithConcrete( dynRetType, *typeSubs );690 // Used to use dynRetType instead of concRetType; this changed so that691 // the correct type parameters are passed for return types (it should be692 // the concrete type's parameters, not the formal type's).693 658 ast::vector<ast::Expr>::iterator argIt = 694 659 passTypeVars( mutExpr, function ); … … 768 733 } 769 734 return stmt; 770 }771 772 void CallAdapter::previsit( ast::PointerType const * type ) {773 GuardScope( scopeTypeVars );774 makeTypeVarMap( type, scopeTypeVars );775 }776 777 void CallAdapter::previsit( ast::FunctionType const * type ) {778 GuardScope( scopeTypeVars );779 makeTypeVarMap( type, scopeTypeVars );780 735 } 781 736 … … 1427 1382 1428 1383 ast::FunctionDecl const * DeclAdapter::previsit( ast::FunctionDecl const * decl ) { 1429 TypeVarMap localTypeVars = { ast::TypeData() };1384 TypeVarMap localTypeVars; 1430 1385 makeTypeVarMap( decl, localTypeVars ); 1431 1386 … … 1458 1413 layoutParams.emplace_back( alignParam ); 1459 1414 } 1460 // TODO: These should possibly all be gone. 1461 // More all assertions into parameter list. 1462 for ( ast::ptr<ast::DeclWithType> & assert : mutParam->assertions ) { 1463 // Assertion parameters may not be used in body, 1464 // pass along with unused attribute. 1465 assert.get_and_mutate()->attributes.push_back( 1466 new ast::Attribute( "unused" ) ); 1467 inferredParams.push_back( assert ); 1468 } 1469 mutParam->assertions.clear(); 1415 // Assertions should be stored in the main list. 1416 assert( mutParam->assertions.empty() ); 1470 1417 typeParam = mutParam; 1471 1418 } 1472 // TODO: New version of inner loop.1473 1419 for ( ast::ptr<ast::DeclWithType> & assert : mutDecl->assertions ) { 1474 1420 // Assertion parameters may not be used in body, … … 1485 1431 spliceBegin( mutDecl->params, layoutParams ); 1486 1432 addAdapters( mutDecl, localTypeVars ); 1433 1434 // Now have to update the type to match the declaration. 1435 ast::FunctionType * type = new ast::FunctionType( 1436 mutDecl->type->isVarArgs, mutDecl->type->qualifiers ); 1437 for ( auto type_param : mutDecl->type_params ) { 1438 type->forall.emplace_back( new ast::TypeInstType( type_param ) ); 1439 } 1440 for ( auto param : mutDecl->params ) { 1441 type->params.emplace_back( param->get_type() ); 1442 } 1443 for ( auto retval : mutDecl->returns ) { 1444 type->returns.emplace_back( retval->get_type() ); 1445 } 1446 mutDecl->type = type; 1487 1447 1488 1448 return mutDecl; … … 1518 1478 } 1519 1479 } 1520 // TODO: Can this be updated as we go along?1521 mutDecl->type = makeFunctionType( mutDecl );1522 1480 return mutDecl; 1523 1481 } … … 1575 1533 assertf( it != adapters.end(), "Could not correct floating node." ); 1576 1534 return ast::mutate_field( expr, &ast::VariableExpr::var, it->second ); 1577 1578 1535 } 1579 1536 … … 1587 1544 /// * Inserts dynamic calculation of polymorphic type layouts where needed. 1588 1545 struct PolyGenericCalculator final : 1589 public BoxPass,1590 1546 public ast::WithConstTypeSubstitution, 1591 1547 public ast::WithDeclsToAdd<>, … … 1595 1551 PolyGenericCalculator(); 1596 1552 1597 void previsit( ast::ObjectDecl const * decl );1598 1553 void previsit( ast::FunctionDecl const * decl ); 1599 1554 void previsit( ast::TypedefDecl const * decl ); … … 1602 1557 ast::StructDecl const * previsit( ast::StructDecl const * decl ); 1603 1558 ast::UnionDecl const * previsit( ast::UnionDecl const * decl ); 1604 void previsit( ast::PointerType const * type );1605 void previsit( ast::FunctionType const * type );1606 1559 ast::DeclStmt const * previsit( ast::DeclStmt const * stmt ); 1607 1560 ast::Expr const * postvisit( ast::MemberExpr const * expr ); … … 1635 1588 /// C sizeof(). 1636 1589 ast::Expr const * genSizeof( CodeLocation const &, ast::Type const * ); 1637 1638 1590 /// Enters a new scope for type-variables, 1639 1591 /// adding the type variables from the provided type. 1640 1592 void beginTypeScope( ast::Type const * ); 1641 /// Enters a new scope for known layouts and offsets, and queues exit calls. 1642 void beginGenericScope();1643 1593 1594 /// The type variables and polymorphic parameters currently in scope. 1595 TypeVarMap scopeTypeVars; 1644 1596 /// Set of generic type layouts known in the current scope, 1645 1597 /// indexed by sizeofName. … … 1652 1604 /// If the argument of an AddressExpr is MemberExpr, it is stored here. 1653 1605 ast::MemberExpr const * addrMember = nullptr; 1654 /// Used to avoid recursing too deep in type declarations.1655 bool expect_func_type = false;1656 1606 }; 1657 1607 … … 1675 1625 } 1676 1626 1677 void PolyGenericCalculator::previsit( ast::ObjectDecl const * decl ) {1678 beginTypeScope( decl->type );1679 }1680 1681 1627 void PolyGenericCalculator::previsit( ast::FunctionDecl const * decl ) { 1682 beginGenericScope();1628 GuardScope( *this ); 1683 1629 beginTypeScope( decl->type ); 1684 1630 } … … 1696 1642 ast::TypeDecl const * decl ) { 1697 1643 ast::Type const * base = decl->base; 1698 if ( nullptr == base ) return decl;1644 if ( nullptr == base ) return decl; 1699 1645 1700 1646 // Add size/align variables for opaque type declarations. … … 1721 1667 alignDecl->accept( *visitor ); 1722 1668 1723 // Can't use [makeVar], because it inserts into stmtsToAdd and TypeDecls1724 // can occur at global scope.1669 // A little trick to replace this with two declarations. 1670 // Adding after makes sure that there is no conflict with adding stmts. 1725 1671 declsToAddAfter.push_back( alignDecl ); 1726 // replace with sizeDecl.1727 1672 return sizeDecl; 1728 1673 } … … 1742 1687 } 1743 1688 1744 void PolyGenericCalculator::previsit( ast::PointerType const * type ) {1745 beginTypeScope( type );1746 }1747 1748 void PolyGenericCalculator::previsit( ast::FunctionType const * type ) {1749 beginTypeScope( type );1750 1751 GuardValue( expect_func_type );1752 GuardScope( *this );1753 1754 // The other functions type we will see in this scope are probably1755 // function parameters they don't help us with the layout and offsets so1756 // don't mark them as known in this scope.1757 expect_func_type = false;1758 }1759 1760 //void PolyGenericCalculator::previsit( ast::DeclStmt const * stmt ) {1761 1689 ast::DeclStmt const * PolyGenericCalculator::previsit( ast::DeclStmt const * stmt ) { 1762 1690 ast::ObjectDecl const * decl = stmt->decl.as<ast::ObjectDecl>(); … … 1766 1694 1767 1695 // Change initialization of a polymorphic value object to allocate via a 1768 // variable-length-array (alloca was previouly used, but it cannot be 1769 // safely used in loops). 1696 // variable-length-array (alloca cannot be safely used in loops). 1770 1697 ast::ObjectDecl * newBuf = new ast::ObjectDecl( decl->location, 1771 1698 bufNamer.newName(), … … 2248 2175 } 2249 2176 2250 void PolyGenericCalculator::beginGenericScope() {2251 GuardScope( *this );2252 // We expect the first function type see to be the type relating to this2253 // scope but any further type is probably some unrelated function pointer2254 // keep track of whrich is the first.2255 GuardValue( expect_func_type ) = true;2256 }2257 2258 2177 // -------------------------------------------------------------------------- 2259 /// No common theme found.2178 /// Removes unneeded or incorrect type information. 2260 2179 /// * Replaces initialization of polymorphic values with alloca. 2261 2180 /// * Replaces declaration of dtype/ftype with appropriate void expression. … … 2263 2182 /// * Strips fields from generic structure declarations. 2264 2183 struct Eraser final : 2265 public BoxPass,2266 2184 public ast::WithGuards { 2267 2185 void guardTypeVarMap( ast::Type const * type ) { … … 2278 2196 void previsit( ast::PointerType const * type ); 2279 2197 void previsit( ast::FunctionType const * type ); 2198 public: 2199 TypeVarMap scopeTypeVars; 2280 2200 }; 2281 2201 -
src/GenPoly/FindFunction.cc
r0030b508 rfc12f05 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
r0030b508 rfc12f05 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
r0030b508 rfc12f05 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; 274 143 275 TypeVarMap forallTypes = { ast::TypeData() };144 TypeVarMap forallTypes; 276 145 makeTypeVarMap( func, forallTypes ); 277 146 return isDynType( func->returns.front(), forallTypes ); 278 147 } 279 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 148 295 149 bool needsAdapter( … … 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( … … 801 379 const ast::FunctionType * function = getFunctionType( expr->func->result ); 802 380 assertf( function, "ApplicationExpr has non-function type: %s", toString( expr->func->result ).c_str() ); 803 TypeVarMap exprTyVars = { ast::TypeData() };381 TypeVarMap exprTyVars; 804 382 makeTypeVarMap( function, exprTyVars ); 805 383 return needsBoxing( param, arg, exprTyVars, subst ); 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
r0030b508 rfc12f05 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 using TypeVarMap = ErasableScopedMap< ast::TypeEnvKey, ast::TypeData >; 32 struct TypeVarMap : public ErasableScopedMap<ast::TypeEnvKey, ast::TypeData> { 33 TypeVarMap() : ErasableScopedMap( ast::TypeData() ) {} 34 }; 36 35 37 36 /// Replaces a TypeInstType by its referrent in the environment, if applicable 38 Type* replaceTypeInst( Type* type, const TypeSubstitution* env );39 const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env );40 37 const ast::Type * replaceTypeInst( const ast::Type *, const ast::TypeSubstitution * ); 41 38 42 39 /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided 43 Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );44 40 const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env = nullptr); 45 41 46 42 /// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided 47 Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );48 43 const ast::Type * isPolyType( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst = nullptr ); 49 44 50 45 /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided 51 ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );52 46 const ast::BaseInstType *isDynType( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst = 0 ); 53 47 54 48 /// true iff function has dynamic-layout return type under the given type variable map 55 ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &tyVars );56 49 const ast::BaseInstType *isDynRet( const ast::FunctionType * type, const TypeVarMap & typeVars ); 57 50 58 51 /// true iff function has dynamic-layout return type under the type variable map generated from its forall-parameters 59 ReferenceToType *isDynRet( FunctionType *function );60 52 const ast::BaseInstType *isDynRet( const ast::FunctionType * func ); 61 53 62 54 /// A function needs an adapter if it returns a dynamic-layout value or if any of its parameters have dynamic-layout type 63 bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVarr );64 55 bool needsAdapter( ast::FunctionType const * adaptee, const TypeVarMap & typeVars ); 65 56 66 /// returns polymorphic type if is pointer to polymorphic type, NULL otherwise; will look up substitution in env if provided67 Type *isPolyPtr( Type *type, const TypeSubstitution *env = 0 );68 69 57 /// returns polymorphic type if is pointer to polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided 70 Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );71 58 const ast::Type * isPolyPtr( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * env = 0 ); 72 73 /// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type, returns the base type, NULL otherwise;74 /// N will be stored in levels, if provided, will look up substitution in env if provided75 Type *hasPolyBase( Type *type, int *levels = 0, const TypeSubstitution *env = 0 );76 59 77 60 /// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type in tyVars, returns the base type, NULL otherwise; 78 61 /// N will be stored in levels, if provided, will look up substitution in env if provided 79 Type *hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels = 0, const TypeSubstitution *env = 0 );80 62 const ast::Type * hasPolyBase( const ast::Type * type, const TypeVarMap & typeVars, int * levels = 0, const ast::TypeSubstitution * env = 0 ); 81 63 82 /// true iff this type or some base of this type after dereferencing pointers is either polymorphic or a generic type with at least one83 /// polymorphic parameter; will look up substitution in env if provided.84 bool includesPolyType( Type *type, const TypeSubstitution *env = 0 );85 86 /// true iff this type or some base of this type after dereferencing pointers is either polymorphic in tyVars, or a generic type with87 /// at least one polymorphic parameter in tyVars; will look up substitution in env if provided.88 bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );89 90 64 /// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise 91 FunctionType *getFunctionType( Type *ty );92 65 const ast::FunctionType * getFunctionType( const ast::Type * ty ); 93 66 94 /// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise;95 /// N will be stored in levels, if provided96 VariableExpr *getBaseVar( Expression *expr, int *levels = 0 );97 98 67 /// true iff types are structurally identical, where TypeInstType's match any type. 99 bool typesPolyCompatible( Type *aty, Type *bty );100 68 bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs ); 101 69 102 70 /// true if arg requires boxing given exprTyVars 103 bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );104 71 bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ); 105 72 106 73 /// true if arg requires boxing in the call to appExpr 107 bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );108 74 bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * expr, const ast::TypeSubstitution * subst ); 109 75 110 76 /// Adds the type variable `tyVar` to `tyVarMap` 111 void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );112 77 void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars ); 113 78 void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ); 114 79 115 80 /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap` 116 void makeTyVarMap( Type *type, TyVarMap &tyVarMap );117 81 void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ); 118 82 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ); 119 120 /// Prints type variable map121 void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );122 123 /// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().124 inline std::string mangleType( const Type *ty ) { return SymTab::Mangler::mangleType( ty ); }125 83 126 84 /// Gets the name of the sizeof parameter for the type, given its mangled name … … 134 92 135 93 /// Gets the name of the layout function for a given aggregate type, given its declaration 136 inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }137 94 inline std::string layoutofName( ast::AggregateDecl const * decl ) { 138 95 return std::string( "_layoutof_" ) + decl->name; -
src/GenPoly/ScrubTyVars.cc
r0030b508 rfc12f05 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
r0030b508 rfc12f05 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
r0030b508 rfc12f05 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 { … … 81 80 } 82 81 83 // The number of elements in a type if it is a flattened tuple.84 size_t flatT upleSize( const ast::Type * type) {85 if ( auto tuple = dynamic_cast<const ast::TupleType *>( type ) ) {86 size_t sum = 0;87 for ( auto t : *tuple) {88 sum += flatT upleSize( t);89 } 90 return sum;91 } else {92 return 1;93 }82 // The number of elements in a list, if all tuples had been flattened. 83 size_t flatTypeListSize( const std::vector<ast::ptr<ast::Type>> & types ) { 84 size_t sum = 0; 85 for ( const ast::ptr<ast::Type> & type : types ) { 86 if ( const ast::TupleType * tuple = type.as<ast::TupleType>() ) { 87 sum += flatTypeListSize( tuple->types ); 88 } else { 89 sum += 1; 90 } 91 } 92 return sum; 94 93 } 95 94 96 95 // Find the total number of components in a parameter list. 97 96 size_t functionParameterSize( const ast::FunctionType * type ) { 98 size_t sum = 0; 99 for ( auto param : type->params ) { 100 sum += flatTupleSize( param ); 101 } 102 return sum; 97 return flatTypeListSize( type->params ); 103 98 } 104 99 -
src/GenPoly/module.mk
r0030b508 rfc12f05 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.