Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    rbd85400 r974906e2  
    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 Feb  5 16:45:07 2016
    13 // Update Count     : 286
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Thu Jan 07 13:40:05 2016
     13// Update Count     : 219
    1414//
    1515
     
    2222
    2323#include "Box.h"
    24 #include "InstantiateGeneric.h"
    2524#include "PolyMutator.h"
    2625#include "FindFunction.h"
    27 #include "ScopedMap.h"
    2826#include "ScrubTyVars.h"
    2927
     
    4139#include "SymTab/Mangler.h"
    4240
    43 #include "Common/SemanticError.h"
    44 #include "Common/UniqueName.h"
    45 #include "Common/utility.h"
     41#include "SemanticError.h"
     42#include "UniqueName.h"
     43#include "utility.h"
    4644
    4745#include <ext/functional> // temporary
     
    7169                        virtual void doEndScope();
    7270                  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
    7671                        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
    7872                        Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, 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 );
     73                        Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg );
    8674                        Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    8775                        void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
    8876                        void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    8977                        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
    9178                        void findAssignOps( const std::list< TypeDecl *> &forall );
    9279                        void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
    9380                        FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
    94                         /// Replaces intrinsic operator functions with their arithmetic desugaring
    9581                        Expression *handleIntrinsics( ApplicationExpr *appExpr );
    96                         /// Inserts a new temporary variable into the current scope with an auto-generated name
    9782                        ObjectDecl *makeTemporary( Type *type );
    9883
    9984                        typedef std::map< std::string, DeclarationWithType *> AdapterMap;
    10085                        std::map< std::string, DeclarationWithType *> assignOps;
    101                         ScopedMap< std::string, DeclarationWithType *> scopedAssignOps;
    10286                        std::stack< AdapterMap > adapters;
    10387                        DeclarationWithType *retval;
     
    123107                };
    124108
    125                 /// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
    126                 /// also fixes offsetof expressions.
    127                 class MemberExprFixer : public PolyMutator {
     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 {
    128111                  public:
    129112                        template< typename DeclClass >
     
    136119                        virtual Type *mutate( PointerType *pointerType );
    137120                        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 );
    153121                  private:
    154122                };
     
    165133        }
    166134
    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 
    193135        void box( std::list< Declaration *>& translationUnit ) {
    194136                Pass1 pass1;
    195137                Pass2 pass2;
    196                 MemberExprFixer memberFixer;
    197138                Pass3 pass3;
    198                 mutateTranslationUnit/*All*/( translationUnit, pass1 );
    199                 mutateTranslationUnit/*All*/( translationUnit, pass2 );
    200                 instantiateGeneric( translationUnit );
    201                 mutateTranslationUnit/*All*/( translationUnit, memberFixer );
    202                 mutateTranslationUnit/*All*/( translationUnit, pass3 );
     139                mutateAll( translationUnit, pass1 );
     140                mutateAll( translationUnit, pass2 );
     141                mutateAll( translationUnit, pass3 );
    203142        }
    204143
     
    246185                }
    247186
    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 ) {
     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 ) {
    250189                        if ( decl->get_name() == "?=?" ) {
    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;
     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
    258200                                                                        } // if
    259201                                                                } // if
     
    263205                                } // if
    264206                        } // if
    265                         return 0;
     207                        return false;
    266208                }
    267209
     
    272214                                for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    273215                                        std::string typeName;
    274                                         if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert ) ) ) {
    275                                                 assignOps[ typeInst->get_name() ] = *assert;
     216                                        if ( checkAssignment( *assert, typeName ) ) {
     217                                                assignOps[ typeName ] = *assert;
    276218                                        } // if
    277219                                } // for
     
    280222
    281223                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 
    289224                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    290225                                doBeginScope();
     
    296231                                // process polymorphic return value
    297232                                retval = 0;
    298                                 if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
     233                                std::string typeName;
     234                                if ( isPolyRet( functionDecl->get_functionType(), typeName ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
    299235                                        retval = functionDecl->get_functionType()->get_returnVals().front();
    300236
     
    320256                                        findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
    321257                                } // for
    322 
    323258                                AdapterMap & adapters = Pass1::adapters.top();
    324259                                for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
     
    369304                        return condExpr;
    370305
    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 );
    398306                }
    399307
     
    417325
    418326                        // add size/align for generic types to parameter list
     327                        //assert( ! appExpr->get_function()->get_results().empty() );
    419328                        if ( appExpr->get_function()->get_results().empty() ) return;
    420329                        FunctionType *funcType = getFunctionType( appExpr->get_function()->get_results().front() );
     
    425334                        std::set< std::string > seenTypes; //< names for generic types we've seen
    426335                        for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
    427                                 Type *polyBase = hasPolyBase( (*fnParm)->get_type(), exprTyVars );
    428                                 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
    429                                         std::string sizeName = sizeofName( polyBase );
     336                                Type *parmType = (*fnParm)->get_type();
     337                                if ( ! dynamic_cast< TypeInstType* >( parmType ) && isPolyType( parmType, exprTyVars ) ) {
     338                                        std::string sizeName = sizeofName( parmType );
    430339                                        if ( seenTypes.count( sizeName ) ) continue;
    431340
    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() ) );
     341                                        assert( ! (*fnArg)->get_results().empty() );
     342                                        Type *argType = (*fnArg)->get_results().front();
     343                                        arg = appExpr->get_args().insert( arg, new SizeofExpr( argType->clone() ) );
    436344                                        arg++;
    437                                         arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
     345                                        arg = appExpr->get_args().insert( arg, new AlignofExpr( argType->clone() ) );
    438346                                        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                                         }
    447347
    448348                                        seenTypes.insert( sizeName );
     
    486386                }
    487387
    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 ) {
     388                Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, std::string typeName, std::list< Expression *>::iterator &arg ) {
     389                        ResolvExpr::EqvClass eqvClass;
    520390                        assert( env );
    521                         Type *concrete = replaceWithConcrete( appExpr, polyType );
     391                        Type *concrete = env->lookup( typeName );
     392                        if ( concrete == 0 ) {
     393                                throw SemanticError( "Unbound type variable " + typeName + " in ", appExpr );
     394                        } // if
    522395                        return addRetParam( appExpr, function, concrete, arg );
    523396                }
     
    531404                        std::string adapterName = makeAdapterName( mangleName );
    532405
    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 ) );
     406                        appExpr->get_args().push_front( appExpr->get_function() );
    536407                        appExpr->set_function( new NameExpr( adapterName ) );
    537408
     
    541412                void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
    542413                        assert( ! arg->get_results().empty() );
    543                         if ( isPolyType( param, exprTyVars ) ) {
     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() ) {
    544417                                if ( dynamic_cast< TypeInstType *>( arg->get_results().front() ) ) {
    545418                                        // if the argument's type is a type parameter, we don't need to box again!
     
    549422                                        arg = new AddressExpr( arg );
    550423                                } else {
    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 );
     424                                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, arg->get_results().front()->clone(), 0 );
    555425                                        newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
    556426                                        stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     
    562432                                } // if
    563433                        } // if
    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.
     434//   }
     435                }
     436
    569437                void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
    570                         Type * newType = formal->clone();
    571                         if ( getFunctionType( newType ) ) {
    572                                 newType = ScrubTyVars::scrub( newType, 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() ) {
    573444                                actual = new CastExpr( actual, newType );
     445                        } else {
     446                                delete newType;
    574447                        } // if
    575448                }
     
    622495                        assert( arg );
    623496                        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 {
    624500                                if ( dynamic_cast<TypeInstType *>(arg->get_type()) == NULL ) {
    625501                                        UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
     
    628504                                        return deref;
    629505                                } // if
     506//     }
    630507                        } // if
    631508                        return new VariableExpr( param );
     
    917794                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    918795
    919                         if ( ReferenceToType *polyType = isPolyRet( function ) ) {
    920                                 ret = addPolyRetParam( appExpr, function, polyType, arg );
     796                        std::string typeName;
     797                        if ( isPolyRet( function, typeName ) ) {
     798                                ret = addPolyRetParam( appExpr, function, typeName, arg );
    921799                        } else if ( needsAdapter( function, scopeTyVars ) ) {
    922800                                // std::cerr << "needs adapter: ";
     
    1005883                                        delete castExpr;
    1006884                                } //while
    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 ) );
     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 ) );
    1031892                                Expression *retParm = new NameExpr( retval->get_name() );
    1032893                                retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
     
    1069930                        // push a copy of the current map
    1070931                        adapters.push(adapters.top());
    1071                         scopedAssignOps.beginScope();
    1072932                }
    1073933
    1074934                void Pass1::doEndScope() {
    1075935                        adapters.pop();
    1076                         scopedAssignOps.endScope();
    1077936                }
    1078937
     
    11421001
    11431002                        // move polymorphic return type to parameter list
    1144                         if ( isPolyRet( funcType ) ) {
     1003                        std::string typeName;
     1004                        if ( isPolyRet( funcType, typeName ) ) {
    11451005                                DeclarationWithType *ret = funcType->get_returnVals().front();
    11461006                                ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
     
    11531013                        std::list< DeclarationWithType *> inferredParams;
    11541014                        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 );
    11571015//   ObjectDecl *newFunPtr = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ), 0 );
    11581016                        for ( std::list< TypeDecl *>::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
     
    11811039
    11821040                        // add size/align for generic types to parameter list
    1183                         std::set< std::string > seenTypes; // sizeofName for generic types we've seen
     1041                        std::set< std::string > seenTypes; //< sizeofName for generic types we've seen
    11841042                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
    1185                                 Type *polyBase = hasPolyBase( (*fnParm)->get_type(), scopeTyVars );
    1186                                 if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
    1187                                         std::string sizeName = sizeofName( polyBase );
     1043                                Type *parmType = (*fnParm)->get_type();
     1044                                if ( ! dynamic_cast< TypeInstType* >( parmType ) && isPolyType( parmType, scopeTyVars ) ) {
     1045                                        std::string sizeName = sizeofName( parmType );
    11881046                                        if ( seenTypes.count( sizeName ) ) continue;
    11891047
    1190                                         ObjectDecl *sizeParm, *alignParm, *offsetParm;
     1048                                        ObjectDecl *sizeParm, *alignParm;
    11911049                                        sizeParm = newObj.clone();
    11921050                                        sizeParm->set_name( sizeName );
     
    11951053
    11961054                                        alignParm = newObj.clone();
    1197                                         alignParm->set_name( alignofName( polyBase ) );
     1055                                        alignParm->set_name( alignofName( parmType ) );
    11981056                                        last = funcType->get_parameters().insert( last, alignParm );
    11991057                                        ++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                                         }
    12071058
    12081059                                        seenTypes.insert( sizeName );
     
    12181069                        scopeTyVars = oldtyVars;
    12191070                        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;
    13861071                }
    13871072
     
    14441129                        return ret;
    14451130                }
     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                }
    14461149        } // anonymous namespace
    14471150} // namespace GenPoly
Note: See TracChangeset for help on using the changeset viewer.