Changeset d335627


Ignore:
Timestamp:
Jul 25, 2017, 10:48:07 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:
8a6cf7e
Parents:
6d267ca
Message:

Add address-of to intrinsic reference-returning functions that are arguments to non-intrinsic functions

Location:
src/GenPoly
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    r6d267ca rd335627  
    10271027                                                } // if
    10281028                                                if ( baseType1 || baseType2 ) {
    1029                                                         ret->set_result( appExpr->get_result()->clone() );
     1029                                                        Type * baseType = InitTweak::getPointerBase( appExpr->get_result() );
     1030                                                        assert( baseType );
     1031                                                        ret->set_result( baseType->clone() );
    10301032                                                        if ( appExpr->get_env() ) {
    10311033                                                                ret->set_env( appExpr->get_env() );
     
    12221224                        // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
    12231225                        // out of the if condition.
     1226                        addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
     1227                        // ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment
    12241228                        bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
    1225                         addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
    12261229                        if ( polytype || needs ) {
    12271230                                Expression *ret = addrExpr->get_arg();
  • src/GenPoly/Lvalue.cc

    r6d267ca rd335627  
    8282                /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
    8383                /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
    84                 struct GeneralizedLvalue final {
     84                struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
    8585                        Expression * postmutate( AddressExpr * addressExpr );
    8686                };
     
    145145                }
    146146
    147                 void fixArg( Expression *& arg, Type * formal ) {
    148                         if ( dynamic_cast<ReferenceType*>( formal ) ) {
    149                                 // if the parameter is a reference, add a dereference to the reference-typed argument.
    150                                 Type * baseType = InitTweak::getPointerBase( arg->get_result() );
    151                                 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ) );
    152                                 PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
    153                                 delete arg->get_result();
    154                                 arg->set_result( ptrType );
    155                                 arg = mkDeref( arg );
    156                         }
    157                 }
    158 
    159147                // xxx - might need to & every * (or every * that is an arg to non-intrinsic function??)
    160148                Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
    161149                        // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
    162150                        if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
    163                                 if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
    164                                         FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
    165                                         assertf( ftype, "Function declaration does not have function type." );
    166                                         for ( auto p : group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
    167                                                 Expression *& arg = std::get<0>( p );
    168                                                 DeclarationWithType * formal = std::get<1>( p );
    169                                                 PRINT(
    170                                                         std::cerr << "pair<0>: " << arg << std::endl;
    171                                                         std::cerr << "pair<1>: " << formal->get_type() << std::endl;
    172                                                 )
    173                                                 if ( isIntrinsicReference( arg ) ) { // intrinsic functions that turn pointers into references
    174                                                         // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
    175                                                         PRINT( std::cerr << "skipping intrinsic reference" << std::endl; )
    176                                                         continue;
    177                                                 } else {
    178                                                         fixArg( arg, formal->get_type() );
     151                                FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
     152                                assertf( ftype, "Function declaration does not have function type." );
     153                                // can be of differing lengths only when function is variadic
     154                                assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
     155                                unsigned int i = 0;
     156                                const unsigned int end = ftype->get_parameters().size();
     157                                for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
     158                                        if (i == end) break;
     159                                        Expression *& arg = std::get<0>( p );
     160                                        Type * formal = std::get<1>( p )->get_type();
     161                                        PRINT(
     162                                                std::cerr << "pair<0>: " << arg << std::endl;
     163                                                std::cerr << "pair<1>: " << formal << std::endl;
     164                                        )
     165                                        if ( dynamic_cast<ReferenceType*>( formal ) ) {
     166                                                if ( isIntrinsicReference( arg ) ) {
     167                                                        if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
     168                                                                // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
     169                                                                PRINT( std::cerr << "is intrinsic arg in non-intrinsic call - adding address" << std::endl; )
     170                                                                arg = new AddressExpr( arg );
     171                                                        }
     172                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
     173                                                        // if the parameter is a reference, add a dereference to the reference-typed argument.
     174                                                        Type * baseType = InitTweak::getPointerBase( arg->get_result() );
     175                                                        assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ) );
     176                                                        PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
     177                                                        delete arg->get_result();
     178                                                        arg->set_result( ptrType );
     179                                                        arg = mkDeref( arg );
    179180                                                }
    180181                                        }
     182                                        ++i;
    181183                                }
    182184                        }
     
    240242                                assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
    241243                        } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     244                                (void)refType;
    242245                                // conversion from reference to rvalue
    243246                                PRINT( std::cerr << "convert reference to rvalue -- *" << std::endl; )
     
    270273                                Expression * arg2 = commaExpr->get_arg2()->clone();
    271274                                delete addrExpr;
    272                                 return new CommaExpr( arg1, new AddressExpr( arg2 ) );
     275                                return new CommaExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ) );
    273276                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( addrExpr->get_arg() ) ) {
    274277                                Expression * arg1 = condExpr->get_arg1()->clone();
     
    276279                                Expression * arg3 = condExpr->get_arg3()->clone();
    277280                                delete addrExpr;
    278                                 return new ConditionalExpr( arg1, new AddressExpr( arg2 ), new AddressExpr( arg3 ) );
     281                                return new ConditionalExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ), (new AddressExpr( arg3 ))->acceptMutator( *visitor ) );
    279282                        }
    280283                        return addrExpr;
Note: See TracChangeset for help on using the changeset viewer.