Changes in / [658f6de0:a73d57a]


Ignore:
Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    r658f6de0 ra73d57a  
    7373                        /// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
    7474                        Expression *makeOffsetArray( StructInstType *type );
     75                        /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
     76                        void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
    7577                        /// passes extra type parameters into a polymorphic function application
    76                         void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
     78                        void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    7779                        /// wraps a function application with a new temporary for the out-parameter return value
    7880                        Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
     
    398400                }
    399401
    400                 void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
     402                void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
     403                        Type *polyBase = hasPolyBase( parmType, exprTyVars );
     404                        if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
     405                                std::string sizeName = sizeofName( polyBase );
     406                                if ( seenTypes.count( sizeName ) ) return;
     407
     408                                arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
     409                                arg++;
     410                                arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
     411                                arg++;
     412                                if ( dynamic_cast< StructInstType* >( polyBase ) ) {
     413                                        if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
     414                                                arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
     415                                                arg++;
     416                                        } else {
     417                                                throw SemanticError( "Cannot pass non-struct type for generic struct" );
     418                                        }
     419                                }
     420
     421                                seenTypes.insert( sizeName );
     422                        }
     423                }
     424
     425                void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
    401426                        // pass size/align for type variables
    402427                        for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
     
    424449                        std::list< Expression* >::const_iterator fnArg = arg;
    425450                        std::set< std::string > seenTypes; //< names for generic types we've seen
     451
     452                        // a polymorphic return type may need to be added to the argument list
     453                        if ( polyRetType ) {
     454                                Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
     455                                passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
     456                        }
     457                       
     458                        // add type information args for presently unseen types in parameter list
    426459                        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                                 }
     460                                VariableExpr *fnArgBase = getBaseVar( *fnArg );
     461                                if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue;
     462                                passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes );
    450463                        }
    451464                }
     
    470483                        ObjectDecl *newObj = makeTemporary( retType->clone() );
    471484                        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.
     485
     486                        // If the type of the temporary is not polymorphic, box temporary by taking its address;
     487                        // otherwise the temporary is already boxed and can be used directly.
    474488                        if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) {
    475489                                paramExpr = new AddressExpr( paramExpr );
     
    520534                        assert( env );
    521535                        Type *concrete = replaceWithConcrete( appExpr, polyType );
     536                        // add out-parameter for return value   
    522537                        return addRetParam( appExpr, function, concrete, arg );
    523538                }
     
    542557                        assert( ! arg->get_results().empty() );
    543558                        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!
     559                                if ( isPolyType( arg->get_results().front() ) ) {
     560                                        // if the argument's type is polymorphic, we don't need to box again!
    546561                                        return;
    547562                                } else if ( arg->get_results().front()->get_isLvalue() ) {
     
    917932                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    918933
    919                         if ( ReferenceToType *polyType = isPolyRet( function ) ) {
    920                                 ret = addPolyRetParam( appExpr, function, polyType, arg );
     934                        TyVarMap exprTyVars;
     935                        makeTyVarMap( function, exprTyVars );
     936                        ReferenceToType *polyRetType = 0;
     937
     938                        if ( polyRetType = isPolyRet( function ) ) {
     939                                ret = addPolyRetParam( appExpr, function, polyRetType, arg );
    921940                        } else if ( needsAdapter( function, scopeTyVars ) ) {
    922941                                // std::cerr << "needs adapter: ";
     
    930949                        arg = appExpr->get_args().begin();
    931950
    932                         TyVarMap exprTyVars;
    933                         makeTyVarMap( function, exprTyVars );
    934 
    935                         passTypeVars( appExpr, arg, exprTyVars );
     951                        passTypeVars( appExpr, polyRetType, arg, exprTyVars );
    936952                        addInferredParams( appExpr, function, arg, exprTyVars );
    937953
     
    9921008                }
    9931009
     1010                /// Wraps a function declaration in a new pointer-to-function variable expression
     1011                VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {
     1012                        // line below cloned from FixFunction.cc
     1013                        ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
     1014                                                                  new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
     1015                        functionObj->set_mangleName( functionDecl->get_mangleName() );
     1016                        return new VariableExpr( functionObj );
     1017                }
     1018               
    9941019                Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
    9951020                        if ( retval && returnStmt->get_expr() ) {
     
    10071032
    10081033                                // find assignment operator for (polymorphic) return type
    1009                                 DeclarationWithType *assignDecl = 0;
     1034                                ApplicationExpr *assignExpr = 0;
    10101035                                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
     1036                                        // find assignment operator for type variable
    10111037                                        std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
    10121038                                        if ( assignIter == assignOps.end() ) {
    10131039                                                throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
    10141040                                        } // if
    1015                                         assignDecl = assignIter->second;
     1041                                        assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
    10161042                                } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
     1043                                        // find assignment operator for generic type
    10171044                                        ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = scopedAssignOps.find( refType->get_name() );
    10181045                                        if ( assignIter == scopedAssignOps.end() ) {
    10191046                                                throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
    10201047                                        }
     1048
     1049                                        // wrap it up in an application expression
    10211050                                        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() );
     1051                                        assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) );
     1052                                        assignExpr->set_env( env->clone() );
     1053
     1054                                        // find each of its needed secondary assignment operators
     1055                                        std::list< Expression* > &tyParams = refType->get_parameters();
     1056                                        std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall();
     1057                                        std::list< Expression* >::const_iterator tyIt = tyParams.begin();
     1058                                        std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
     1059                                        for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
     1060                                                if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype)
     1061
     1062                                                std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
     1063                                                assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
     1064                                                DeclarationWithType *actualDecl = asserts.front();
     1065                                                ReferenceToType *actualType = isAssignment( actualDecl );
     1066                                                assert( actualType && "First assertion of type with assertions should be assignment operator" );
     1067                                                TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
     1068                                                assert( formalTypeExpr && "type parameters must be type expressions" );
     1069                                                Type *formalType = formalTypeExpr->get_type();
     1070                                                assignExpr->get_env()->add( actualType->get_name(), formalType );
     1071                                               
     1072                                                DeclarationWithType *assertAssign = 0;
     1073                                                if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
     1074                                                        std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
     1075                                                        if ( assertAssignIt == assignOps.end() ) {
     1076                                                                throw SemanticError( "No assignment operation found for ", formalTypeInstType );
     1077                                                        }
     1078                                                        assertAssign = assertAssignIt->second;
     1079                                                        //assignExpr->get_env()->add( formalTypeInstType->get_name(), actualType );
     1080                                                } else if ( ReferenceToType *formalReferenceType = dynamic_cast< ReferenceToType* >( formalType ) )  {
     1081                                                        ScopedMap< std::string, DeclarationWithType *>::const_iterator assertAssignIt = scopedAssignOps.find( formalReferenceType->get_name() );
     1082                                                        if ( assertAssignIt == scopedAssignOps.end() ) {
     1083                                                                throw SemanticError( "No assignment operation found for ", formalReferenceType );
     1084                                                        }
     1085                                                        assertAssign = assertAssignIt->second;
     1086                                                } else assert( false && "returning polymorphic types with non struct/polymorphic parameters not yet supported" );
     1087                                               
     1088
     1089                                                assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
     1090                                                        = ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
     1091                                        }
    10261092                                }
    1027                                 assert( assignDecl );
     1093                                assert( assignExpr );
    10281094
    10291095                                // replace return statement with appropriate assignment to out parameter
    1030                                 ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) );
    10311096                                Expression *retParm = new NameExpr( retval->get_name() );
    10321097                                retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
     
    11801245                        }
    11811246
    1182                         // add size/align for generic types to parameter list
     1247                        // add size/align for generic parameter types to parameter list
    11831248                        std::set< std::string > seenTypes; // sizeofName for generic types we've seen
    11841249                        for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
     
    12951360
    12961361                                if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
    1297                                         if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
     1362                                        if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty()
     1363                                             || memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
    12981364                                        else continue;
    12991365                                } else return i;
     
    13531419                                delete memberExpr;
    13541420                                return fieldLoc;
    1355                         } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {
     1421                        } else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
    13561422                                // union members are all at offset zero, so build appropriately-dereferenced variable
    13571423                                Expression *derefdVar = makeDerefdVar( varExpr->clone(), varDepth );
     
    13791445                                delete offsetofExpr;
    13801446                                return offsetInd;
    1381                         } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( ty ) ) {
     1447                        } else if ( dynamic_cast< UnionInstType* >( ty ) ) {
    13821448                                // all union members are at offset zero
    13831449                                delete offsetofExpr;
  • src/SymTab/Validate.cc

    r658f6de0 ra73d57a  
    382382                // it's not a semantic error if the struct is not found, just an implicit forward declaration
    383383                if ( st ) {
    384                         assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
     384                        //assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
    385385                        structInst->set_baseStruct( st );
    386386                } // if
     
    659659        }
    660660
     661        /// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
     662        TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
     663                TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
     664
     665                if ( src->get_kind() == TypeDecl::Any ) {
     666                        // just include assignment operator assertion
     667                        TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
     668                        FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
     669                        assignFunctionType->get_returnVals().push_back(
     670                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
     671                        assignFunctionType->get_parameters().push_back(
     672                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
     673                        assignFunctionType->get_parameters().push_back(
     674                                new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
     675                        FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
     676                        dst->get_assertions().push_back( assignAssert );
     677                }
     678
     679                return dst;
     680        }
     681
    661682        Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
    662683                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     
    666687                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
    667688                std::list< Expression* > structParams;  // List of matching parameters to put on types
     689                TypeSubstitution genericSubs; // Substitutions to make to member types of struct
    668690                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    669691                        isGeneric = true;
    670                         TypeDecl *typeParam = (*param)->clone();
     692                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    671693                        assignType->get_forall().push_back( typeParam );
    672                         structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
     694                        TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
     695                        genericSubs.add( (*param)->get_name(), newParamType );
     696                        structParams.push_back( new TypeExpr( newParamType ) );
    673697                }
    674698
     
    701725                                }
    702726
    703                                 if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
    704                                         makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
    705                                         if ( isGeneric ) makeArrayAssignment( srcParam, returnVal, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     727                                if ( isGeneric ) {
     728                                        // rewrite member type in terms of the type variables on this operator
     729                                        DeclarationWithType *fixedMember = dwt->clone();
     730                                        genericSubs.apply( fixedMember );
     731
     732                                        // assign to both destination and return value
     733                                        if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
     734                                                makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     735                                                makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     736                                        } else {
     737                                                makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
     738                                                makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
     739                                        } // if
    706740                                } else {
    707                                         makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
    708                                         if ( isGeneric ) makeScalarAssignment( srcParam, returnVal, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
     741                                        // assign to destination
     742                                        if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
     743                                                makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
     744                                        } else {
     745                                                makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
     746                                        } // if
    709747                                } // if
    710748                        } // if
     
    724762                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
    725763                        isGeneric = true;
    726                         TypeDecl *typeParam = (*param)->clone();
     764                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
    727765                        assignType->get_forall().push_back( typeParam );
    728766                        unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
Note: See TracChangeset for help on using the changeset viewer.