Ignore:
Timestamp:
Aug 11, 2017, 10:04:23 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:
83a071f9
Parents:
b1bead1
Message:

Convert intrinsic expressions to value type, add implicit dereferences to reference-typed address-expressions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    rb1bead1 r8499c707  
    2828#include "SymTab/Indexer.h"
    2929#include "SymTab/Autogen.h"
     30
    3031#include "ResolvExpr/Resolver.h"
    3132#include "ResolvExpr/typeops.h"
     
    3334#include "Common/UniqueName.h"
    3435#include "Common/utility.h"
     36#include "Common/PassVisitor.h"
     37
    3538#include "InitTweak/InitTweak.h"
    36 
    37 #include "Common/PassVisitor.h"
    38 
    39 // need to be careful about polymorphic references... e.g. in *? (___operator_deref__A0_1_0_0__Fd0_Pd0_intrinsic___1)
    40 // the variable is automatically dereferenced and this causes errors dereferencing void*.
    4139
    4240#if 0
     
    5755                                ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
    5856                                delete ret->get_result();
    59                                 ret->set_result( new ReferenceType( Type::Qualifiers(), base->clone() ) );
     57                                ret->set_result( base->clone() );
     58                                ret->get_result()->set_lvalue( true );
    6059                                return ret;
    6160                        } else {
     
    6564
    6665                struct ReferenceConversions final {
     66                        void premutate( AddressExpr * addrExpr );
     67
    6768                        Expression * postmutate( CastExpr * castExpr );
    6869                        Expression * postmutate( AddressExpr * addrExpr );
     
    7172                /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
    7273                struct FixIntrinsicArgs final {
    73                         Expression * postmutate( ApplicationExpr *appExpr );
    74                 };
    75 
     74                        Expression * postmutate( ApplicationExpr * appExpr );
     75                };
     76
     77                struct FixIntrinsicResult final {
     78                        Expression * postmutate( ApplicationExpr * appExpr );
     79                };
    7680
    7781                /// Replace reference types with pointer types
     
    9195                        Expression * postmutate( AddressExpr * addressExpr );
    9296                        Expression * postmutate( ApplicationExpr * appExpr );
     97                };
     98
     99                struct AddrRef final : public WithGuards {
     100                        void premutate( AddressExpr * addrExpr );
     101                        Expression * postmutate( AddressExpr * addrExpr );
     102                        void premutate( Expression * expr );
     103
     104                        bool first = true;
     105                        bool current = false;
     106                        int refDepth = 0;
    93107                };
    94108        } // namespace
     
    107121                PassVisitor<FixIntrinsicArgs> fixer;
    108122                PassVisitor<CollapseAddrDeref> collapser;
     123                PassVisitor<AddrRef> addrRef;
     124                PassVisitor<FixIntrinsicResult> intrinsicResults;
     125                mutateAll( translationUnit, intrinsicResults );
     126                mutateAll( translationUnit, addrRef );
    109127                mutateAll( translationUnit, refCvt );
    110128                mutateAll( translationUnit, fixer );
     129                mutateAll( translationUnit, collapser );
    111130                mutateAll( translationUnit, genLval );
    112                 mutateAll( translationUnit, collapser );
    113131                mutateAll( translationUnit, elim );  // last because other passes need reference types to work
    114132
     
    135153                }
    136154
    137                 // xxx - might need to & every * (or every * that is an arg to non-intrinsic function??)
     155                Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) {
     156                        if ( isIntrinsicReference( appExpr ) ) {
     157                                // eliminate reference types from intrinsic applications - now they return lvalues
     158                                Type * result = appExpr->get_result();
     159                                appExpr->set_result( result->stripReferences()->clone() );
     160                                appExpr->get_result()->set_lvalue( true );
     161                                Expression * ret = new CastExpr( appExpr, result );
     162                                ret->set_env( appExpr->get_env() );
     163                                appExpr->set_env( nullptr );
     164                                return ret;
     165                        }
     166                        return appExpr;
     167                }
     168
    138169                Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
    139170                        // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
     
    144175                                assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
    145176
    146                                 if ( isIntrinsicReference( appExpr ) ) {
    147                                         // eliminate reference types from intrinsic applications - now they return lvalues
    148                                         appExpr->set_result( appExpr->get_result()->stripReferences() );
    149                                         appExpr->get_result()->set_lvalue( true );
    150                                 }
    151177
    152178                                unsigned int i = 0;
     
    161187                                        )
    162188                                        if ( dynamic_cast<ReferenceType*>( formal ) ) {
    163                                                 if ( isIntrinsicReference( arg ) ) {
     189                                                if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if
    164190                                                        if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
    165191                                                                // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
    166                                                                 PRINT( std::cerr << "is intrinsic arg in non-intrinsic call - adding address" << std::endl; )
     192                                                                PRINT(
     193                                                                        std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
     194                                                                )
    167195                                                                arg = new AddressExpr( arg );
    168196                                                        }
    169197                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
     198                                                        // std::cerr << "===adding deref to arg" << std::endl;
    170199                                                        // if the parameter is a reference, add a dereference to the reference-typed argument.
    171200                                                        Type * baseType = InitTweak::getPointerBase( arg->get_result() );
    172                                                         assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ) );
     201                                                        assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() );
    173202                                                        PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
    174203                                                        delete arg->get_result();
     
    183212                }
    184213
     214                // idea: &&&E: get outer &, inner &
     215                // at inner &, record depth D of reference type
     216                // at outer &, add D derefs.
     217                void AddrRef::premutate( Expression * expr ) {
     218                        GuardValue( current );
     219                        GuardValue( first );
     220                        current = false;
     221                        first = true;
     222                }
     223
     224                void AddrRef::premutate( AddressExpr * addrExpr ) {
     225                        GuardValue( current );
     226                        GuardValue( first );
     227                        current = first;
     228                        first = false;
     229                        if ( current ) {
     230                                GuardValue( refDepth );
     231                                refDepth = 0;
     232                        }
     233                }
     234
     235                Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
     236                        if ( refDepth == 0 ) {
     237                                if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) {
     238                                        // try to avoid ?[?]
     239                                        refDepth = addrExpr->get_arg()->get_result()->referenceDepth();
     240                                }
     241                        }
     242                        if ( current ) {
     243                                Expression * ret = addrExpr;
     244                                while ( refDepth ) {
     245                                        ret = mkDeref( ret );
     246                                        refDepth--;
     247                                }
     248                                return ret;
     249                        }
     250                        return addrExpr;
     251                }
     252
    185253                Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
    186254                        // Inner expression may have been lvalue to reference conversion, which becomes an address expression.
    187255                        // In this case, remove the outer address expression and return the argument.
    188256                        // TODO: It's possible that this might catch too much and require a more sophisticated check.
    189                         if ( dynamic_cast<AddressExpr*>( addrExpr->get_arg() ) ) {
    190                                 Expression * arg = addrExpr->get_arg();
    191                                 arg->set_env( addrExpr->get_env() );
    192                                 addrExpr->set_arg( nullptr );
    193                                 addrExpr->set_env( nullptr );
    194                                 delete addrExpr;
    195                                 return arg;
    196                         }
    197257                        return addrExpr;
    198258                }
     
    219279                                                        std::cerr << callExpr << std::endl;
    220280                                                )
     281                                                callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts
     282                                                delete callExpr->get_result();
     283                                                callExpr->set_result( refType->clone() );
    221284                                                // move environment out to new top-level
    222285                                                callExpr->set_env( castExpr->get_env() );
     
    226289                                                return callExpr;
    227290                                        }
    228                                         assertf( false, "non-intrinsic reference with cast of reference to reference not yet supported: ", toString( castExpr ) );
     291                                        int depth1 = refType->referenceDepth();
     292                                        int depth2 = otherRef->referenceDepth();
     293                                        assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
    229294                                        PRINT( std::cerr << castExpr << std::endl; )
    230295                                        return castExpr;
     
    241306                                                // must keep cast if cast-to type is different from the actual type
    242307                                                castExpr->set_arg( ret );
    243 
    244308                                                return castExpr;
    245309                                        }
    246310                                        ret->set_env( castExpr->get_env() );
     311                                        delete ret->get_result();
     312                                        ret->set_result( castExpr->get_result() );
    247313                                        castExpr->set_env( nullptr );
    248314                                        castExpr->set_arg( nullptr );
     315                                        castExpr->set_result( nullptr );
    249316                                        delete castExpr;
    250317                                        return ret;
     
    296363                                Expression * arg1 = commaExpr->get_arg1()->clone();
    297364                                Expression * arg2 = commaExpr->get_arg2()->clone();
     365                                Expression * ret = new CommaExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ) );
     366                                ret->set_env( addrExpr->get_env() );
     367                                addrExpr->set_env( nullptr );
    298368                                delete addrExpr;
    299                                 return new CommaExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ) );
     369                                return ret;
    300370                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( addrExpr->get_arg() ) ) {
    301371                                Expression * arg1 = condExpr->get_arg1()->clone();
    302372                                Expression * arg2 = condExpr->get_arg2()->clone();
    303373                                Expression * arg3 = condExpr->get_arg3()->clone();
     374                                Expression * ret = new ConditionalExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ), (new AddressExpr( arg3 ))->acceptMutator( *visitor ) );
     375                                ret->set_env( addrExpr->get_env() );
     376                                addrExpr->set_env( nullptr );
    304377                                delete addrExpr;
    305                                 return new ConditionalExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ), (new AddressExpr( arg3 ))->acceptMutator( *visitor ) );
     378                                return ret;
    306379                        }
    307380                        return addrExpr;
    308381                }
    309382
    310                 Expression * CollapseAddrDeref::postmutate( AddressExpr * addressExpr ) {
    311                         Expression * arg = addressExpr->get_arg();
     383                Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) {
     384                        Expression * arg = addrExpr->get_arg();
    312385                        if ( isIntrinsicReference( arg ) ) {
    313386                                std::string fname = InitTweak::getFunctionName( arg );
     
    315388                                        Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
    316389                                        Expression * ret = arg0;
    317                                         ret->set_env( addressExpr->get_env() );
     390                                        ret->set_env( addrExpr->get_env() );
    318391                                        arg0 = nullptr;
    319                                         addressExpr->set_env( nullptr );
    320                                         delete addressExpr;
     392                                        addrExpr->set_env( nullptr );
     393                                        delete addrExpr;
    321394                                        return ret;
    322395                                }
    323396                        }
    324                         return addressExpr;
     397                        return addrExpr;
    325398                }
    326399
Note: See TracChangeset for help on using the changeset viewer.