Changeset 3606fe4 for src/GenPoly


Ignore:
Timestamp:
Sep 14, 2022, 9:46:19 AM (2 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, master, pthread-emulation
Children:
1c0657a
Parents:
fc96890
Message:

Translated Instantiate Generic to the new AST. This includes various utilities and some assorted clean-up.

Location:
src/GenPoly
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/GenPoly.cc

    rfc96890 r3606fe4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 29 21:45:53 2016
    13 // Update Count     : 14
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Sep 14  9:24:00 2022
     13// Update Count     : 15
    1414//
    1515
     
    8383                }
    8484
     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
    8596                /// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present
    8697                bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
     
    198209                }
    199210                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;
    200231        }
    201232
     
    378409                inline D* as( B* p ) { return reinterpret_cast<D*>(p); }
    379410
     411                template<typename D, typename B>
     412                inline D const * as( B const * p ) {
     413                        return reinterpret_cast<D const *>( p );
     414                }
     415
    380416                /// Flattens a declaration list
    381417                template<typename Output>
     
    391427                        for ( Type* ty : src ) {
    392428                                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 );
    393436                        }
    394437                }
     
    409452                                // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;
    410453                                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                                }
    411479                        }
    412480
     
    505573        }
    506574
     575bool 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
    507687        namespace {
    508688                // temporary hack to avoid re-implementing anything related to TyVarMap
  • src/GenPoly/GenPoly.h

    rfc96890 r3606fe4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:22:57 2017
    13 // Update Count     : 7
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Aug 19 16:03:00 2022
     13// Update Count     : 8
    1414//
    1515
     
    2727namespace GenPoly {
    2828
     29        // TODO Via some tricks this works for ast::TypeDecl::Data as well.
    2930        typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
     31
    3032        /// Replaces a TypeInstType by its referrent in the environment, if applicable
    3133        Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
     
    4143        /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided
    4244        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 );
    4346
    4447        /// true iff function has dynamic-layout return type under the given type variable map
     
    8386        /// true iff types are structurally identical, where TypeInstType's match any type.
    8487        bool typesPolyCompatible( Type *aty, Type *bty );
     88        bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs );
    8589
    8690        /// true if arg requires boxing given exprTyVars
  • src/GenPoly/InstantiateGeneric.h

    rfc96890 r3606fe4  
    1919
    2020class Declaration;
     21namespace ast {
     22        class TranslationUnit;
     23}
    2124
    2225namespace 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.
     30void instantiateGeneric( std::list< Declaration* > &translationUnit );
     31void instantiateGeneric( ast::TranslationUnit & translationUnit );
    2732} // namespace GenPoly
    2833
  • src/GenPoly/ScrubTyVars.cc

    rfc96890 r3606fe4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 16 15:44:27 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Aug 19 16:10:00 2022
     13// Update Count     : 4
    1414//
    1515
    1616#include <utility>                      // for pair
    1717
     18#include "AST/Pass.hpp"
    1819#include "GenPoly.h"                    // for mangleType, TyVarMap, alignof...
    1920#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2021#include "ScrubTyVars.h"
     22#include "SymTab/Mangler.h"             // for mangle, typeMode
    2123#include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
    2224#include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
     
    112114                return pointer;
    113115        }
     116
     117namespace {
     118
     119enum class ScrubMode {
     120        FromMap,
     121        DynamicFromMap,
     122        All,
     123};
     124
     125struct 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
     147private:
     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
     185ast::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
     217ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
     218        return postvisitAggregateType( type );
     219}
     220
     221ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
     222        return postvisitAggregateType( type );
     223}
     224
     225ast::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
     235ast::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
     245ast::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
     255const 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
     269template<>
     270ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) {
     271        return scrubTypeVarsBase( target, ScrubMode::All, nullptr );
     272}
     273
    114274} // namespace GenPoly
    115275
  • src/GenPoly/ScrubTyVars.h

    rfc96890 r3606fe4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:21:47 2017
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Aug 19 14:14:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    1818#include <cassert>            // for assert
    1919
     20#include "AST/Fwd.hpp"        // for Node
    2021#include "Common/PassVisitor.h"
    2122#include "GenPoly.h"          // for TyVarMap, isPolyType, isDynType
     
    108109        }
    109110
     111/// For all polymorphic types, replaces generic types, with the appropriate
     112/// void type, and sizeof/alignof expressions with the proper variable.
     113template<typename node_t>
     114node_t const * scrubAllTypeVars( node_t const * target ) {
     115        return strict_dynamic_cast<node_t const *>( scrubAllTypeVars<ast::Node>( target ) );
     116}
     117
     118template<>
     119ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target );
     120
    110121} // namespace GenPoly
    111122
  • src/GenPoly/module.mk

    rfc96890 r3606fe4  
    2727        GenPoly/FindFunction.cc \
    2828        GenPoly/FindFunction.h \
     29        GenPoly/InstantiateGenericNew.cpp \
    2930        GenPoly/InstantiateGeneric.cc \
    3031        GenPoly/InstantiateGeneric.h \
Note: See TracChangeset for help on using the changeset viewer.