Changeset 24d6572 for src/GenPoly


Ignore:
Timestamp:
Jun 12, 2023, 2:45:32 PM (2 years ago)
Author:
Fangren Yu <f37yu@…>
Branches:
ast-experimental, master
Children:
62d62db
Parents:
34b4268 (diff), 251ce80 (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.
Message:

Merge branch 'master' into ast-experimental

Location:
src/GenPoly
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    r34b4268 r24d6572  
    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 : Fri Dec 13 23:40:34 2019
    13 // Update Count     : 347
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Dec 19 16:36:00 2022
     13// Update Count     : 348
    1414//
     15
     16#include "Box.h"
    1517
    1618#include <algorithm>                     // for mismatch
     
    2426#include <utility>                       // for pair
    2527
    26 #include "Box.h"
    27 
    2828#include "CodeGen/OperatorTable.h"
    2929#include "Common/PassVisitor.h"          // for PassVisitor
     
    3131#include "Common/SemanticError.h"        // for SemanticError
    3232#include "Common/UniqueName.h"           // for UniqueName
    33 #include "Common/utility.h"              // for toString
     33#include "Common/ToString.hpp"           // for toCString
    3434#include "FindFunction.h"                // for findFunction, findAndReplace...
    3535#include "GenPoly/ErasableScopedMap.h"   // for ErasableScopedMap<>::const_i...
     
    3737#include "InitTweak/InitTweak.h"         // for getFunctionName, isAssignment
    3838#include "Lvalue.h"                      // for generalizedLvalue
    39 #include "ResolvExpr/typeops.h"          // for typesCompatible
     39#include "ResolvExpr/Unify.h"            // for typesCompatible
    4040#include "ScopedSet.h"                   // for ScopedSet, ScopedSet<>::iter...
    4141#include "ScrubTyVars.h"                 // for ScrubTyVars
     
    7272                };
    7373
     74                /// Updates the call sites of polymorphic functions.
    7475                /// Replaces polymorphic return types with out-parameters,
    7576                /// replaces calls to polymorphic functions with adapter calls,
    7677                /// and adds appropriate type variables to the function call.
    77                 class Pass1 final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {
     78                class CallAdapter final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<CallAdapter>, public WithShortCircuiting {
    7879                  public:
    79                         Pass1();
    80 
     80                        CallAdapter();
     81
     82                        void premutate( Declaration * declaration );
    8183                        void premutate( FunctionDecl * functionDecl );
    8284                        void premutate( TypeDecl * typeDecl );
     
    138140                };
    139141
     142                /// Updates declarations (and types) that require adapters.
    140143                /// * Moves polymorphic returns in function types to pointer-type parameters
    141144                /// * adds type size and assertion parameters to parameter lists
    142                 struct Pass2 final : public BoxPass, public WithGuards {
     145                struct DeclAdapter final : public BoxPass, public WithGuards {
    143146                        void handleAggDecl();
    144147
     
    210213                };
    211214
     215                /// Erases unneeded/unwanted polymorphic information.
    212216                /// Replaces initialization of polymorphic values with alloca,
    213217                /// declaration of dtype/ftype with appropriate void expression,
    214218                /// sizeof expressions of polymorphic types with the proper variable,
    215219                /// and strips fields from generic struct declarations.
    216                 struct Pass3 final : public BoxPass, public WithGuards {
    217                         template< typename DeclClass >
    218                         void handleDecl( DeclClass * decl, Type * type );
    219 
     220                struct Eraser final {
    220221                        void premutate( ObjectDecl * objectDecl );
    221222                        void premutate( FunctionDecl * functionDecl );
     
    223224                        void premutate( StructDecl * structDecl );
    224225                        void premutate( UnionDecl * unionDecl );
    225                         void premutate( TypeDecl * typeDecl );
    226                         void premutate( PointerType * pointerType );
    227                         void premutate( FunctionType * funcType );
    228226                };
    229227        } // anonymous namespace
     
    231229        void box( std::list< Declaration *>& translationUnit ) {
    232230                PassVisitor<LayoutFunctionBuilder> layoutBuilder;
    233                 PassVisitor<Pass1> pass1;
    234                 PassVisitor<Pass2> pass2;
     231                PassVisitor<CallAdapter> callAdapter;
     232                PassVisitor<DeclAdapter> declAdapter;
    235233                PassVisitor<PolyGenericCalculator> polyCalculator;
    236                 PassVisitor<Pass3> pass3;
     234                PassVisitor<Eraser> eraser;
    237235
    238236                acceptAll( translationUnit, layoutBuilder );
    239                 mutateAll( translationUnit, pass1 );
    240                 mutateAll( translationUnit, pass2 );
     237                mutateAll( translationUnit, callAdapter );
     238                mutateAll( translationUnit, declAdapter );
    241239                mutateAll( translationUnit, polyCalculator );
    242                 mutateAll( translationUnit, pass3 );
     240                mutateAll( translationUnit, eraser );
    243241        }
    244242
    245         ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
     243////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////
    246244
    247245        /// Get a list of type declarations that will affect a layout function
     
    423421        }
    424422
    425         ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
     423////////////////////////////////////////////// CallAdapter //////////////////////////////////////
    426424
    427425        namespace {
    428426                std::string makePolyMonoSuffix( FunctionType const * function, const TyVarMap &tyVars ) {
    429                         std::stringstream name;
    430 
    431427                        // NOTE: this function previously used isPolyObj, which failed to produce
    432428                        // the correct thing in some situations. It's not clear to me why this wasn't working.
     
    435431                        // to take those polymorphic types as pointers. Therefore, there can be two different functions
    436432                        // with the same mangled name, so we need to further mangle the names.
     433                        std::stringstream name;
    437434                        for ( DeclarationWithType const * const ret : function->returnVals ) {
    438                                 if ( isPolyType( ret->get_type(), tyVars ) ) {
    439                                         name << "P";
    440                                 } else {
    441                                         name << "M";
    442                                 }
    443                         }
    444                         name << "_";
     435                                name << ( isPolyType( ret->get_type(), tyVars ) ? 'P' : 'M' );
     436                        }
     437                        name << '_';
    445438                        for ( DeclarationWithType const * const arg : function->parameters ) {
    446                                 if ( isPolyType( arg->get_type(), tyVars ) ) {
    447                                         name << "P";
    448                                 } else {
    449                                         name << "M";
    450                                 }
    451                         } // for
     439                                name << ( isPolyType( arg->get_type(), tyVars ) ? 'P' : 'M' );
     440                        }
    452441                        return name.str();
    453442                }
     
    465454                Type *replaceWithConcrete( Type *type, TypeSubstitution const * env, bool doClone = true );
    466455
    467                 Pass1::Pass1() : tempNamer( "_temp" ) {}
    468 
    469                 void Pass1::premutate( FunctionDecl *functionDecl ) {
     456                CallAdapter::CallAdapter() : tempNamer( "_temp" ) {}
     457
     458                void CallAdapter::premutate( Declaration * ) {
     459                        // Prevent type declaration information from leaking out.
     460                        GuardScope( scopeTyVars );
     461                }
     462
     463                void CallAdapter::premutate( FunctionDecl *functionDecl ) {
    470464                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    471465                                // std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
     
    500494                                for ( FunctionType const * const funType : functions ) {
    501495                                        std::string mangleName = mangleAdapterName( funType, scopeTyVars );
    502                                         if ( adapters.find( mangleName ) == adapters.end() ) {
     496                                        if ( !adapters.contains( mangleName ) ) {
    503497                                                std::string adapterName = makeAdapterName( mangleName );
    504498                                                adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), nullptr ) ) );
     
    509503                }
    510504
    511                 void Pass1::premutate( TypeDecl *typeDecl ) {
     505                void CallAdapter::premutate( TypeDecl *typeDecl ) {
    512506                        addToTyVarMap( typeDecl, scopeTyVars );
    513507                }
    514508
    515                 void Pass1::premutate( CommaExpr *commaExpr ) {
     509                void CallAdapter::premutate( CommaExpr *commaExpr ) {
    516510                        // Attempting to find application expressions that were mutated by the copy constructor passes
    517511                        // to use an explicit return variable, so that the variable can be reused as a parameter to the
     
    531525                }
    532526
    533                 std::list< Expression *>::iterator Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
     527                std::list< Expression *>::iterator CallAdapter::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
    534528                        Type *polyType = isPolyType( parmType, exprTyVars );
    535529                        if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     
    558552                }
    559553
    560                 std::list< Expression *>::iterator Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {
     554                std::list< Expression *>::iterator CallAdapter::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {
    561555                        assert( env );
    562556                        std::list< Expression *>::iterator arg = appExpr->args.begin();
     
    568562                        // even when converted to strings, sort in the original order.
    569563                        // (At least, that is the best explination I have.)
    570                         for ( std::pair<std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {
     564                        for ( std::pair<const std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {
    571565                                if ( !tyParam.second.isComplete ) continue;
    572566                                Type *concrete = env->lookup( tyParam.first );
     
    611605                }
    612606
    613                 ObjectDecl *Pass1::makeTemporary( Type *type ) {
     607                ObjectDecl *CallAdapter::makeTemporary( Type *type ) {
    614608                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
    615609                        stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
     
    617611                }
    618612
    619                 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, Type *retType ) {
     613                Expression *CallAdapter::addRetParam( ApplicationExpr *appExpr, Type *retType ) {
    620614                        // Create temporary to hold return value of polymorphic function and produce that temporary as a result
    621615                        // using a comma expression.
     
    680674                }
    681675
    682                 Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {
     676                Expression *CallAdapter::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {
    683677                        Type *concrete = replaceWithConcrete( dynType, env );
    684678                        // add out-parameter for return value
     
    686680                }
    687681
    688                 Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {
     682                Expression *CallAdapter::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {
    689683                        Expression *ret = appExpr;
    690684                        if ( isDynRet( function, scopeTyVars ) ) {
     
    735729                }
    736730
    737                 void Pass1::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {
     731                void CallAdapter::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {
    738732                        assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
    739733                        addCast( arg, param, exprTyVars );
     
    770764                }
    771765
    772                 void Pass1::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {
     766                void CallAdapter::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {
    773767                        for ( DeclarationWithType * param : function->parameters ) {
    774768                                assertf( arg != appExpr->args.end(), "boxParams: missing argument for param %s to %s in %s", toString( param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
     
    778772                }
    779773
    780                 void Pass1::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {
     774                void CallAdapter::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {
    781775                        for ( TypeDecl * const tyVar : functionType->forall ) {
    782776                                for ( DeclarationWithType * const assert : tyVar->assertions ) {
     
    846840                }
    847841
    848                 FunctionDecl *Pass1::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
     842                FunctionDecl *CallAdapter::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
    849843                        FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
    850844                        adapterType = ScrubTyVars::scrub( adapterType, tyVars );
     
    906900                }
    907901
    908                 void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
     902                void CallAdapter::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
    909903                        // collect a list of function types passed as parameters or implicit parameters (assertions)
    910904                        std::list<FunctionType const *> functions;
     
    923917
    924918                        for ( FunctionType const * const funType : functions ) {
    925                                 FunctionType *originalFunction = funType->clone();
    926                                 FunctionType *realFunction = funType->clone();
    927                                 std::string mangleName = SymTab::Mangler::mangle( realFunction );
     919                                std::string mangleName = SymTab::Mangler::mangle( funType );
    928920
    929921                                // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
    930922                                // pre-substitution parameter function type.
    931923                                // The second part of the insert result is "is the value new".
    932                                 if ( adaptersDone.insert( mangleName ).second ) {
    933 
    934                                         // apply substitution to type variables to figure out what the adapter's type should look like
    935                                         assert( env );
    936                                         env->apply( realFunction );
    937                                         mangleName = SymTab::Mangler::mangle( realFunction );
    938                                         mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
    939 
    940                                         typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
    941                                         AdapterIter adapter = adapters.find( mangleName );
    942                                         if ( adapter == adapters.end() ) {
    943                                                 // adapter has not been created yet in the current scope, so define it
    944                                                 FunctionDecl *newAdapter = makeAdapter( funType, realFunction, mangleName, exprTyVars );
    945                                                 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
    946                                                 adapter = answer.first;
    947                                                 stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
    948                                         } // if
    949                                         assert( adapter != adapters.end() );
    950 
    951                                         // add the appropriate adapter as a parameter
    952                                         appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
     924                                if ( !adaptersDone.insert( mangleName ).second ) continue;
     925
     926                                // Apply substitution to type variables to figure out what the adapter's type should look like.
     927                                assert( env );
     928                                FunctionType *realType = funType->clone();
     929                                env->apply( realType );
     930                                mangleName = SymTab::Mangler::mangle( realType );
     931                                mangleName += makePolyMonoSuffix( funType, exprTyVars );
     932
     933                                typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
     934                                AdapterIter adapter = adapters.find( mangleName );
     935                                if ( adapter == adapters.end() ) {
     936                                        // Adapter has not been created yet in the current scope, so define it.
     937                                        FunctionDecl *newAdapter = makeAdapter( funType, realType, mangleName, exprTyVars );
     938                                        std::pair< AdapterIter, bool > answer = adapters.insert( mangleName, newAdapter );
     939                                        adapter = answer.first;
     940                                        stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
    953941                                } // if
     942                                assert( adapter != adapters.end() );
     943
     944                                // Add the appropriate adapter as a parameter.
     945                                appExpr->args.push_front( new VariableExpr( adapter->second ) );
    954946                        } // for
    955947                } // passAdapters
     
    974966                }
    975967
    976                 Expression *Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {
     968                Expression *CallAdapter::handleIntrinsics( ApplicationExpr *appExpr ) {
    977969                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->function ) ) {
    978970                                if ( varExpr->var->linkage == LinkageSpec::Intrinsic ) {
     
    10971089                }
    10981090
    1099                 Expression *Pass1::postmutate( ApplicationExpr *appExpr ) {
     1091                Expression *CallAdapter::postmutate( ApplicationExpr *appExpr ) {
    11001092                        // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
    11011093                        // for ( auto tyVar : scopeTyVars ) {
     
    11691161                }
    11701162
    1171                 Expression * Pass1::postmutate( UntypedExpr *expr ) {
     1163                Expression * CallAdapter::postmutate( UntypedExpr *expr ) {
    11721164                        if ( isPolyDeref( expr, scopeTyVars, env ) ) {
    11731165                                Expression *ret = expr->args.front();
     
    11791171                }
    11801172
    1181                 void Pass1::premutate( AddressExpr * ) { visit_children = false; }
    1182 
    1183                 Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
     1173                void CallAdapter::premutate( AddressExpr * ) { visit_children = false; }
     1174
     1175                Expression * CallAdapter::postmutate( AddressExpr * addrExpr ) {
    11841176                        assert( addrExpr->arg->result && ! addrExpr->arg->result->isVoid() );
    11851177
     
    12121204                }
    12131205
    1214                 void Pass1::premutate( ReturnStmt *returnStmt ) {
     1206                void CallAdapter::premutate( ReturnStmt *returnStmt ) {
    12151207                        if ( retval && returnStmt->expr ) {
    12161208                                assert( returnStmt->expr->result && ! returnStmt->expr->result->isVoid() );
     
    12201212                }
    12211213
    1222                 void Pass1::premutate( PointerType *pointerType ) {
     1214                void CallAdapter::premutate( PointerType *pointerType ) {
    12231215                        GuardScope( scopeTyVars );
    12241216                        makeTyVarMap( pointerType, scopeTyVars );
    12251217                }
    12261218
    1227                 void Pass1::premutate( FunctionType *functionType ) {
     1219                void CallAdapter::premutate( FunctionType *functionType ) {
    12281220                        GuardScope( scopeTyVars );
    12291221                        makeTyVarMap( functionType, scopeTyVars );
    12301222                }
    12311223
    1232                 void Pass1::beginScope() {
     1224                void CallAdapter::beginScope() {
    12331225                        adapters.beginScope();
    12341226                }
    12351227
    1236                 void Pass1::endScope() {
     1228                void CallAdapter::endScope() {
    12371229                        adapters.endScope();
    12381230                }
    12391231
    1240 ////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
    1241 
    1242                 void Pass2::addAdapters( FunctionType *functionType ) {
     1232////////////////////////////////////////// DeclAdapter //////////////////////////////////////////
     1233
     1234                void DeclAdapter::addAdapters( FunctionType *functionType ) {
    12431235                        std::list< FunctionType const *> functions;
    12441236                        for ( DeclarationWithType * const arg : functionType->parameters ) {
     
    12601252                }
    12611253
    1262                 DeclarationWithType * Pass2::postmutate( FunctionDecl *functionDecl ) {
     1254                DeclarationWithType * DeclAdapter::postmutate( FunctionDecl *functionDecl ) {
    12631255                        FunctionType * ftype = functionDecl->type;
    12641256                        if ( ! ftype->returnVals.empty() && functionDecl->statements ) {
     
    12851277                }
    12861278
    1287                 void Pass2::premutate( StructDecl * ) {
     1279                void DeclAdapter::premutate( StructDecl * ) {
    12881280                        // prevent tyVars from leaking into containing scope
    12891281                        GuardScope( scopeTyVars );
    12901282                }
    12911283
    1292                 void Pass2::premutate( UnionDecl * ) {
     1284                void DeclAdapter::premutate( UnionDecl * ) {
    12931285                        // prevent tyVars from leaking into containing scope
    12941286                        GuardScope( scopeTyVars );
    12951287                }
    12961288
    1297                 void Pass2::premutate( TraitDecl * ) {
     1289                void DeclAdapter::premutate( TraitDecl * ) {
    12981290                        // prevent tyVars from leaking into containing scope
    12991291                        GuardScope( scopeTyVars );
    13001292                }
    13011293
    1302                 void Pass2::premutate( TypeDecl *typeDecl ) {
     1294                void DeclAdapter::premutate( TypeDecl *typeDecl ) {
    13031295                        addToTyVarMap( typeDecl, scopeTyVars );
    13041296                }
    13051297
    1306                 void Pass2::premutate( PointerType *pointerType ) {
     1298                void DeclAdapter::premutate( PointerType *pointerType ) {
    13071299                        GuardScope( scopeTyVars );
    13081300                        makeTyVarMap( pointerType, scopeTyVars );
    13091301                }
    13101302
    1311                 void Pass2::premutate( FunctionType *funcType ) {
     1303                void DeclAdapter::premutate( FunctionType *funcType ) {
    13121304                        GuardScope( scopeTyVars );
    13131305                        makeTyVarMap( funcType, scopeTyVars );
     
    13931385                }
    13941386
    1395 ////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
     1387////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////
    13961388
    13971389                PolyGenericCalculator::PolyGenericCalculator()
     
    14741466                        // make sure that any type information passed into the function is accounted for
    14751467                        for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
    1476                                 // condition here duplicates that in Pass2::mutate( FunctionType* )
     1468                                // condition here duplicates that in DeclAdapter::mutate( FunctionType* )
    14771469                                Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
    14781470                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     
    15011493                                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
    15021494                                                // do not try to monomorphize generic parameters
    1503                                                 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {
     1495                                                if ( scopeTyVars.contains( typeInst->get_name() ) && ! genericParams.count( typeInst->name ) ) {
    15041496                                                        // polymorphic aggregate members should be converted into monomorphic members.
    15051497                                                        // Using char[size_T] here respects the expected sizing rules of an aggregate type.
     
    17101702
    17111703                        if ( auto typeInst = dynamic_cast< TypeInstType const * >( ty ) ) {
    1712                                 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
     1704                                if ( scopeTyVars.contains( typeInst->get_name() ) ) {
    17131705                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
    17141706                                        return true;
     
    17181710                                // check if this type already has a layout generated for it
    17191711                                std::string typeName = mangleType( ty );
    1720                                 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     1712                                if ( knownLayouts.contains( typeName ) ) return true;
    17211713
    17221714                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     
    17551747                                // check if this type already has a layout generated for it
    17561748                                std::string typeName = mangleType( ty );
    1757                                 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     1749                                if ( knownLayouts.contains( typeName ) ) return true;
    17581750
    17591751                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     
    18461838                        } else {
    18471839                                std::string offsetName = offsetofName( mangleType( ty ) );
    1848                                 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
     1840                                if ( knownOffsets.contains( offsetName ) ) {
    18491841                                        // use the already-generated offsets for this type
    18501842                                        ret = new NameExpr( offsetName );
     
    18841876                }
    18851877
    1886 ////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
    1887 
    1888                 template< typename DeclClass >
    1889                 void Pass3::handleDecl( DeclClass * decl, Type * type ) {
    1890                         GuardScope( scopeTyVars );
    1891                         makeTyVarMap( type, scopeTyVars );
    1892                         ScrubTyVars::scrubAll( decl );
    1893                 }
    1894 
    1895                 void Pass3::premutate( ObjectDecl * objectDecl ) {
    1896                         handleDecl( objectDecl, objectDecl->type );
    1897                 }
    1898 
    1899                 void Pass3::premutate( FunctionDecl * functionDecl ) {
    1900                         handleDecl( functionDecl, functionDecl->type );
    1901                 }
    1902 
    1903                 void Pass3::premutate( TypedefDecl * typedefDecl ) {
    1904                         handleDecl( typedefDecl, typedefDecl->base );
     1878////////////////////////////////////////// Eraser ///////////////////////////////////////////////
     1879
     1880                void Eraser::premutate( ObjectDecl * objectDecl ) {
     1881                        ScrubTyVars::scrubAll( objectDecl );
     1882                }
     1883
     1884                void Eraser::premutate( FunctionDecl * functionDecl ) {
     1885                        ScrubTyVars::scrubAll( functionDecl );
     1886                }
     1887
     1888                void Eraser::premutate( TypedefDecl * typedefDecl ) {
     1889                        ScrubTyVars::scrubAll( typedefDecl );
    19051890                }
    19061891
    19071892                /// Strips the members from a generic aggregate
    1908                 void stripGenericMembers(AggregateDecl * decl) {
     1893                static void stripGenericMembers( AggregateDecl * decl ) {
    19091894                        if ( ! decl->parameters.empty() ) decl->members.clear();
    19101895                }
    19111896
    1912                 void Pass3::premutate( StructDecl * structDecl ) {
     1897                void Eraser::premutate( StructDecl * structDecl ) {
    19131898                        stripGenericMembers( structDecl );
    19141899                }
    19151900
    1916                 void Pass3::premutate( UnionDecl * unionDecl ) {
     1901                void Eraser::premutate( UnionDecl * unionDecl ) {
    19171902                        stripGenericMembers( unionDecl );
    1918                 }
    1919 
    1920                 void Pass3::premutate( TypeDecl * typeDecl ) {
    1921                         addToTyVarMap( typeDecl, scopeTyVars );
    1922                 }
    1923 
    1924                 void Pass3::premutate( PointerType * pointerType ) {
    1925                         GuardScope( scopeTyVars );
    1926                         makeTyVarMap( pointerType, scopeTyVars );
    1927                 }
    1928 
    1929                 void Pass3::premutate( FunctionType * functionType ) {
    1930                         GuardScope( scopeTyVars );
    1931                         makeTyVarMap( functionType, scopeTyVars );
    19321903                }
    19331904        } // anonymous namespace
     
    19391910// compile-command: "make install" //
    19401911// End: //
    1941 
  • src/GenPoly/ErasableScopedMap.h

    r34b4268 r24d6572  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ScopedMap.h --
     7// ErasableScopedMap.h --
    88//
    99// Author           : Aaron B. Moss
     
    5151        typedef typename Scope::const_pointer const_pointer;
    5252
    53         // Both iterator types are complete bidirection iterators, defined below.
     53        // Both iterator types are complete bidirectional iterators, see below.
    5454        class iterator;
    5555        class const_iterator;
     
    118118        std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
    119119
     120        Value& operator[] ( const Key &key ) {
     121                iterator slot = find( key );
     122                if ( slot != end() ) return slot->second;
     123                return insert( key, Value() ).first->second;
     124        }
     125
    120126        /// Marks the given element as erased from this scope inward; returns 1 for erased an element, 0 otherwise
    121127        size_type erase( const Key &key ) {
     
    130136        }
    131137
    132         Value& operator[] ( const Key &key ) {
    133                 iterator slot = find( key );
    134                 if ( slot != end() ) return slot->second;
    135                 return insert( key, Value() ).first->second;
     138        bool contains( const Key & key ) const {
     139                return find( key ) != cend();
    136140        }
    137141};
  • src/GenPoly/FindFunction.cc

    r34b4268 r24d6572  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Fri Feb 05 12:22:20 2016
    13 // Update Count     : 6
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct  7 17:05:20 2022
     13// Update Count     : 7
    1414//
    1515
     
    1818#include <utility>                      // for pair
    1919
     20#include "AST/Pass.hpp"                 // for Pass
     21#include "AST/Type.hpp"
    2022#include "Common/PassVisitor.h"         // for PassVisitor
    2123#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
     
    8991                handleForall( pointerType->get_forall() );
    9092        }
     93
     94namespace {
     95
     96struct FindFunctionCore :
     97                public ast::WithGuards,
     98                public ast::WithShortCircuiting,
     99                public ast::WithVisitorRef<FindFunctionCore> {
     100        FindFunctionCore(
     101                std::vector<ast::ptr<ast::FunctionType>> & functions,
     102                const TypeVarMap & typeVars, FindFunctionPred predicate,
     103                bool replaceMode );
     104
     105        void previsit( ast::FunctionType const * type );
     106        ast::Type const * postvisit( ast::FunctionType const * type );
     107        void previsit( ast::PointerType const * type );
     108private:
     109        void handleForall( const ast::FunctionType::ForallList & forall );
     110
     111        std::vector<ast::ptr<ast::FunctionType>> &functions;
     112        TypeVarMap typeVars;
     113        FindFunctionPred predicate;
     114        bool replaceMode;
     115};
     116
     117FindFunctionCore::FindFunctionCore(
     118                std::vector<ast::ptr<ast::FunctionType>> & functions,
     119                const TypeVarMap &typeVars, FindFunctionPred predicate,
     120                bool replaceMode ) :
     121        functions( functions ), typeVars( typeVars ),
     122        predicate( predicate ), replaceMode( replaceMode ) {}
     123
     124void FindFunctionCore::handleForall( const ast::FunctionType::ForallList & forall ) {
     125        for ( const ast::ptr<ast::TypeInstType> & td : forall ) {
     126                TypeVarMap::iterator var = typeVars.find( *td );
     127                if ( var != typeVars.end() ) {
     128                        typeVars.erase( var->first );
     129                } // if
     130        } // for
     131}
     132
     133void FindFunctionCore::previsit( ast::FunctionType const * type ) {
     134        visit_children = false;
     135        GuardScope( typeVars );
     136        handleForall( type->forall );
     137        //ast::accept_all( type->returns, *visitor );
     138        // This might have to become ast::mutate_each with return.
     139        ast::accept_each( type->returns, *visitor );
     140}
     141
     142ast::Type const * FindFunctionCore::postvisit( ast::FunctionType const * type ) {
     143        ast::Type const * ret = type;
     144        if ( predicate( type, typeVars ) ) {
     145                functions.push_back( type );
     146                if ( replaceMode ) {
     147                        // replace type parameters in function type with void*
     148                        ret = scrubTypeVars( ast::deepCopy( type ), typeVars );
     149                } // if
     150        } // if
     151        return ret;
     152}
     153
     154void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) {
     155        GuardScope( typeVars );
     156        //handleForall( type->forall );
     157}
     158
     159} // namespace
     160
     161void findFunction( const ast::Type * type,
     162                std::vector<ast::ptr<ast::FunctionType>> & functions,
     163                const TypeVarMap & typeVars, FindFunctionPred predicate ) {
     164        ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, false );
     165        type->accept( pass );
     166        //(void)type;
     167        //(void)functions;
     168        //(void)typeVars;
     169        //(void)predicate;
     170}
     171
     172const ast::Type * findAndReplaceFunction( const ast::Type * type,
     173                std::vector<ast::ptr<ast::FunctionType>> & functions,
     174                const TypeVarMap & typeVars, FindFunctionPred predicate ) {
     175        ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, true );
     176        return type->accept( pass );
     177        //(void)functions;
     178        //(void)typeVars;
     179        //(void)predicate;
     180        //return type;
     181}
     182
    91183} // namespace GenPoly
    92184
  • src/GenPoly/FindFunction.h

    r34b4268 r24d6572  
    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:23:36 2017
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct  7 10:30:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    3030        /// like `findFunction`, but also replaces the function type with void ()(void)
    3131        void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
     32
     33typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & );
     34
     35/// Recursively walks `type`, placing all functions that match `predicate`
     36/// under `typeVars` into `functions`.
     37void findFunction( const ast::Type * type,
     38                std::vector<ast::ptr<ast::FunctionType>> & functions,
     39                const TypeVarMap & typeVars, FindFunctionPred predicate );
     40/// Like findFunction, but also replaces the function type with `void ()(void)`.
     41const ast::Type * findAndReplaceFunction( const ast::Type * type,
     42                std::vector<ast::ptr<ast::FunctionType>> & functions,
     43                const TypeVarMap & typeVars, FindFunctionPred predicate );
     44
    3245} // namespace GenPoly
    3346
  • src/GenPoly/GenPoly.cc

    r34b4268 r24d6572  
    2424#include <vector>                       // for vector
    2525
     26#include "AST/Expr.hpp"
    2627#include "AST/Type.hpp"
     28#include "AST/TypeSubstitution.hpp"
    2729#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2830#include "ResolvExpr/typeops.h"         // for flatten
     
    170172
    171173                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    172                         if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
     174                        if ( tyVars.contains( typeInst->get_name() ) ) {
    173175                                return type;
    174176                        }
     
    187189
    188190                if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    189                         return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr;
     191                        if ( tyVars.contains( typeInst->typeString() ) ) return type;
    190192                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    191193                        return isPolyType( arrayType->base, env );
     
    203205
    204206        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    205                 if ( typeVars.find( *inst ) != typeVars.end() ) return type;
     207                if ( typeVars.contains( *inst ) ) return type;
    206208        } else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) {
    207209                return isPolyType( array->base, subst );
     
    272274                return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
    273275        }
     276
     277const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) {
     278        if ( func->returns.empty() ) return nullptr;
     279
     280        TypeVarMap forallTypes = { ast::TypeData() };
     281        makeTypeVarMap( func, forallTypes );
     282        return isDynType( func->returns.front(), forallTypes );
     283}
    274284
    275285        bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
     
    317327                return 0;
    318328        }
     329
     330const ast::Type * isPolyPtr(
     331                const ast::Type * type, const TypeVarMap & typeVars,
     332                const ast::TypeSubstitution * typeSubs ) {
     333        type = replaceTypeInst( type, typeSubs );
     334
     335        if ( auto * ptr = dynamic_cast<ast::PointerType const *>( type ) ) {
     336                return isPolyType( ptr->base, typeVars, typeSubs );
     337        }
     338        return nullptr;
     339}
    319340
    320341        Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
     
    391412
    392413                if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
    393                         if ( tyVars.find( typeInstType->get_name() ) != tyVars.end() ) {
     414                        if ( tyVars.contains( typeInstType->get_name() ) ) {
    394415                                return true;
    395416                        }
     
    490511                }
    491512
     513                /// Flattens a list of types.
     514                // There is another flattenList in Unify.
    492515                void flattenList( vector<ast::ptr<ast::Type>> const & src,
    493516                                vector<ast::ptr<ast::Type>> & out ) {
     
    792815        }
    793816
     817void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) {
     818        typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) );
     819}
     820
    794821void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) {
    795         typeVars.insert( *type, ast::TypeData( type->base ) );
     822        typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) );
    796823}
    797824
     
    818845}
    819846
     847void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) {
     848        for ( auto & typeDecl : decl->type_params ) {
     849                addToTypeVarMap( typeDecl, typeVars );
     850        }
     851}
     852
    820853        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
    821854                for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
  • src/GenPoly/GenPoly.h

    r34b4268 r24d6572  
    111111        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
    112112        void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars );
     113        void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars );
    113114
    114115        /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
    115116        void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
    116117        void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars );
     118        void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars );
    117119
    118120        /// Prints type variable map
  • src/GenPoly/InstantiateGeneric.cc

    r34b4268 r24d6572  
    2828#include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
    2929#include "InitTweak/InitTweak.h"
    30 #include "ResolvExpr/typeops.h"
     30#include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
     31#include "ResolvExpr/Unify.h"          // for typesCompatible
    3132#include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
    3233#include "ScrubTyVars.h"               // for ScrubTyVars
  • src/GenPoly/InstantiateGenericNew.cpp

    r34b4268 r24d6572  
    3232#include "GenPoly/GenPoly.h"           // for isPolyType, typesPolyCompatible
    3333#include "GenPoly/ScrubTyVars.h"       // for scrubAll
    34 #include "ResolvExpr/typeops.h"        // for typesCompatible
     34#include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
     35#include "ResolvExpr/Unify.h"          // for typesCompatible
    3536
    3637namespace GenPoly {
     
    361362                        ResolvExpr::typesCompatible(
    362363                                memberExpr->result,
    363                                 memberExpr->member->get_type(), ast::SymbolTable() ) ) {
     364                                memberExpr->member->get_type() ) ) {
    364365                return memberExpr;
    365366        }
  • src/GenPoly/Lvalue.cc

    r34b4268 r24d6572  
    1717#include <string>                        // for string
    1818
     19#include "Common/ToString.hpp"           // for toCString
    1920#include "Common/UniqueName.h"
    2021#include "Common/PassVisitor.h"
  • src/GenPoly/LvalueNew.cpp

    r34b4268 r24d6572  
    2525#include "AST/Pass.hpp"
    2626#include "Common/SemanticError.h"      // for SemanticWarning
     27#include "Common/ToString.hpp"         // for toCString
    2728#include "Common/UniqueName.h"         // for UniqueName
    2829#include "GenPoly/GenPoly.h"           // for genFunctionType
     
    358359                                !ResolvExpr::typesCompatible(
    359360                                        srcType,
    360                                         strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base,
    361                                         ast::SymbolTable() ) ) {
     361                                        strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base ) ) {
    362362                        // Must keep cast if cast-to type is different from the actual type.
    363363                        return ast::mutate_field( expr, &ast::CastExpr::arg, ret );
     
    376376                if ( !ResolvExpr::typesCompatibleIgnoreQualifiers(
    377377                                dstType->stripReferences(),
    378                                 srcType->stripReferences(),
    379                                 ast::SymbolTable() ) ) {
     378                                srcType->stripReferences() ) ) {
    380379                        return ast::mutate_field( expr, &ast::CastExpr::arg, ret );
    381380                }
     
    392391                                ResolvExpr::typesCompatible(
    393392                                        expr->result,
    394                                         expr->arg->result, ast::SymbolTable() ) ) {
     393                                        expr->arg->result ) ) {
    395394                        PRINT(
    396395                                std::cerr << "types are compatible, removing cast: " << expr << '\n';
     
    589588                ast::OpenVarSet openVars;
    590589                ResolvExpr::unify( ret->arg2->result, ret->arg3->result, newEnv,
    591                         needAssertions, haveAssertions, openVars,
    592                         ast::SymbolTable(), common );
     590                        needAssertions, haveAssertions, openVars, common );
    593591                ret->result = common ? common : ast::deepCopy( ret->arg2->result );
    594592                return ret;
  • src/GenPoly/ScopedSet.h

    r34b4268 r24d6572  
    2121
    2222namespace GenPoly {
    23         /// A set where the items are placed into nested scopes;
    24         /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
    25         template<typename Value>
    26         class ScopedSet {
    27                 typedef std::set< Value > Scope;
    28                 typedef std::vector< Scope > ScopeList;
    29 
    30                 ScopeList scopes; ///< scoped list of sets
    31         public:
    32                 typedef typename Scope::key_type key_type;
    33                 typedef typename Scope::value_type value_type;
    34                 typedef typename ScopeList::size_type size_type;
    35                 typedef typename ScopeList::difference_type difference_type;
    36                 typedef typename Scope::reference reference;
    37                 typedef typename Scope::const_reference const_reference;
    38                 typedef typename Scope::pointer pointer;
    39                 typedef typename Scope::const_pointer const_pointer;
    40 
    41                 class iterator : public std::iterator< std::bidirectional_iterator_tag,
    42                                                        value_type > {
    43                 friend class ScopedSet;
    44                 friend class const_iterator;
    45                         typedef typename std::set< Value >::iterator wrapped_iterator;
    46                         typedef typename std::vector< std::set< Value > > scope_list;
    47                         typedef typename scope_list::size_type size_type;
    48 
    49                         /// Checks if this iterator points to a valid item
    50                         bool is_valid() const {
    51                                 return it != (*scopes)[i].end();
    52                         }
    53 
    54                         /// Increments on invalid
    55                         iterator& next_valid() {
    56                                 if ( ! is_valid() ) { ++(*this); }
    57                                 return *this;
    58                         }
    59 
    60                         /// Decrements on invalid
    61                         iterator& prev_valid() {
    62                                 if ( ! is_valid() ) { --(*this); }
    63                                 return *this;
    64                         }
    65 
    66                         iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
    67                                 : scopes(&_scopes), it(_it), i(_i) {}
    68                 public:
    69                         iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    70                         iterator& operator= (const iterator &that) {
    71                                 scopes = that.scopes; i = that.i; it = that.it;
    72                                 return *this;
    73                         }
    74 
    75                         reference operator* () { return *it; }
    76                         pointer operator-> () { return it.operator->(); }
    77 
    78                         iterator& operator++ () {
    79                                 if ( it == (*scopes)[i].end() ) {
    80                                         if ( i == 0 ) return *this;
    81                                         --i;
    82                                         it = (*scopes)[i].begin();
    83                                 } else {
    84                                         ++it;
    85                                 }
    86                                 return next_valid();
    87                         }
    88                         iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    89 
    90                         iterator& operator-- () {
    91                                 // may fail if this is the begin iterator; allowed by STL spec
    92                                 if ( it == (*scopes)[i].begin() ) {
    93                                         ++i;
    94                                         it = (*scopes)[i].end();
    95                                 }
    96                                 --it;
    97                                 return prev_valid();
    98                         }
    99                         iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    100 
    101                         bool operator== (const iterator &that) {
    102                                 return scopes == that.scopes && i == that.i && it == that.it;
    103                         }
    104                         bool operator!= (const iterator &that) { return !( *this == that ); }
    105 
    106                         size_type get_level() const { return i; }
    107 
    108                 private:
    109                         scope_list const *scopes;
    110                         wrapped_iterator it;
    111                         size_type i;
    112                 };
    113 
    114                 class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
    115                                                              value_type > {
    116                 friend class ScopedSet;
    117                         typedef typename std::set< Value >::iterator wrapped_iterator;
    118                         typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
    119                         typedef typename std::vector< std::set< Value > > scope_list;
    120                         typedef typename scope_list::size_type size_type;
    121 
    122                         /// Checks if this iterator points to a valid item
    123                         bool is_valid() const {
    124                                 return it != (*scopes)[i].end();
    125                         }
    126 
    127                         /// Increments on invalid
    128                         const_iterator& next_valid() {
    129                                 if ( ! is_valid() ) { ++(*this); }
    130                                 return *this;
    131                         }
    132 
    133                         /// Decrements on invalid
    134                         const_iterator& prev_valid() {
    135                                 if ( ! is_valid() ) { --(*this); }
    136                                 return *this;
    137                         }
    138 
    139                         const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
    140                                 : scopes(&_scopes), it(_it), i(_i) {}
    141                 public:
    142                         const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    143                         const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    144                         const_iterator& operator= (const iterator &that) {
    145                                 scopes = that.scopes; i = that.i; it = that.it;
    146                                 return *this;
    147                         }
    148                         const_iterator& operator= (const const_iterator &that) {
    149                                 scopes = that.scopes; i = that.i; it = that.it;
    150                                 return *this;
    151                         }
    152 
    153                         const_reference operator* () { return *it; }
    154                         const_pointer operator-> () { return it.operator->(); }
    155 
    156                         const_iterator& operator++ () {
    157                                 if ( it == (*scopes)[i].end() ) {
    158                                         if ( i == 0 ) return *this;
    159                                         --i;
    160                                         it = (*scopes)[i].begin();
    161                                 } else {
    162                                         ++it;
    163                                 }
    164                                 return next_valid();
    165                         }
    166                         const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    167 
    168                         const_iterator& operator-- () {
    169                                 // may fail if this is the begin iterator; allowed by STL spec
    170                                 if ( it == (*scopes)[i].begin() ) {
    171                                         ++i;
    172                                         it = (*scopes)[i].end();
    173                                 }
    174                                 --it;
    175                                 return prev_valid();
    176                         }
    177                         const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    178 
    179                         bool operator== (const const_iterator &that) {
    180                                 return scopes == that.scopes && i == that.i && it == that.it;
    181                         }
    182                         bool operator!= (const const_iterator &that) { return !( *this == that ); }
    183 
    184                         size_type get_level() const { return i; }
    185 
    186                 private:
    187                         scope_list const *scopes;
    188                         wrapped_const_iterator it;
    189                         size_type i;
    190                 };
    191 
    192                 /// Starts a new scope
    193                 void beginScope() {
    194                         Scope scope;
    195                         scopes.push_back(scope);
    196                 }
    197 
    198                 /// Ends a scope; invalidates any iterators pointing to elements of that scope
    199                 void endScope() {
    200                         scopes.pop_back();
    201                 }
    202 
    203                 /// Default constructor initializes with one scope
    204                 ScopedSet() { beginScope(); }
    205 
    206                 iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    207                 const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    208                 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    209                 iterator end() { return iterator(scopes, scopes[0].end(), 0); }
    210                 const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
    211                 const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
    212 
    213                 /// Gets the index of the current scope (counted from 1)
    214                 size_type currentScope() const { return scopes.size(); }
    215 
    216                 /// Finds the given key in the outermost scope it occurs; returns end() for none such
    217                 iterator find( const Value &key ) {
    218                         for ( size_type i = scopes.size() - 1; ; --i ) {
    219                                 typename Scope::iterator val = scopes[i].find( key );
    220                                 if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    221                                 if ( i == 0 ) break;
    222                         }
    223                         return end();
    224                 }
    225                 const_iterator find( const Value &key ) const {
    226                         return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
    227                 }
    228 
    229                 /// Finds the given key in the outermost scope inside the given scope where it occurs
    230                 iterator findNext( const_iterator &it, const Value &key ) {
    231                         if ( it.i == 0 ) return end();
     23
     24/// A set where the items are placed into nested scopes;
     25/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
     26template<typename Value>
     27class ScopedSet {
     28        typedef std::set< Value > Scope;
     29        typedef std::vector< Scope > ScopeList;
     30
     31        /// Scoped list of sets.
     32        ScopeList scopes;
     33public:
     34        typedef typename Scope::key_type key_type;
     35        typedef typename Scope::value_type value_type;
     36        typedef typename ScopeList::size_type size_type;
     37        typedef typename ScopeList::difference_type difference_type;
     38        typedef typename Scope::reference reference;
     39        typedef typename Scope::const_reference const_reference;
     40        typedef typename Scope::pointer pointer;
     41        typedef typename Scope::const_pointer const_pointer;
     42
     43        // Both iterator types are complete bidirectional iterators, see below.
     44        class iterator;
     45        class const_iterator;
     46
     47        /// Starts a new scope
     48        void beginScope() {
     49                Scope scope;
     50                scopes.push_back(scope);
     51        }
     52
     53        /// Ends a scope; invalidates any iterators pointing to elements of that scope
     54        void endScope() {
     55                scopes.pop_back();
     56        }
     57
     58        /// Default constructor initializes with one scope
     59        ScopedSet() { beginScope(); }
     60
     61        iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     62        const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     63        const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     64        iterator end() { return iterator(scopes, scopes[0].end(), 0); }
     65        const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
     66        const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
     67
     68        /// Gets the index of the current scope (counted from 1)
     69        size_type currentScope() const { return scopes.size(); }
     70
     71        /// Finds the given key in the outermost scope it occurs; returns end() for none such
     72        iterator find( const Value &key ) {
     73                for ( size_type i = scopes.size() - 1; ; --i ) {
     74                        typename Scope::iterator val = scopes[i].find( key );
     75                        if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     76                        if ( i == 0 ) break;
     77                }
     78                return end();
     79        }
     80        const_iterator find( const Value &key ) const {
     81                return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
     82        }
     83
     84        /// Finds the given key in the outermost scope inside the given scope where it occurs
     85        iterator findNext( const_iterator &it, const Value &key ) {
     86                if ( it.i == 0 ) return end();
    23287                        for ( size_type i = it.i - 1; ; --i ) {
    233                                 typename Scope::iterator val = scopes[i].find( key );
    234                                 if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    235                                 if ( i == 0 ) break;
    236                         }
    237                         return end();
    238                 }
    239                 const_iterator findNext( const_iterator &it, const Value &key ) const {
    240                         return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
    241                 }
    242 
    243                 /// Inserts the given value into the outermost scope
    244                 std::pair< iterator, bool > insert( const value_type &value ) {
    245                         std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
    246                         return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
    247                 }
    248 
    249         };
     88                        typename Scope::iterator val = scopes[i].find( key );
     89                        if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     90                        if ( i == 0 ) break;
     91                }
     92                return end();
     93        }
     94        const_iterator findNext( const_iterator &it, const Value &key ) const {
     95                return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
     96        }
     97
     98        /// Inserts the given value into the outermost scope
     99        std::pair< iterator, bool > insert( const value_type &value ) {
     100                std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
     101                return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
     102        }
     103
     104        bool contains( const Value & key ) const {
     105                return find( key ) != cend();
     106        }
     107};
     108
     109template<typename Value>
     110class ScopedSet<Value>::iterator :
     111                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     112        friend class ScopedSet;
     113        friend class const_iterator;
     114        typedef typename std::set< Value >::iterator wrapped_iterator;
     115        typedef typename std::vector< std::set< Value > > scope_list;
     116        typedef typename scope_list::size_type size_type;
     117
     118        /// Checks if this iterator points to a valid item
     119        bool is_valid() const {
     120                return it != (*scopes)[i].end();
     121        }
     122
     123        /// Increments on invalid
     124        iterator& next_valid() {
     125                if ( ! is_valid() ) { ++(*this); }
     126                return *this;
     127        }
     128
     129        /// Decrements on invalid
     130        iterator& prev_valid() {
     131                if ( ! is_valid() ) { --(*this); }
     132                return *this;
     133        }
     134
     135        iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
     136                : scopes(&_scopes), it(_it), i(_i) {}
     137public:
     138        iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     139        iterator& operator= (const iterator &that) {
     140                scopes = that.scopes; i = that.i; it = that.it;
     141                return *this;
     142        }
     143
     144        reference operator* () { return *it; }
     145        pointer operator-> () { return it.operator->(); }
     146
     147        iterator& operator++ () {
     148                if ( it == (*scopes)[i].end() ) {
     149                        if ( i == 0 ) return *this;
     150                        --i;
     151                        it = (*scopes)[i].begin();
     152                } else {
     153                        ++it;
     154                }
     155                return next_valid();
     156        }
     157        iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     158
     159        iterator& operator-- () {
     160                // may fail if this is the begin iterator; allowed by STL spec
     161                if ( it == (*scopes)[i].begin() ) {
     162                        ++i;
     163                        it = (*scopes)[i].end();
     164                }
     165                --it;
     166                return prev_valid();
     167        }
     168        iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     169
     170        bool operator== (const iterator &that) {
     171                return scopes == that.scopes && i == that.i && it == that.it;
     172        }
     173        bool operator!= (const iterator &that) { return !( *this == that ); }
     174
     175        size_type get_level() const { return i; }
     176
     177private:
     178        scope_list const *scopes;
     179        wrapped_iterator it;
     180        size_type i;
     181};
     182
     183template<typename Value>
     184class ScopedSet<Value>::const_iterator :
     185                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     186        friend class ScopedSet;
     187        typedef typename std::set< Value >::iterator wrapped_iterator;
     188        typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
     189        typedef typename std::vector< std::set< Value > > scope_list;
     190        typedef typename scope_list::size_type size_type;
     191
     192        /// Checks if this iterator points to a valid item
     193        bool is_valid() const {
     194                return it != (*scopes)[i].end();
     195        }
     196
     197        /// Increments on invalid
     198        const_iterator& next_valid() {
     199                if ( ! is_valid() ) { ++(*this); }
     200                return *this;
     201        }
     202
     203        /// Decrements on invalid
     204        const_iterator& prev_valid() {
     205                if ( ! is_valid() ) { --(*this); }
     206                return *this;
     207        }
     208
     209        const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
     210                : scopes(&_scopes), it(_it), i(_i) {}
     211public:
     212        const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     213        const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     214        const_iterator& operator= (const iterator &that) {
     215                scopes = that.scopes; i = that.i; it = that.it;
     216                return *this;
     217        }
     218        const_iterator& operator= (const const_iterator &that) {
     219                scopes = that.scopes; i = that.i; it = that.it;
     220                return *this;
     221        }
     222
     223        const_reference operator* () { return *it; }
     224        const_pointer operator-> () { return it.operator->(); }
     225
     226        const_iterator& operator++ () {
     227                if ( it == (*scopes)[i].end() ) {
     228                        if ( i == 0 ) return *this;
     229                        --i;
     230                        it = (*scopes)[i].begin();
     231                } else {
     232                        ++it;
     233                }
     234                return next_valid();
     235        }
     236        const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     237
     238        const_iterator& operator-- () {
     239                // may fail if this is the begin iterator; allowed by STL spec
     240                if ( it == (*scopes)[i].begin() ) {
     241                        ++i;
     242                        it = (*scopes)[i].end();
     243                }
     244                --it;
     245                return prev_valid();
     246        }
     247        const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     248
     249        bool operator== (const const_iterator &that) {
     250                return scopes == that.scopes && i == that.i && it == that.it;
     251        }
     252        bool operator!= (const const_iterator &that) { return !( *this == that ); }
     253
     254        size_type get_level() const { return i; }
     255
     256private:
     257        scope_list const *scopes;
     258        wrapped_const_iterator it;
     259        size_type i;
     260};
     261
    250262} // namespace GenPoly
    251263
  • src/GenPoly/ScrubTyVars.cc

    r34b4268 r24d6572  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  7 15:42:00 2022
    13 // Update Count     : 5
     12// Last Modified On : Wed Dec  7 17:01:00 2022
     13// Update Count     : 6
    1414//
    1515
     
    117117namespace {
    118118
    119 enum class ScrubMode {
    120         FromMap,
    121         DynamicFromMap,
    122         All,
    123 };
    124 
    125119struct ScrubTypeVars :
    126120        public ast::WithGuards,
     
    184178
    185179ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
     180        ast::TypeDecl::Kind kind;
    186181        // This implies that mode == ScrubMode::All.
    187182        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 );
    198         if ( typeVar == typeVars->end() ) {
    199                 return type;
    200         }
    201 
    202         switch ( typeVar->second.kind ) {
    203         case ::TypeDecl::Dtype:
    204         case ::TypeDecl::Ttype:
     183                kind = type->kind;
     184        } else {
     185                // Otherwise, only scrub the type var if it is in map.
     186                auto typeVar = typeVars->find( *type );
     187                if ( typeVar == typeVars->end() ) {
     188                        return type;
     189                }
     190                kind = typeVar->second.kind;
     191        }
     192
     193        switch ( kind ) {
     194        case ast::TypeDecl::Dtype:
     195        case ast::TypeDecl::Ttype:
    205196                return new ast::PointerType(
    206197                        new ast::VoidType( type->qualifiers ) );
    207         case ::TypeDecl::Ftype:
     198        case ast::TypeDecl::Ftype:
    208199                return new ast::PointerType(
    209200                        new ast::FunctionType( ast::VariableArgs ) );
    210201        default:
    211                 assertf( false,
    212                         "Unhandled type variable kind: %d", typeVar->second.kind );
     202                assertf( false, "Unhandled type variable kind: %d", kind );
    213203                throw; // Just in case the assert is removed, stop here.
    214204        }
     
    253243}
    254244
     245} // namespace
     246
    255247const ast::Node * scrubTypeVarsBase(
    256                 const ast::Node * target,
    257                 ScrubMode mode, const TypeVarMap * typeVars ) {
     248                const ast::Node * node, const TypeVarMap * typeVars, ScrubMode mode ) {
    258249        if ( ScrubMode::All == mode ) {
    259250                assert( nullptr == typeVars );
     
    262253        }
    263254        ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
    264         return target->accept( visitor );
    265 }
    266 
    267 } // namespace
    268 
    269 template<>
    270 ast::Node const * scrubTypeVars<ast::Node>(
    271         const ast::Node * target, const TypeVarMap & typeVars ) {
    272         return scrubTypeVarsBase( target, ScrubMode::FromMap, &typeVars );
    273 }
    274 
    275 template<>
    276 ast::Node const * scrubTypeVarsDynamic<ast::Node>(
    277         ast::Node const * target, const TypeVarMap & typeVars ) {
    278         return scrubTypeVarsBase( target, ScrubMode::DynamicFromMap, &typeVars );
    279 }
    280 
    281 template<>
    282 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) {
    283         return scrubTypeVarsBase( target, ScrubMode::All, nullptr );
     255        return node->accept( visitor );
    284256}
    285257
  • src/GenPoly/ScrubTyVars.h

    r34b4268 r24d6572  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  7 15:51:00 2022
    13 // Update Count     : 4
     12// Last Modified On : Wed Dec  7 16:57:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    109109        }
    110110
     111// ScrubMode and scrubTypeVarsBase are internal.
     112enum class ScrubMode { FromMap, DynamicFromMap, All };
     113
     114const ast::Node * scrubTypeVarsBase(
     115        const ast::Node * target, const TypeVarMap * typeVars, ScrubMode mode );
     116
     117
    111118/// For all polymorphic types with type variables in `typeVars`,
    112119/// replaces generic types, dtypes, and ftypes with the appropriate void type,
     
    116123                node_t const * target, const TypeVarMap & typeVars ) {
    117124        return strict_dynamic_cast<node_t const *>(
    118                         scrubTypeVars<ast::Node>( target, typeVars ) );
     125                        scrubTypeVarsBase( target, &typeVars, ScrubMode::FromMap ) );
    119126}
    120127
     
    123130/// and sizeof/alignof expressions with the proper variable.
    124131template<typename node_t>
    125 ast::Node const * scrubTypeVarsDynamic(
     132node_t const * scrubTypeVarsDynamic(
    126133                node_t const * target, const TypeVarMap & typeVars ) {
    127134        return strict_dynamic_cast<node_t const *>(
    128                         scrubTypeVarsDynamic<ast::Node>( target, typeVars ) );
     135                        scrubTypeVarsBase( target, &typeVars, ScrubMode::DynamicFromMap ) );
    129136}
    130137
     
    134141node_t const * scrubAllTypeVars( node_t const * target ) {
    135142        return strict_dynamic_cast<node_t const *>(
    136                         scrubAllTypeVars<ast::Node>( target ) );
     143                        scrubTypeVarsBase( target, nullptr, ScrubMode::All ) );
    137144}
    138 
    139 // We specialize for Node as a base case.
    140 template<>
    141 ast::Node const * scrubTypeVars<ast::Node>(
    142                 const ast::Node * target, const TypeVarMap & typeVars );
    143 
    144 template<>
    145 ast::Node const * scrubTypeVarsDynamic<ast::Node>(
    146                 ast::Node const * target, const TypeVarMap & typeVars );
    147 
    148 template<>
    149 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target );
    150145
    151146} // namespace GenPoly
  • src/GenPoly/SpecializeNew.cpp

    r34b4268 r24d6572  
    1616#include "Specialize.h"
    1717
     18#include "AST/Copy.hpp"                  // for deepCopy
    1819#include "AST/Inspect.hpp"               // for isIntrinsicCallExpr
    1920#include "AST/Pass.hpp"                  // for Pass
Note: See TracChangeset for help on using the changeset viewer.