Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    r974906e2 rbd85400  
    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 : Thu Jan 07 13:40:05 2016
    13 // Update Count     : 219
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Feb  5 16:45:07 2016
     13// Update Count     : 286
    1414//
    1515
     
    2222
    2323#include "Box.h"
     24#include "InstantiateGeneric.h"
    2425#include "PolyMutator.h"
    2526#include "FindFunction.h"
     27#include "ScopedMap.h"
    2628#include "ScrubTyVars.h"
    2729
     
    3941#include "SymTab/Mangler.h"
    4042
    41 #include "SemanticError.h"
    42 #include "UniqueName.h"
    43 #include "utility.h"
     43#include "Common/SemanticError.h"
     44#include "Common/UniqueName.h"
     45#include "Common/utility.h"
    4446
    4547#include <ext/functional> // temporary
     
    6971                        virtual void doEndScope();
    7072                  private:
     73                        /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
     74                        Expression *makeOffsetArray( StructInstType *type );
     75                        /// passes extra type parameters into a polymorphic function application
    7176                        void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
     77                        /// wraps a function application with a new temporary for the out-parameter return value
    7278                        Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
    73                         Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg );
     79                        /// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment
     80                        void replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params );
     81                        /// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete).
     82                        /// If `doClone` is set to false, will not clone interior types
     83                        Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true );
     84                        /// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
     85                        Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg );
    7486                        Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    7587                        void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
    7688                        void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    7789                        void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
     90                        /// Stores assignment operators from assertion list in local map of assignment operations
    7891                        void findAssignOps( const std::list< TypeDecl *> &forall );
    7992                        void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
    8093                        FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
     94                        /// Replaces intrinsic operator functions with their arithmetic desugaring
    8195                        Expression *handleIntrinsics( ApplicationExpr *appExpr );
     96                        /// Inserts a new temporary variable into the current scope with an auto-generated name
    8297                        ObjectDecl *makeTemporary( Type *type );
    8398
    8499                        typedef std::map< std::string, DeclarationWithType *> AdapterMap;
    85100                        std::map< std::string, DeclarationWithType *> assignOps;
     101                        ScopedMap< std::string, DeclarationWithType *> scopedAssignOps;
    86102                        std::stack< AdapterMap > adapters;
    87103                        DeclarationWithType *retval;
     
    107123                };
    108124
    109                 /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable
    110                 class Pass3 : public PolyMutator {
     125                /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
     126                /// also fixes offsetof expressions.
     127                class MemberExprFixer : public PolyMutator {
    111128                  public:
    112129                        template< typename DeclClass >
     
    119136                        virtual Type *mutate( PointerType *pointerType );
    120137                        virtual Type *mutate( FunctionType *funcType );
     138                        virtual Expression *mutate( MemberExpr *memberExpr );
     139                        virtual Expression *mutate( OffsetofExpr *offsetofExpr );
     140                };
     141
     142                /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable
     143                class Pass3 : public PolyMutator {
     144                  public:
     145                        template< typename DeclClass >
     146                        DeclClass *handleDecl( DeclClass *decl, Type *type );
     147                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
     148                        virtual ObjectDecl *mutate( ObjectDecl *objectDecl );
     149                        virtual TypedefDecl *mutate( TypedefDecl *objectDecl );
     150                        virtual TypeDecl *mutate( TypeDecl *objectDecl );
     151                        virtual Type *mutate( PointerType *pointerType );
     152                        virtual Type *mutate( FunctionType *funcType );
    121153                  private:
    122154                };
     
    133165        }
    134166
     167        /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
     168        template< typename MutatorType >
     169        inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) {
     170                bool seenIntrinsic = false;
     171                SemanticError errors;
     172                for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
     173                        try {
     174                                if ( *i ) {
     175                                        if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) {
     176                                                seenIntrinsic = true;
     177                                        } else if ( seenIntrinsic ) {
     178                                                seenIntrinsic = false; // break on this line when debugging for end of prelude
     179                                        }
     180
     181                                        *i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) );
     182                                        assert( *i );
     183                                } // if
     184                        } catch( SemanticError &e ) {
     185                                errors.append( e );
     186                        } // try
     187                } // for
     188                if ( ! errors.isEmpty() ) {
     189                        throw errors;
     190                } // if
     191        }
     192
    135193        void box( std::list< Declaration *>& translationUnit ) {
    136194                Pass1 pass1;
    137195                Pass2 pass2;
     196                MemberExprFixer memberFixer;
    138197                Pass3 pass3;
    139                 mutateAll( translationUnit, pass1 );
    140                 mutateAll( translationUnit, pass2 );
    141                 mutateAll( translationUnit, pass3 );
     198                mutateTranslationUnit/*All*/( translationUnit, pass1 );
     199                mutateTranslationUnit/*All*/( translationUnit, pass2 );
     200                instantiateGeneric( translationUnit );
     201                mutateTranslationUnit/*All*/( translationUnit, memberFixer );
     202                mutateTranslationUnit/*All*/( translationUnit, pass3 );
    142203        }
    143204
     
    185246                }
    186247
    187                 // returns true if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be)
    188                 bool checkAssignment( DeclarationWithType *decl, std::string &name ) {
     248                /// returns T if the given declaration is: (*?=?)(T *, T) for some T (return not checked, but maybe should be), NULL otherwise
     249                ReferenceToType *isAssignment( DeclarationWithType *decl ) {
    189250                        if ( decl->get_name() == "?=?" ) {
    190                                 if ( PointerType *ptrType = dynamic_cast< PointerType *>( decl->get_type() ) ) {
    191                                         if ( FunctionType *funType = dynamic_cast< FunctionType *>( ptrType->get_base() ) ) {
    192                                                 if ( funType->get_parameters().size() == 2 ) {
    193                                                         if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
    194                                                                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
    195                                                                         if ( TypeInstType *typeInst2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
    196                                                                                 if ( typeInst->get_name() == typeInst2->get_name() ) {
    197                                                                                         name = typeInst->get_name();
    198                                                                                         return true;
    199                                                                                 } // if
     251                                if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
     252                                        if ( funType->get_parameters().size() == 2 ) {
     253                                                if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {
     254                                                        if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( pointer->get_base() ) ) {
     255                                                                if ( ReferenceToType *refType2 = dynamic_cast< ReferenceToType *>( funType->get_parameters().back()->get_type() ) ) {
     256                                                                        if ( refType->get_name() == refType2->get_name() ) {
     257                                                                                return refType;
    200258                                                                        } // if
    201259                                                                } // if
     
    205263                                } // if
    206264                        } // if
    207                         return false;
     265                        return 0;
    208266                }
    209267
     
    214272                                for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    215273                                        std::string typeName;
    216                                         if ( checkAssignment( *assert, typeName ) ) {
    217                                                 assignOps[ typeName ] = *assert;
     274                                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert ) ) ) {
     275                                                assignOps[ typeInst->get_name() ] = *assert;
    218276                                        } // if
    219277                                } // for
     
    222280
    223281                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
     282                        // if this is a polymorphic assignment function, put it in the map for this scope
     283                        if ( ReferenceToType *refType = isAssignment( functionDecl ) ) {
     284                                if ( ! dynamic_cast< TypeInstType* >( refType ) ) {
     285                                        scopedAssignOps.insert( refType->get_name(), functionDecl );
     286                                }
     287                        }
     288
    224289                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    225290                                doBeginScope();
     
    231296                                // process polymorphic return value
    232297                                retval = 0;
    233                                 std::string typeName;
    234                                 if ( isPolyRet( functionDecl->get_functionType(), typeName ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
     298                                if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
    235299                                        retval = functionDecl->get_functionType()->get_returnVals().front();
    236300
     
    256320                                        findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
    257321                                } // for
     322
    258323                                AdapterMap & adapters = Pass1::adapters.top();
    259324                                for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
     
    304369                        return condExpr;
    305370
     371                }
     372
     373                Expression *Pass1::makeOffsetArray( StructInstType *ty ) {
     374                        std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
     375
     376                        // make a new temporary array
     377                        Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     378                        std::stringstream lenGen;
     379                        lenGen << baseMembers.size();
     380                        ConstantExpr *lenExpr = new ConstantExpr( Constant( offsetType->clone(), lenGen.str() ) );
     381                        ObjectDecl *arrayTemp = makeTemporary( new ArrayType( Type::Qualifiers(), offsetType, lenExpr, false, false ) );
     382
     383                        // build initializer list for temporary
     384                        std::list< Initializer* > inits;
     385                        for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
     386                                DeclarationWithType *memberDecl;
     387                                if ( DeclarationWithType *origMember = dynamic_cast< DeclarationWithType* >( *member ) ) {
     388                                        memberDecl = origMember->clone();
     389                                } else {
     390                                        memberDecl = new ObjectDecl( (*member)->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, offsetType->clone(), 0 );
     391                                }
     392                                inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
     393                        }
     394                        arrayTemp->set_init( new ListInit( inits ) );
     395
     396                        // return variable pointing to temporary
     397                        return new VariableExpr( arrayTemp );
    306398                }
    307399
     
    325417
    326418                        // add size/align for generic types to parameter list
    327                         //assert( ! appExpr->get_function()->get_results().empty() );
    328419                        if ( appExpr->get_function()->get_results().empty() ) return;
    329420                        FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() );
     
    334425                        std::set< std::string > seenTypes; //< names for generic types we've seen
    335426                        for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
    336                                 Type *parmType = (*fnParm)->get_type();
    337                                 if ( ! dynamic_cast< TypeInstType* >( parmType ) && isPolyType( parmType, exprTyVars ) ) {
    338                                         std::string sizeName = sizeofName( parmType );
     427                                Type *polyBase = hasPolyBase( (*fnParm)->get_type(), exprTyVars );
     428                                if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
     429                                        std::string sizeName = sizeofName( polyBase );
    339430                                        if ( seenTypes.count( sizeName ) ) continue;
    340431
    341                                         assert( ! (*fnArg)->get_results().empty() );
    342                                         Type *argType = (*fnArg)->get_results().front();
    343                                         arg = appExpr->get_args().insert( arg, new SizeofExpr( argType->clone() ) );
     432                                        VariableExpr *fnArgBase = getBaseVar( *fnArg );
     433                                        assert( fnArgBase && ! fnArgBase->get_results().empty() );
     434                                        Type *argBaseType = fnArgBase->get_results().front();
     435                                        arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
    344436                                        arg++;
    345                                         arg = appExpr->get_args().insert( arg, new AlignofExpr( argType->clone() ) );
     437                                        arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
    346438                                        arg++;
     439                                        if ( dynamic_cast< StructInstType* >( polyBase ) ) {
     440                                                if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
     441                                                        arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
     442                                                        arg++;
     443                                                } else {
     444                                                        throw SemanticError( "Cannot pass non-struct type for generic struct" );
     445                                                }
     446                                        }
    347447
    348448                                        seenTypes.insert( sizeName );
     
    386486                }
    387487
    388                 Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ) {
    389                         ResolvExpr::EqvClass eqvClass;
     488                void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) {
     489                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
     490                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     491                                assert(paramType && "Aggregate parameters should be type expressions");
     492                                paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) );
     493                        }
     494                }
     495
     496                Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) {
     497                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
     498                                Type *concrete = env->lookup( typeInst->get_name() );
     499                                if ( concrete == 0 ) {
     500                                        throw SemanticError( "Unbound type variable " + typeInst->get_name() + " in ", appExpr );
     501                                } // if
     502                                return concrete;
     503                        } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
     504                                if ( doClone ) {
     505                                        structType = structType->clone();
     506                                }
     507                                replaceParametersWithConcrete( appExpr, structType->get_parameters() );
     508                                return structType;
     509                        } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
     510                                if ( doClone ) {
     511                                        unionType = unionType->clone();
     512                                }
     513                                replaceParametersWithConcrete( appExpr, unionType->get_parameters() );
     514                                return unionType;
     515                        }
     516                        return type;
     517                }
     518
     519                Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ) {
    390520                        assert( env );
    391                         Type *concrete = env->lookup( typeName );
    392                         if ( concrete == 0 ) {
    393                                 throw SemanticError( "Unbound type variable " + typeName + " in ", appExpr );
    394                         } // if
     521                        Type *concrete = replaceWithConcrete( appExpr, polyType );
    395522                        return addRetParam( appExpr, function, concrete, arg );
    396523                }
     
    404531                        std::string adapterName = makeAdapterName( mangleName );
    405532
    406                         appExpr->get_args().push_front( appExpr->get_function() );
     533                        // cast adaptee to void (*)(), since it may have any type inside a polymorphic function
     534                        Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
     535                        appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) );
    407536                        appExpr->set_function( new NameExpr( adapterName ) );
    408537
     
    412541                void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
    413542                        assert( ! arg->get_results().empty() );
    414 //   if ( ! dynamic_cast< PointerType *>( arg->get_results().front() ) ) {
    415                         TypeInstType *typeInst = dynamic_cast< TypeInstType *>( param );
    416                         if ( typeInst && exprTyVars.find( typeInst->get_name() ) != exprTyVars.end() ) {
     543                        if ( isPolyType( param, exprTyVars ) ) {
    417544                                if ( dynamic_cast< TypeInstType *>( arg->get_results().front() ) ) {
    418545                                        // if the argument's type is a type parameter, we don't need to box again!
     
    422549                                        arg = new AddressExpr( arg );
    423550                                } else {
    424                                         ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, arg->get_results().front()->clone(), 0 );
     551                                        // use type computed in unification to declare boxed variables
     552                                        Type * newType = param->clone();
     553                                        if ( env ) env->apply( newType );
     554                                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, newType, 0 );
    425555                                        newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
    426556                                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     
    432562                                } // if
    433563                        } // if
    434 //   }
    435                 }
    436 
     564                }
     565
     566                /// cast parameters to polymorphic functions so that types are replaced with
     567                /// void * if they are type parameters in the formal type.
     568                /// this gets rid of warnings from gcc.
    437569                void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
    438                         Type *newType = formal->clone();
    439                         std::list< FunctionType *> functions;
    440                         // instead of functions needing adapters, this really ought to look for
    441                         // any function mentioning a polymorphic type
    442                         findAndReplaceFunction( newType, functions, tyVars, needsAdapter );
    443                         if ( ! functions.empty() ) {
     570                        Type * newType = formal->clone();
     571                        if ( getFunctionType( newType ) ) {
     572                                newType = ScrubTyVars::scrub( newType, tyVars );
    444573                                actual = new CastExpr( actual, newType );
    445                         } else {
    446                                 delete newType;
    447574                        } // if
    448575                }
     
    495622                        assert( arg );
    496623                        if ( isPolyType( realParam->get_type(), tyVars ) ) {
    497 //     if ( dynamic_cast< PointerType *>( arg->get_type() ) ) {
    498 //       return new CastExpr( new VariableExpr( param ), arg->get_type()->clone() );
    499 //     } else {
    500624                                if ( dynamic_cast<TypeInstType *>(arg->get_type()) == NULL ) {
    501625                                        UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
     
    504628                                        return deref;
    505629                                } // if
    506 //     }
    507630                        } // if
    508631                        return new VariableExpr( param );
     
    794917                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    795918
    796                         std::string typeName;
    797                         if ( isPolyRet( function, typeName ) ) {
    798                                 ret = addPolyRetParam( appExpr, function, typeName, arg );
     919                        if ( ReferenceToType *polyType = isPolyRet( function ) ) {
     920                                ret = addPolyRetParam( appExpr, function, polyType, arg );
    799921                        } else if ( needsAdapter( function, scopeTyVars ) ) {
    800922                                // std::cerr << "needs adapter: ";
     
    8831005                                        delete castExpr;
    8841006                                } //while
    885                                 TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() );
    886                                 assert( typeInst );
    887                                 std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
    888                                 if ( assignIter == assignOps.end() ) {
    889                                         throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
    890                                 } // if
    891                                 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
     1007
     1008                                // find assignment operator for (polymorphic) return type
     1009                                DeclarationWithType *assignDecl = 0;
     1010                                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
     1011                                        std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
     1012                                        if ( assignIter == assignOps.end() ) {
     1013                                                throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
     1014                                        } // if
     1015                                        assignDecl = assignIter->second;
     1016                                } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
     1017                                        ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = scopedAssignOps.find( refType->get_name() );
     1018                                        if ( assignIter == scopedAssignOps.end() ) {
     1019                                                throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
     1020                                        }
     1021                                        DeclarationWithType *functionDecl = assignIter->second;
     1022                                        // line below cloned from FixFunction.cc
     1023                                        assignDecl = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
     1024                                                                     new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
     1025                                        assignDecl->set_mangleName( functionDecl->get_mangleName() );
     1026                                }
     1027                                assert( assignDecl );
     1028
     1029                                // replace return statement with appropriate assignment to out parameter
     1030                                ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) );
    8921031                                Expression *retParm = new NameExpr( retval->get_name() );
    8931032                                retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
     
    9301069                        // push a copy of the current map
    9311070                        adapters.push(adapters.top());
     1071                        scopedAssignOps.beginScope();
    9321072                }
    9331073
    9341074                void Pass1::doEndScope() {
    9351075                        adapters.pop();
     1076                        scopedAssignOps.endScope();
    9361077                }
    9371078
     
    10011142
    10021143                        // move polymorphic return type to parameter list
    1003                         std::string typeName;
    1004                         if ( isPolyRet( funcType, typeName ) ) {
     1144                        if ( isPolyRet( funcType ) ) {
    10051145                                DeclarationWithType *ret = funcType->get_returnVals().front();
    10061146                                ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
     
    10131153                        std::list< DeclarationWithType *> inferredParams;
    10141154                        ObjectDecl newObj( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), 0 );
     1155                        ObjectDecl newPtr( "", DeclarationNode::NoStorageClass, LinkageSpec::C, 0,
     1156                                           new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
    10151157//   ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 );
    10161158                        for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
     
    10391181
    10401182                        // add size/align for generic types to parameter list
    1041                         std::set< std::string > seenTypes; //< sizeofName for generic types we've seen
     1183                        std::set< std::string > seenTypes; // sizeofName for generic types we've seen
    10421184                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
    1043                                 Type *parmType = (*fnParm)->get_type();
    1044                                 if ( ! dynamic_cast< TypeInstType* >( parmType ) && isPolyType( parmType, scopeTyVars ) ) {
    1045                                         std::string sizeName = sizeofName( parmType );
     1185                                Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );
     1186                                if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
     1187                                        std::string sizeName = sizeofName( polyBase );
    10461188                                        if ( seenTypes.count( sizeName ) ) continue;
    10471189
    1048                                         ObjectDecl *sizeParm, *alignParm;
     1190                                        ObjectDecl *sizeParm, *alignParm, *offsetParm;
    10491191                                        sizeParm = newObj.clone();
    10501192                                        sizeParm->set_name( sizeName );
     
    10531195
    10541196                                        alignParm = newObj.clone();
    1055                                         alignParm->set_name( alignofName( parmType ) );
     1197                                        alignParm->set_name( alignofName( polyBase ) );
    10561198                                        last = funcType->get_parameters().insert( last, alignParm );
    10571199                                        ++last;
     1200
     1201                                        if ( dynamic_cast< StructInstType* >( polyBase ) ) {
     1202                                                offsetParm = newPtr.clone();
     1203                                                offsetParm->set_name( offsetofName( polyBase ) );
     1204                                                last = funcType->get_parameters().insert( last, offsetParm );
     1205                                                ++last;
     1206                                        }
    10581207
    10591208                                        seenTypes.insert( sizeName );
     
    10691218                        scopeTyVars = oldtyVars;
    10701219                        return funcType;
     1220                }
     1221
     1222////////////////////////////////////////// MemberExprFixer ////////////////////////////////////////////////////
     1223
     1224                template< typename DeclClass >
     1225                DeclClass * MemberExprFixer::handleDecl( DeclClass *decl, Type *type ) {
     1226                        TyVarMap oldtyVars = scopeTyVars;
     1227                        makeTyVarMap( type, scopeTyVars );
     1228
     1229                        DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
     1230
     1231                        scopeTyVars = oldtyVars;
     1232                        return ret;
     1233                }
     1234
     1235                ObjectDecl * MemberExprFixer::mutate( ObjectDecl *objectDecl ) {
     1236                        return handleDecl( objectDecl, objectDecl->get_type() );
     1237                }
     1238
     1239                DeclarationWithType * MemberExprFixer::mutate( FunctionDecl *functionDecl ) {
     1240                        return handleDecl( functionDecl, functionDecl->get_functionType() );
     1241                }
     1242
     1243                TypedefDecl * MemberExprFixer::mutate( TypedefDecl *typedefDecl ) {
     1244                        return handleDecl( typedefDecl, typedefDecl->get_base() );
     1245                }
     1246
     1247                TypeDecl * MemberExprFixer::mutate( TypeDecl *typeDecl ) {
     1248                        scopeTyVars[ typeDecl->get_name() ] = typeDecl->get_kind();
     1249                        return Mutator::mutate( typeDecl );
     1250                }
     1251
     1252                Type * MemberExprFixer::mutate( PointerType *pointerType ) {
     1253                        TyVarMap oldtyVars = scopeTyVars;
     1254                        makeTyVarMap( pointerType, scopeTyVars );
     1255
     1256                        Type *ret = Mutator::mutate( pointerType );
     1257
     1258                        scopeTyVars = oldtyVars;
     1259                        return ret;
     1260                }
     1261
     1262                Type * MemberExprFixer::mutate( FunctionType *functionType ) {
     1263                        TyVarMap oldtyVars = scopeTyVars;
     1264                        makeTyVarMap( functionType, scopeTyVars );
     1265
     1266                        Type *ret = Mutator::mutate( functionType );
     1267
     1268                        scopeTyVars = oldtyVars;
     1269                        return ret;
     1270                }
     1271
     1272                Statement *MemberExprFixer::mutate( DeclStmt *declStmt ) {
     1273                        if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
     1274                                if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
     1275                                        // change initialization of a polymorphic value object
     1276                                        // to allocate storage with alloca
     1277                                        Type *declType = objectDecl->get_type();
     1278                                        UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
     1279                                        alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );
     1280
     1281                                        delete objectDecl->get_init();
     1282
     1283                                        std::list<Expression*> designators;
     1284                                        objectDecl->set_init( new SingleInit( alloc, designators ) );
     1285                                }
     1286                        }
     1287                        return Mutator::mutate( declStmt );
     1288                }
     1289
     1290                /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
     1291                long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
     1292                        long i = 0;
     1293                        for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) {
     1294                                if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
     1295
     1296                                if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
     1297                                        if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
     1298                                        else continue;
     1299                                } else return i;
     1300                        }
     1301                        return -1;
     1302                }
     1303
     1304                /// Returns an index expression into the offset array for a type
     1305                Expression *makeOffsetIndex( Type *objectType, long i ) {
     1306                        std::stringstream offset_namer;
     1307                        offset_namer << i;
     1308                        ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
     1309                        UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
     1310                        fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );
     1311                        fieldOffset->get_args().push_back( fieldIndex );
     1312                        return fieldOffset;
     1313                }
     1314
     1315                /// Returns an expression dereferenced n times
     1316                Expression *makeDerefdVar( Expression *derefdVar, long n ) {
     1317                        for ( int i = 1; i < n; ++i ) {
     1318                                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     1319                                derefExpr->get_args().push_back( derefdVar );
     1320                                derefdVar = derefExpr;
     1321                        }
     1322                        return derefdVar;
     1323                }
     1324               
     1325                Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
     1326                        // mutate, exiting early if no longer MemberExpr
     1327                        Expression *expr = Mutator::mutate( memberExpr );
     1328                        memberExpr = dynamic_cast< MemberExpr* >( expr );
     1329                        if ( ! memberExpr ) return expr;
     1330
     1331                        // get declaration for base struct, exiting early if not found
     1332                        int varDepth;
     1333                        VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate(), &varDepth );
     1334                        if ( ! varExpr ) return memberExpr;
     1335                        ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
     1336                        if ( ! objectDecl ) return memberExpr;
     1337
     1338                        // only mutate member expressions for polymorphic types
     1339                        int tyDepth;
     1340                        Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
     1341                        if ( ! objectType ) return memberExpr;
     1342
     1343                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
     1344                                // look up offset index
     1345                                long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() );
     1346                                if ( i == -1 ) return memberExpr;
     1347
     1348                                // replace member expression with pointer to base plus offset
     1349                                UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
     1350                                fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) );
     1351                                fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
     1352
     1353                                delete memberExpr;
     1354                                return fieldLoc;
     1355                        } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {
     1356                                // union members are all at offset zero, so build appropriately-dereferenced variable
     1357                                Expression *derefdVar = makeDerefdVar( varExpr->clone(), varDepth );
     1358                                delete memberExpr;
     1359                                return derefdVar;
     1360                        } else return memberExpr;
     1361                }
     1362
     1363                Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) {
     1364                        // mutate, exiting early if no longer OffsetofExpr
     1365                        Expression *expr = Mutator::mutate( offsetofExpr );
     1366                        offsetofExpr = dynamic_cast< OffsetofExpr* >( expr );
     1367                        if ( ! offsetofExpr ) return expr;
     1368
     1369                        // only mutate expressions for polymorphic structs/unions
     1370                        Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars );
     1371                        if ( ! ty ) return offsetofExpr;
     1372
     1373                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
     1374                                // replace offsetof expression by index into offset array
     1375                                long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
     1376                                if ( i == -1 ) return offsetofExpr;
     1377
     1378                                Expression *offsetInd = makeOffsetIndex( ty, i );
     1379                                delete offsetofExpr;
     1380                                return offsetInd;
     1381                        } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( ty ) ) {
     1382                                // all union members are at offset zero
     1383                                delete offsetofExpr;
     1384                                return new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::string("0") ) );
     1385                        } else return offsetofExpr;
    10711386                }
    10721387
     
    11291444                        return ret;
    11301445                }
    1131 
    1132                 Statement *Pass3::mutate( DeclStmt *declStmt ) {
    1133                         if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
    1134                                 if ( isPolyType( objectDecl->get_type(), scopeTyVars ) ) {
    1135                                         // change initialization of a polymorphic value object
    1136                                         // to allocate storage with alloca
    1137                                         Type *declType = objectDecl->get_type();
    1138                                         UntypedExpr *alloc = new UntypedExpr( new NameExpr( "__builtin_alloca" ) );
    1139                                         alloc->get_args().push_back( new NameExpr( sizeofName( declType ) ) );
    1140 
    1141                                         delete objectDecl->get_init();
    1142 
    1143                                         std::list<Expression*> designators;
    1144                                         objectDecl->set_init( new SingleInit( alloc, designators, false ) ); // not constructed
    1145                                 }
    1146                         }
    1147                         return Mutator::mutate( declStmt );
    1148                 }
    11491446        } // anonymous namespace
    11501447} // namespace GenPoly
Note: See TracChangeset for help on using the changeset viewer.