Changeset ae1b9ea


Ignore:
Timestamp:
Oct 19, 2017, 11:15:36 AM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
a365e0d
Parents:
aabc60c
git-author:
Rob Schluntz <rschlunt@…> (10/17/17 17:10:04)
git-committer:
Rob Schluntz <rschlunt@…> (10/19/17 11:15:36)
Message:

Always copy construct arguments that require boxing

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    raabc60c rae1b9ea  
    715715                void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
    716716                        assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
    717                         if ( isPolyType( param, exprTyVars ) ) {
    718                                 Type * newType = arg->get_result()->clone();
     717                        if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return;
     718
     719                        if ( arg->result->get_lvalue() ) {
     720                                // argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
     721                                // if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
     722                                //      if ( dynamic_cast<ArrayType *>( varExpr->var->get_type() ) ){
     723                                //              // temporary hack - don't box arrays, because &arr is not the same as &arr[0]
     724                                //              return;
     725                                //      }
     726                                // }
     727                                arg =  generalizedLvalue( new AddressExpr( arg ) );
     728                                if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
     729                                        // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
     730                                        arg = new CastExpr( arg, param->clone() );
     731                                }
     732                        } else {
     733                                // use type computed in unification to declare boxed variables
     734                                Type * newType = param->clone();
    719735                                if ( env ) env->apply( newType );
    720                                 std::unique_ptr<Type> manager( newType );
    721                                 if ( isPolyType( newType ) ) {
    722                                         // if the argument's type is polymorphic, we don't need to box again!
    723                                         return;
    724                                 } else if ( arg->get_result()->get_lvalue() ) {
    725                                         // argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
    726                                         // if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
    727                                         //      if ( dynamic_cast<ArrayType *>( varExpr->var->get_type() ) ){
    728                                         //              // temporary hack - don't box arrays, because &arr is not the same as &arr[0]
    729                                         //              return;
    730                                         //      }
    731                                         // }
    732                                         arg =  generalizedLvalue( new AddressExpr( arg ) );
    733                                         if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
    734                                                 // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
    735                                                 arg = new CastExpr( arg, param->clone() );
    736                                         }
    737                                 } else {
    738                                         // use type computed in unification to declare boxed variables
    739                                         Type * newType = param->clone();
    740                                         if ( env ) env->apply( newType );
    741                                         ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 );
    742                                         newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
    743                                         stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
    744                                         UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
    745                                         assign->get_args().push_back( new VariableExpr( newObj ) );
    746                                         assign->get_args().push_back( arg );
    747                                         stmtsToAddBefore.push_back( new ExprStmt( noLabels, assign ) );
    748                                         arg = new AddressExpr( new VariableExpr( newObj ) );
    749                                 } // if
     736                                ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 );
     737                                newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
     738                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
     739                                UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
     740                                assign->get_args().push_back( new VariableExpr( newObj ) );
     741                                assign->get_args().push_back( arg );
     742                                stmtsToAddBefore.push_back( new ExprStmt( noLabels, assign ) );
     743                                arg = new AddressExpr( new VariableExpr( newObj ) );
    750744                        } // if
    751745                }
  • src/GenPoly/GenPoly.cc

    raabc60c rae1b9ea  
    432432        }
    433433
     434        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env ) {
     435                // is parameter is not polymorphic, don't need to box
     436                if ( ! isPolyType( param, exprTyVars ) ) return false;
     437                Type * newType = arg->clone();
     438                if ( env ) env->apply( newType );
     439                std::unique_ptr<Type> manager( newType );
     440                // if the argument's type is polymorphic, we don't need to box again!
     441                return ! isPolyType( newType );
     442        }
     443
     444        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env ) {
     445                FunctionType * function = getFunctionType( appExpr->function->result );
     446                assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
     447                TyVarMap exprTyVars( TypeDecl::Data{} );
     448                makeTyVarMap( function, exprTyVars );
     449                return needsBoxing( param, arg, exprTyVars, env );
     450        }
     451
    434452        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    435453                // xxx - should this actually be insert?
  • src/GenPoly/GenPoly.h

    raabc60c rae1b9ea  
    8080        bool typesPolyCompatible( Type *aty, Type *bty );
    8181
     82        /// true if arg requires boxing given exprTyVars
     83        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, TypeSubstitution * env );
     84
     85        /// true if arg requires boxing in the call to appExpr
     86        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, TypeSubstitution * env );
     87
    8288        /// Adds the type variable `tyVar` to `tyVarMap`
    8389        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
  • src/InitTweak/FixInit.cc

    raabc60c rae1b9ea  
    9393                        /// true if type does not need to be copy constructed to ensure correctness
    9494                        bool skipCopyConstruct( Type * type );
    95                         void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
     95                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
    9696                        void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    9797
     
    260260
    261261                GenStructMemberCalls::generate( translationUnit );
     262
    262263                // xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a
    263264                // hack in the way untyped assignments are generated, where the first argument cannot have
     
    384385                }
    385386
    386                 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     387                void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ) {
    387388                        static UniqueName tempNamer("_tmp_cp");
    388389                        assert( env );
    389390                        CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
    390391                        assert( arg->result );
    391                         Type * result = arg->get_result();
     392                        Type * result = arg->result;
    392393                        if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
    393394
    394                         // type may involve type variables, so apply type substitution to get temporary variable's actual type
     395                        // type may involve type variables, so apply type substitution to get temporary variable's actual type.
     396                        // Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T).
    395397                        result = result->clone();
    396                         env->apply( result );
     398                        env->applyFree( result );
    397399                        ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
    398400                        tmp->get_type()->set_const( false );
     
    405407                                // if the chosen constructor is intrinsic, the copy is unnecessary, so
    406408                                // don't create the temporary and don't call the copy constructor
    407                                 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
    408                                 assert( function );
    409                                 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
     409                                VariableExpr * function = strict_dynamic_cast< VariableExpr * >( appExpr->function );
     410                                if ( function->var->linkage == LinkageSpec::Intrinsic ) {
     411                                        // arguments that need to be boxed need a temporary regardless of whether the copy constructor is intrinsic,
     412                                        // so that the object isn't changed inside of the polymorphic function
     413                                        if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return;
     414                                }
    410415                        }
    411416
     
    415420                        // replace argument to function call with temporary
    416421                        arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
    417                         impCpCtorExpr->get_tempDecls().push_back( tmp );
    418                         impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
     422                        impCpCtorExpr->tempDecls.push_back( tmp );
     423                        impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
    419424                }
    420425
     
    426431                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    427432
    428                         ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
     433                        ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
    429434
    430435                        // take each argument and attempt to copy construct it.
    431                         for ( Expression * & arg : appExpr->get_args() ) {
    432                                 copyConstructArg( arg, impCpCtorExpr );
     436                        FunctionType * ftype = GenPoly::getFunctionType( appExpr->function->result );
     437                        assert( ftype );
     438                        auto & params = ftype->parameters;
     439                        auto iter = params.begin();
     440                        for ( Expression * & arg : appExpr->args ) {
     441                                Type * formal = nullptr;
     442                                if ( iter != params.end() ) {
     443                                        DeclarationWithType * param = *iter++;
     444                                        formal = param->get_type();
     445                                }
     446
     447                                copyConstructArg( arg, impCpCtorExpr, formal );
    433448                        } // for
    434449
     
    436451                        // initialized with the return value and is destructed later
    437452                        // xxx - handle named return values?
    438                         Type * result = appExpr->get_result();
     453                        Type * result = appExpr->result;
    439454                        if ( ! result->isVoid() ) {
    440455                                static UniqueName retNamer("_tmp_cp_ret");
     
    442457                                env->apply( result );
    443458                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    444                                 ret->get_type()->set_const( false );
    445                                 impCpCtorExpr->get_returnDecls().push_back( ret );
     459                                ret->type->set_const( false );
     460                                impCpCtorExpr->returnDecls.push_back( ret );
    446461                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    447462                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
Note: See TracChangeset for help on using the changeset viewer.