Changeset 3606fe4 for src/GenPoly
- Timestamp:
- Sep 14, 2022, 9:46:19 AM (2 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation
- Children:
- 1c0657a
- Parents:
- fc96890
- Location:
- src/GenPoly
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/GenPoly.cc
rfc96890 r3606fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Jun 29 21:45:53 201613 // Update Count : 1 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Sep 14 9:24:00 2022 13 // Update Count : 15 14 14 // 15 15 … … 83 83 } 84 84 85 bool hasDynParams( const std::vector<ast::ptr<ast::Expr>> & params, const TyVarMap &tyVars, const ast::TypeSubstitution *typeSubs ) { 86 for ( ast::ptr<ast::Expr> const & param : params ) { 87 auto paramType = param.as<ast::TypeExpr>(); 88 assertf( paramType, "Aggregate parameters should be type expressions." ); 89 if ( isDynType( paramType->type, tyVars, typeSubs ) ) { 90 return true; 91 } 92 } 93 return false; 94 } 95 85 96 /// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present 86 97 bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) { … … 198 209 } 199 210 return 0; 211 } 212 213 const ast::BaseInstType *isDynType( const ast::Type *type, const TyVarMap &tyVars, const ast::TypeSubstitution *typeSubs ) { 214 type = replaceTypeInst( type, typeSubs ); 215 216 if ( auto inst = dynamic_cast<ast::TypeInstType const *>( type ) ) { 217 auto var = tyVars.find( inst->name ); 218 if ( var != tyVars.end() && var->second.isComplete ) { 219 return inst; 220 } 221 } else if ( auto inst = dynamic_cast<ast::StructInstType const *>( type ) ) { 222 if ( hasDynParams( inst->params, tyVars, typeSubs ) ) { 223 return inst; 224 } 225 } else if ( auto inst = dynamic_cast<ast::UnionInstType const *>( type ) ) { 226 if ( hasDynParams( inst->params, tyVars, typeSubs ) ) { 227 return inst; 228 } 229 } 230 return nullptr; 200 231 } 201 232 … … 378 409 inline D* as( B* p ) { return reinterpret_cast<D*>(p); } 379 410 411 template<typename D, typename B> 412 inline D const * as( B const * p ) { 413 return reinterpret_cast<D const *>( p ); 414 } 415 380 416 /// Flattens a declaration list 381 417 template<typename Output> … … 391 427 for ( Type* ty : src ) { 392 428 ResolvExpr::flatten( ty, out ); 429 } 430 } 431 432 void flattenList( vector<ast::ptr<ast::Type>> const & src, 433 vector<ast::ptr<ast::Type>> & out ) { 434 for ( auto const & type : src ) { 435 ResolvExpr::flatten( type, out ); 393 436 } 394 437 } … … 409 452 // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue; 410 453 if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false; 454 } 455 456 return true; 457 } 458 459 bool paramListsPolyCompatible( 460 std::vector<ast::ptr<ast::Expr>> const & lparams, 461 std::vector<ast::ptr<ast::Expr>> const & rparams ) { 462 if ( lparams.size() != rparams.size() ) { 463 return false; 464 } 465 466 for ( auto lparam = lparams.begin(), rparam = rparams.begin() ; 467 lparam != lparams.end() ; ++lparam, ++rparam ) { 468 ast::TypeExpr const * lexpr = lparam->as<ast::TypeExpr>(); 469 assertf( lexpr, "Aggregate parameters should be type expressions" ); 470 ast::TypeExpr const * rexpr = rparam->as<ast::TypeExpr>(); 471 assertf( rexpr, "Aggregate parameters should be type expressions" ); 472 473 // xxx - might need to let VoidType be a wildcard here too; could have some voids 474 // stuffed in for dtype-statics. 475 // if ( is<VoidType>( lexpr->type() ) || is<VoidType>( bparam->get_type() ) ) continue; 476 if ( !typesPolyCompatible( lexpr->type, rexpr->type ) ) { 477 return false; 478 } 411 479 } 412 480 … … 505 573 } 506 574 575 bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs ) { 576 type_index const lid = typeid(*lhs); 577 578 // Polymorphic types always match: 579 if ( type_index(typeid(ast::TypeInstType)) == lid ) return true; 580 581 type_index const rid = typeid(*rhs); 582 if ( type_index(typeid(ast::TypeInstType)) == rid ) return true; 583 584 // All other types only match if they are the same type: 585 if ( lid != rid ) return false; 586 587 // So remaining types can be examined case by case. 588 // Recurse through type structure (conditions borrowed from Unify.cc). 589 590 if ( type_index(typeid(ast::BasicType)) == lid ) { 591 return as<ast::BasicType>(lhs)->kind == as<ast::BasicType>(rhs)->kind; 592 } else if ( type_index(typeid(ast::PointerType)) == lid ) { 593 ast::PointerType const * l = as<ast::PointerType>(lhs); 594 ast::PointerType const * r = as<ast::PointerType>(rhs); 595 596 // void pointers should match any other pointer type. 597 return is<ast::VoidType>( l->base.get() ) 598 || is<ast::VoidType>( r->base.get() ) 599 || typesPolyCompatible( l->base.get(), r->base.get() ); 600 } else if ( type_index(typeid(ast::ReferenceType)) == lid ) { 601 ast::ReferenceType const * l = as<ast::ReferenceType>(lhs); 602 ast::ReferenceType const * r = as<ast::ReferenceType>(rhs); 603 604 // void references should match any other reference type. 605 return is<ast::VoidType>( l->base.get() ) 606 || is<ast::VoidType>( r->base.get() ) 607 || typesPolyCompatible( l->base.get(), r->base.get() ); 608 } else if ( type_index(typeid(ast::ArrayType)) == lid ) { 609 ast::ArrayType const * l = as<ast::ArrayType>(lhs); 610 ast::ArrayType const * r = as<ast::ArrayType>(rhs); 611 612 if ( l->isVarLen ) { 613 if ( !r->isVarLen ) return false; 614 } else { 615 if ( r->isVarLen ) return false; 616 617 auto lc = l->dimension.as<ast::ConstantExpr>(); 618 auto rc = r->dimension.as<ast::ConstantExpr>(); 619 if ( lc && rc && lc->intValue() != rc->intValue() ) { 620 return false; 621 } 622 } 623 624 return typesPolyCompatible( l->base.get(), r->base.get() ); 625 } else if ( type_index(typeid(ast::FunctionType)) == lid ) { 626 ast::FunctionType const * l = as<ast::FunctionType>(lhs); 627 ast::FunctionType const * r = as<ast::FunctionType>(rhs); 628 629 std::vector<ast::ptr<ast::Type>> lparams, rparams; 630 flattenList( l->params, lparams ); 631 flattenList( r->params, rparams ); 632 if ( lparams.size() != rparams.size() ) return false; 633 for ( unsigned i = 0; i < lparams.size(); ++i ) { 634 if ( !typesPolyCompatible( lparams[i], rparams[i] ) ) return false; 635 } 636 637 std::vector<ast::ptr<ast::Type>> lrets, rrets; 638 flattenList( l->returns, lrets ); 639 flattenList( r->returns, rrets ); 640 if ( lrets.size() != rrets.size() ) return false; 641 for ( unsigned i = 0; i < lrets.size(); ++i ) { 642 if ( !typesPolyCompatible( lrets[i], rrets[i] ) ) return false; 643 } 644 return true; 645 } else if ( type_index(typeid(ast::StructInstType)) == lid ) { 646 ast::StructInstType const * l = as<ast::StructInstType>(lhs); 647 ast::StructInstType const * r = as<ast::StructInstType>(rhs); 648 649 if ( l->name != r->name ) return false; 650 return paramListsPolyCompatible( l->params, r->params ); 651 } else if ( type_index(typeid(ast::UnionInstType)) == lid ) { 652 ast::UnionInstType const * l = as<ast::UnionInstType>(lhs); 653 ast::UnionInstType const * r = as<ast::UnionInstType>(rhs); 654 655 if ( l->name != r->name ) return false; 656 return paramListsPolyCompatible( l->params, r->params ); 657 } else if ( type_index(typeid(ast::EnumInstType)) == lid ) { 658 ast::EnumInstType const * l = as<ast::EnumInstType>(lhs); 659 ast::EnumInstType const * r = as<ast::EnumInstType>(rhs); 660 661 return l->name == r->name; 662 } else if ( type_index(typeid(ast::TraitInstType)) == lid ) { 663 ast::TraitInstType const * l = as<ast::TraitInstType>(lhs); 664 ast::TraitInstType const * r = as<ast::TraitInstType>(rhs); 665 666 return l->name == r->name; 667 } else if ( type_index(typeid(ast::TupleType)) == lid ) { 668 ast::TupleType const * l = as<ast::TupleType>(lhs); 669 ast::TupleType const * r = as<ast::TupleType>(rhs); 670 671 std::vector<ast::ptr<ast::Type>> ltypes, rtypes; 672 flattenList( l->types, ( ltypes ) ); 673 flattenList( r->types, ( rtypes ) ); 674 if ( ltypes.size() != rtypes.size() ) return false; 675 676 for ( unsigned i = 0 ; i < ltypes.size() ; ++i ) { 677 if ( !typesPolyCompatible( ltypes[i], rtypes[i] ) ) return false; 678 } 679 return true; 680 // The remaining types (VoidType, VarArgsType, ZeroType & OneType) 681 // have no variation so will always be equal. 682 } else { 683 return true; 684 } 685 } 686 507 687 namespace { 508 688 // temporary hack to avoid re-implementing anything related to TyVarMap -
src/GenPoly/GenPoly.h
rfc96890 r3606fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:22:57 201713 // Update Count : 711 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Aug 19 16:03:00 2022 13 // Update Count : 8 14 14 // 15 15 … … 27 27 namespace GenPoly { 28 28 29 // TODO Via some tricks this works for ast::TypeDecl::Data as well. 29 30 typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap; 31 30 32 /// Replaces a TypeInstType by its referrent in the environment, if applicable 31 33 Type* replaceTypeInst( Type* type, const TypeSubstitution* env ); … … 41 43 /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided 42 44 ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 ); 45 const ast::BaseInstType *isDynType( const ast::Type *type, const TyVarMap &tyVars, const ast::TypeSubstitution *typeSubs = 0 ); 43 46 44 47 /// true iff function has dynamic-layout return type under the given type variable map … … 83 86 /// true iff types are structurally identical, where TypeInstType's match any type. 84 87 bool typesPolyCompatible( Type *aty, Type *bty ); 88 bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs ); 85 89 86 90 /// true if arg requires boxing given exprTyVars -
src/GenPoly/InstantiateGeneric.h
rfc96890 r3606fe4 19 19 20 20 class Declaration; 21 namespace ast { 22 class TranslationUnit; 23 } 21 24 22 25 namespace GenPoly { 23 /// Replaces all generic types that have static layout with concrete instantiations. 24 /// Types with concrete values for otype parameters will be template-expanded, while 25 /// dtype and ftype parameters will be replaced by the appropriate void type. 26 void instantiateGeneric( std::list< Declaration* > &translationUnit ); 26 /// Replaces all generic types that have static layout with concrete 27 /// instantiations. Types with concrete values for otype parameters will be 28 /// template-expanded, while dtype and ftype parameters will be replaced by 29 /// the appropriate void type. 30 void instantiateGeneric( std::list< Declaration* > &translationUnit ); 31 void instantiateGeneric( ast::TranslationUnit & translationUnit ); 27 32 } // namespace GenPoly 28 33 -
src/GenPoly/ScrubTyVars.cc
rfc96890 r3606fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Mar 16 15:44:27 201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Aug 19 16:10:00 2022 13 // Update Count : 4 14 14 // 15 15 16 16 #include <utility> // for pair 17 17 18 #include "AST/Pass.hpp" 18 19 #include "GenPoly.h" // for mangleType, TyVarMap, alignof... 19 20 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::const_it... 20 21 #include "ScrubTyVars.h" 22 #include "SymTab/Mangler.h" // for mangle, typeMode 21 23 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data, Typ... 22 24 #include "SynTree/Expression.h" // for Expression (ptr only), NameExpr … … 112 114 return pointer; 113 115 } 116 117 namespace { 118 119 enum class ScrubMode { 120 FromMap, 121 DynamicFromMap, 122 All, 123 }; 124 125 struct ScrubTypeVars : 126 public ast::WithGuards, 127 public ast::WithShortCircuiting, 128 public ast::WithVisitorRef<ScrubTypeVars> { 129 130 ScrubTypeVars( ScrubMode m, TyVarMap const * tv ) : 131 mode ( m ), typeVars( tv ) {} 132 133 void previsit( ast::TypeInstType const * ) { visit_children = false; } 134 void previsit( ast::StructInstType const * ) { visit_children = false; } 135 void previsit( ast::UnionInstType const * ) { visit_children = false; } 136 void previsit( ast::SizeofExpr const * expr ) { primeBaseScrub( expr->type ); } 137 void previsit( ast::AlignofExpr const * expr ) { primeBaseScrub( expr->type ); } 138 void previsit( ast::PointerType const * type ) { primeBaseScrub( type->base ); } 139 140 ast::Type const * postvisit( ast::TypeInstType const * type ); 141 ast::Type const * postvisit( ast::StructInstType const * type ); 142 ast::Type const * postvisit( ast::UnionInstType const * type ); 143 ast::Expr const * postvisit( ast::SizeofExpr const * expr ); 144 ast::Expr const * postvisit( ast::AlignofExpr const * expr ); 145 ast::Type const * postvisit( ast::PointerType const * type ); 146 147 private: 148 ScrubMode const mode; 149 /// Type varriables to scrub. 150 TyVarMap const * const typeVars; 151 /// Value cached by primeBaseScrub. 152 ast::Type const * dynType = nullptr; 153 154 /// Returns the type if it should be scrubbed, nullptr otherwise. 155 ast::Type const * shouldScrub( ast::Type const * type ) { 156 switch ( mode ) { 157 case ScrubMode::FromMap: 158 return isPolyType( type, *typeVars ); 159 case ScrubMode::DynamicFromMap: 160 return isDynType( type, *typeVars ); 161 case ScrubMode::All: 162 return isPolyType( type ); 163 default: 164 assertf( false, "Invalid ScrubMode in shouldScrub." ); 165 throw; 166 } 167 } 168 169 void primeBaseScrub( ast::Type const * type ) { 170 // Need to determine whether type needs to be scrubbed to 171 // determine whether automatic recursion is necessary. 172 if ( ast::Type const * t = shouldScrub( type ) ) { 173 visit_children = false; 174 GuardValue( dynType ) = t; 175 } 176 } 177 178 ast::Type const * postvisitAggregateType( 179 ast::BaseInstType const * type ) { 180 if ( !shouldScrub( type ) ) return type; 181 return new ast::PointerType( new ast::VoidType( type->qualifiers ) ); 182 } 183 }; 184 185 ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) { 186 // This implies that mode == ScrubMode::All. 187 if ( !typeVars ) { 188 if ( ast::TypeDecl::Ftype == type->kind ) { 189 return new ast::PointerType( 190 new ast::FunctionType( ast::FixedArgs ) ); 191 } else { 192 return new ast::PointerType( 193 new ast::VoidType( type->qualifiers ) ); 194 } 195 } 196 197 auto typeVar = typeVars->find( type->name ); 198 if ( typeVar == typeVars->end() ) { 199 return type; 200 } 201 202 switch ( typeVar->second.kind ) { 203 case ast::TypeDecl::Dtype: 204 case ast::TypeDecl::Ttype: 205 return new ast::PointerType( 206 new ast::VoidType( type->qualifiers ) ); 207 case ast::TypeDecl::Ftype: 208 return new ast::PointerType( 209 new ast::FunctionType( ast::VariableArgs ) ); 210 default: 211 assertf( false, 212 "Unhandled type variable kind: %d", typeVar->second.kind ); 213 throw; // Just in case the assert is removed, stop here. 214 } 215 } 216 217 ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) { 218 return postvisitAggregateType( type ); 219 } 220 221 ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) { 222 return postvisitAggregateType( type ); 223 } 224 225 ast::Expr const * ScrubTypeVars::postvisit( ast::SizeofExpr const * expr ) { 226 // sizeof( T ) becomes the _sizeof_T parameter. 227 if ( dynType ) { 228 return new ast::NameExpr( expr->location, 229 sizeofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) ); 230 } else { 231 return expr; 232 } 233 } 234 235 ast::Expr const * ScrubTypeVars::postvisit( ast::AlignofExpr const * expr ) { 236 // alignof( T ) becomes the _alignof_T parameter. 237 if ( dynType ) { 238 return new ast::NameExpr( expr->location, 239 alignofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) ); 240 } else { 241 return expr; 242 } 243 } 244 245 ast::Type const * ScrubTypeVars::postvisit( ast::PointerType const * type ) { 246 if ( dynType ) { 247 ast::Type * ret = ast::mutate( dynType->accept( *visitor ) ); 248 ret->qualifiers |= type->qualifiers; 249 return ret; 250 } else { 251 return type; 252 } 253 } 254 255 const ast::Node * scrubTypeVarsBase( 256 const ast::Node * target, 257 ScrubMode mode, const TyVarMap * typeVars ) { 258 if ( ScrubMode::All == mode ) { 259 assert( nullptr == typeVars ); 260 } else { 261 assert( nullptr != typeVars ); 262 } 263 ast::Pass<ScrubTypeVars> visitor( mode, typeVars ); 264 return target->accept( visitor ); 265 } 266 267 } // namespace 268 269 template<> 270 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) { 271 return scrubTypeVarsBase( target, ScrubMode::All, nullptr ); 272 } 273 114 274 } // namespace GenPoly 115 275 -
src/GenPoly/ScrubTyVars.h
rfc96890 r3606fe4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:21:47 201713 // Update Count : 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Aug 19 14:14:00 2022 13 // Update Count : 3 14 14 // 15 15 … … 18 18 #include <cassert> // for assert 19 19 20 #include "AST/Fwd.hpp" // for Node 20 21 #include "Common/PassVisitor.h" 21 22 #include "GenPoly.h" // for TyVarMap, isPolyType, isDynType … … 108 109 } 109 110 111 /// For all polymorphic types, replaces generic types, with the appropriate 112 /// void type, and sizeof/alignof expressions with the proper variable. 113 template<typename node_t> 114 node_t const * scrubAllTypeVars( node_t const * target ) { 115 return strict_dynamic_cast<node_t const *>( scrubAllTypeVars<ast::Node>( target ) ); 116 } 117 118 template<> 119 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ); 120 110 121 } // namespace GenPoly 111 122 -
src/GenPoly/module.mk
rfc96890 r3606fe4 27 27 GenPoly/FindFunction.cc \ 28 28 GenPoly/FindFunction.h \ 29 GenPoly/InstantiateGenericNew.cpp \ 29 30 GenPoly/InstantiateGeneric.cc \ 30 31 GenPoly/InstantiateGeneric.h \
Note: See TracChangeset
for help on using the changeset viewer.