Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    rbd85400 r4067aa8  
    2525#include "PolyMutator.h"
    2626#include "FindFunction.h"
    27 #include "ScopedMap.h"
    2827#include "ScrubTyVars.h"
    2928
     
    3837
    3938#include "ResolvExpr/TypeEnvironment.h"
     39#include "ResolvExpr/TypeMap.h"
     40#include "ResolvExpr/typeops.h"
    4041
    4142#include "SymTab/Mangler.h"
     
    7374                        /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
    7475                        Expression *makeOffsetArray( StructInstType *type );
     76                        /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
     77                        void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
    7578                        /// passes extra type parameters into a polymorphic function application
    76                         void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
     79                        void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    7780                        /// wraps a function application with a new temporary for the out-parameter return value
    7881                        Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
     
    99102                        typedef std::map< std::string, DeclarationWithType *> AdapterMap;
    100103                        std::map< std::string, DeclarationWithType *> assignOps;
    101                         ScopedMap< std::string, DeclarationWithType *> scopedAssignOps;
     104                        ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;
    102105                        std::stack< AdapterMap > adapters;
    103106                        DeclarationWithType *retval;
     
    246249                }
    247250
    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 ) {
     251                /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
     252                TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) {
    250253                        if ( decl->get_name() == "?=?" ) {
    251254                                if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
    252255                                        if ( funType->get_parameters().size() == 2 ) {
    253256                                                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() ) ) {
     257                                                        if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {
     258                                                                if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {
    256259                                                                        if ( refType->get_name() == refType2->get_name() ) {
    257260                                                                                return refType;
     
    265268                        return 0;
    266269                }
     270               
     271                /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
     272                /// Only picks assignments where neither parameter is cv-qualified
     273                Type *isAssignment( DeclarationWithType *decl ) {
     274                        if ( decl->get_name() == "?=?" ) {
     275                                if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {
     276                                        if ( funType->get_parameters().size() == 2 ) {
     277                                                Type::Qualifiers defaultQualifiers;
     278                                                Type *paramType1 = funType->get_parameters().front()->get_type();
     279                                                if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0;
     280                                                Type *paramType2 = funType->get_parameters().back()->get_type();
     281                                                if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
     282                                               
     283                                                if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
     284                                                        Type *baseType1 = pointerType->get_base();
     285                                                        if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0;
     286                                                        SymTab::Indexer dummy;
     287                                                        if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) {
     288                                                                return baseType1;
     289                                                        } // if
     290                                                } // if
     291                                        } // if
     292                                } // if
     293                        } // if
     294                        return 0;
     295                }
    267296
    268297                void Pass1::findAssignOps( const std::list< TypeDecl *> &forall ) {
     
    272301                                for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    273302                                        std::string typeName;
    274                                         if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( isAssignment( *assert ) ) ) {
     303                                        if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) {
    275304                                                assignOps[ typeInst->get_name() ] = *assert;
    276305                                        } // if
     
    281310                DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
    282311                        // 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 );
     312                        if ( Type *assignedType = isAssignment( functionDecl ) ) {
     313                                if ( ! dynamic_cast< TypeInstType* >( assignedType ) ) {
     314                                        scopedAssignOps.insert( assignedType, functionDecl );
    286315                                }
    287316                        }
     
    398427                }
    399428
    400                 void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
     429                void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
     430                        Type *polyBase = hasPolyBase( parmType, exprTyVars );
     431                        if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
     432                                std::string sizeName = sizeofName( polyBase );
     433                                if ( seenTypes.count( sizeName ) ) return;
     434
     435                                arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
     436                                arg++;
     437                                arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
     438                                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                                }
     447
     448                                seenTypes.insert( sizeName );
     449                        }
     450                }
     451
     452                void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
    401453                        // pass size/align for type variables
    402454                        for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
     
    424476                        std::list< Expression* >::const_iterator fnArg = arg;
    425477                        std::set< std::string > seenTypes; //< names for generic types we've seen
     478
     479                        // a polymorphic return type may need to be added to the argument list
     480                        if ( polyRetType ) {
     481                                Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
     482                                passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
     483                        }
     484                       
     485                        // add type information args for presently unseen types in parameter list
    426486                        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 );
    430                                         if ( seenTypes.count( sizeName ) ) continue;
    431 
    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() ) );
    436                                         arg++;
    437                                         arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
    438                                         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                                         }
    447 
    448                                         seenTypes.insert( sizeName );
    449                                 }
     487                                VariableExpr *fnArgBase = getBaseVar( *fnArg );
     488                                if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue;
     489                                passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes );
    450490                        }
    451491                }
     
    470510                        ObjectDecl *newObj = makeTemporary( retType->clone() );
    471511                        Expression *paramExpr = new VariableExpr( newObj );
    472                         // If the type of the temporary is not polymorphic, box temporary by taking its address; otherwise the
    473                         // temporary is already boxed and can be used directly.
     512
     513                        // If the type of the temporary is not polymorphic, box temporary by taking its address;
     514                        // otherwise the temporary is already boxed and can be used directly.
    474515                        if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) {
    475516                                paramExpr = new AddressExpr( paramExpr );
     
    520561                        assert( env );
    521562                        Type *concrete = replaceWithConcrete( appExpr, polyType );
     563                        // add out-parameter for return value   
    522564                        return addRetParam( appExpr, function, concrete, arg );
    523565                }
     
    542584                        assert( ! arg->get_results().empty() );
    543585                        if ( isPolyType( param, exprTyVars ) ) {
    544                                 if ( dynamic_cast< TypeInstType *>( arg->get_results().front() ) ) {
    545                                         // if the argument's type is a type parameter, we don't need to box again!
     586                                if ( isPolyType( arg->get_results().front() ) ) {
     587                                        // if the argument's type is polymorphic, we don't need to box again!
    546588                                        return;
    547589                                } else if ( arg->get_results().front()->get_isLvalue() ) {
     
    622664                        assert( arg );
    623665                        if ( isPolyType( realParam->get_type(), tyVars ) ) {
    624                                 if ( dynamic_cast<TypeInstType *>(arg->get_type()) == NULL ) {
     666                                if ( ! isPolyType( arg->get_type() ) ) {
    625667                                        UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    626668                                        deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
     
    917959                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    918960
    919                         if ( ReferenceToType *polyType = isPolyRet( function ) ) {
    920                                 ret = addPolyRetParam( appExpr, function, polyType, arg );
     961                        TyVarMap exprTyVars;
     962                        makeTyVarMap( function, exprTyVars );
     963                        ReferenceToType *polyRetType = isPolyRet( function );
     964
     965                        if ( polyRetType ) {
     966                                ret = addPolyRetParam( appExpr, function, polyRetType, arg );
    921967                        } else if ( needsAdapter( function, scopeTyVars ) ) {
    922968                                // std::cerr << "needs adapter: ";
     
    930976                        arg = appExpr->get_args().begin();
    931977
    932                         TyVarMap exprTyVars;
    933                         makeTyVarMap( function, exprTyVars );
    934 
    935                         passTypeVars( appExpr, arg, exprTyVars );
     978                        passTypeVars( appExpr, polyRetType, arg, exprTyVars );
    936979                        addInferredParams( appExpr, function, arg, exprTyVars );
    937980
     
    9921035                }
    9931036
     1037                /// Wraps a function declaration in a new pointer-to-function variable expression
     1038                VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {
     1039                        // line below cloned from FixFunction.cc
     1040                        ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
     1041                                                                  new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
     1042                        functionObj->set_mangleName( functionDecl->get_mangleName() );
     1043                        return new VariableExpr( functionObj );
     1044                }
     1045               
    9941046                Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
    9951047                        if ( retval && returnStmt->get_expr() ) {
     
    10071059
    10081060                                // find assignment operator for (polymorphic) return type
    1009                                 DeclarationWithType *assignDecl = 0;
     1061                                ApplicationExpr *assignExpr = 0;
    10101062                                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
     1063                                        // find assignment operator for type variable
    10111064                                        std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
    10121065                                        if ( assignIter == assignOps.end() ) {
    10131066                                                throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
    10141067                                        } // if
    1015                                         assignDecl = assignIter->second;
     1068                                        assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
    10161069                                } 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() ) {
     1070                                        // find assignment operator for generic type
     1071                                        DeclarationWithType *functionDecl = scopedAssignOps.find( refType );
     1072                                        if ( ! functionDecl ) {
    10191073                                                throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
    10201074                                        }
    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() );
     1075
     1076                                        // wrap it up in an application expression
     1077                                        assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) );
     1078                                        assignExpr->set_env( env->clone() );
     1079
     1080                                        // find each of its needed secondary assignment operators
     1081                                        std::list< Expression* > &tyParams = refType->get_parameters();
     1082                                        std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall();
     1083                                        std::list< Expression* >::const_iterator tyIt = tyParams.begin();
     1084                                        std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
     1085                                        for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
     1086                                                if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype)
     1087
     1088                                                std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
     1089                                                assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
     1090                                                DeclarationWithType *actualDecl = asserts.front();
     1091                                                TypeInstType *actualType = isTypeInstAssignment( actualDecl );
     1092                                                assert( actualType && "First assertion of type with assertions should be assignment operator" );
     1093                                                TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
     1094                                                assert( formalTypeExpr && "type parameters must be type expressions" );
     1095                                                Type *formalType = formalTypeExpr->get_type();
     1096                                                assignExpr->get_env()->add( actualType->get_name(), formalType );
     1097                                               
     1098                                                DeclarationWithType *assertAssign = 0;
     1099                                                if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
     1100                                                        std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
     1101                                                        if ( assertAssignIt == assignOps.end() ) {
     1102                                                                throw SemanticError( "No assignment operation found for ", formalTypeInstType );
     1103                                                        }
     1104                                                        assertAssign = assertAssignIt->second;
     1105                                                } else {
     1106                                                        assertAssign = scopedAssignOps.find( formalType );
     1107                                                        if ( ! assertAssign ) {
     1108                                                                throw SemanticError( "No assignment operation found for ", formalType );
     1109                                                        }
     1110                                                }
     1111                                               
     1112
     1113                                                assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
     1114                                                        = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
     1115                                        }
    10261116                                }
    1027                                 assert( assignDecl );
     1117                                assert( assignExpr );
    10281118
    10291119                                // replace return statement with appropriate assignment to out parameter
    1030                                 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) );
    10311120                                Expression *retParm = new NameExpr( retval->get_name() );
    10321121                                retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
     
    11801269                        }
    11811270
    1182                         // add size/align for generic types to parameter list
     1271                        // add size/align for generic parameter types to parameter list
    11831272                        std::set< std::string > seenTypes; // sizeofName for generic types we've seen
    11841273                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
     
    12951384
    12961385                                if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
    1297                                         if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
     1386                                        if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty()
     1387                                             || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
    12981388                                        else continue;
    12991389                                } else return i;
     
    13411431                        if ( ! objectType ) return memberExpr;
    13421432
     1433                        Expression *newMemberExpr = 0;
    13431434                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
    13441435                                // look up offset index
     
    13501441                                fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) );
    13511442                                fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
    1352 
    1353                                 delete memberExpr;
    1354                                 return fieldLoc;
    1355                         } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {
     1443                                newMemberExpr = fieldLoc;
     1444                        } else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
    13561445                                // 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;
     1446                                newMemberExpr = makeDerefdVar( varExpr->clone(), varDepth );
    13601447                        } else return memberExpr;
     1448                        assert( newMemberExpr );
     1449
     1450                        Type *memberType = memberExpr->get_member()->get_type();
     1451                        if ( ! isPolyType( memberType, scopeTyVars ) ) {
     1452                                // Not all members of a polymorphic type are themselves of polymorphic type; in this case the member expression should be wrapped and dereferenced to form an lvalue
     1453                                CastExpr *ptrCastExpr = new CastExpr( newMemberExpr, new PointerType( Type::Qualifiers(), memberType->clone() ) );
     1454                                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     1455                                derefExpr->get_args().push_back( ptrCastExpr );
     1456                                newMemberExpr = derefExpr;
     1457                        }
     1458
     1459                        delete memberExpr;
     1460                        return newMemberExpr;
    13611461                }
    13621462
     
    13791479                                delete offsetofExpr;
    13801480                                return offsetInd;
    1381                         } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( ty ) ) {
     1481                        } else if ( dynamic_cast< UnionInstType* >( ty ) ) {
    13821482                                // all union members are at offset zero
    13831483                                delete offsetofExpr;
Note: See TracChangeset for help on using the changeset viewer.