Ignore:
Timestamp:
Apr 23, 2018, 12:57:46 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, with_gc
Children:
57acae0
Parents:
ba89e9b (diff), c8ad5d9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into references

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    rba89e9b rda7fe39  
    9999                };
    100100
    101                 struct AddrRef final : public WithGuards {
     101                struct AddrRef final : public WithGuards, public WithVisitorRef<AddrRef>, public WithShortCircuiting {
    102102                        void premutate( AddressExpr * addrExpr );
    103103                        Expression * postmutate( AddressExpr * addrExpr );
    104104                        void premutate( Expression * expr );
     105                        void premutate( ApplicationExpr * appExpr );
     106                        void premutate( SingleInit * init );
     107
     108                        void handleNonAddr( Expression * );
    105109
    106110                        bool first = true;
    107111                        bool current = false;
    108112                        int refDepth = 0;
     113                        bool addCast = false;
    109114                };
    110115        } // namespace
     
    215220                                                )
    216221                                                // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
    217                                                 // if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    218                                                 //      // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
    219                                                 //      // PRINT(
    220                                                 //              std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
    221                                                 //      // )
    222                                                 //      arg = new AddressExpr( arg );
    223                                                 // } else
    224                                                 // if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
    225                                                 if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
    226 
     222
     223                                                if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
    227224                                                        // needed for definition of prelude functions, etc.
    228 
     225                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     226
     227                                                        // NOTE: previously, this condition fixed
     228                                                        //   void f(int *&);
     229                                                        //   int & x = ...;
     230                                                        //   f(&x);
     231                                                        // But now this is taken care of by a reference cast added by AddrRef. Need to find a new
     232                                                        // example or remove this branch.
     233
     234                                                        PRINT(
     235                                                                std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
     236                                                        )
     237                                                        arg = new AddressExpr( arg );
     238                                                // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
     239                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
    229240                                                        // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
    230241                                                        PRINT(
     
    247258
    248259                // idea: &&&E: get outer &, inner &
    249                 // at inner &, record depth D of reference type
     260                // at inner &, record depth D of reference type of argument of &
    250261                // at outer &, add D derefs.
    251                 void AddrRef::premutate( Expression * ) {
     262                void AddrRef::handleNonAddr( Expression * ) {
     263                        // non-address-of: reset status variables:
     264                        // * current expr is NOT the first address-of expr in an address-of chain
     265                        // * next seen address-of expr IS the first in the chain.
    252266                        GuardValue( current );
    253267                        GuardValue( first );
     
    256270                }
    257271
     272                void AddrRef::premutate( Expression * expr ) {
     273                        handleNonAddr( expr );
     274                        GuardValue( addCast );
     275                        addCast = false;
     276                }
     277
    258278                void AddrRef::premutate( AddressExpr * ) {
    259279                        GuardValue( current );
    260280                        GuardValue( first );
    261                         current = first;
    262                         first = false;
    263                         if ( current ) {
     281                        current = first; // is this the first address-of in the chain?
     282                        first = false;   // from here out, no longer possible for next address-of to be first in chain
     283                        if ( current ) { // this is the outermost address-of in a chain
    264284                                GuardValue( refDepth );
    265                                 refDepth = 0;
     285                                refDepth = 0;  // set depth to 0 so that postmutate can find the innermost address-of easily
    266286                        }
    267287                }
    268288
    269289                Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
     290                        PRINT( std::cerr << "addr ref at " << addrExpr << std::endl; )
    270291                        if ( refDepth == 0 ) {
     292                                PRINT( std::cerr << "depth 0, get new depth..." << std::endl; )
     293                                // this is the innermost address-of in a chain, record depth D
    271294                                if ( ! isIntrinsicReference( addrExpr->arg ) ) {
    272295                                        // try to avoid ?[?]
     296                                        // xxx - is this condition still necessary? intrinsicReferences should have a cast around them at this point, so I don't think this condition ever fires.
    273297                                        refDepth = addrExpr->arg->result->referenceDepth();
    274                                 }
    275                         }
    276                         if ( current ) {
     298                                        PRINT( std::cerr << "arg not intrinsic reference, new depth is: " << refDepth << std::endl; )
     299                                } else {
     300                                        assertf( false, "AddrRef : address-of should not have intrinsic reference argument: %s", toCString( addrExpr->arg ) );
     301                                }
     302                        }
     303                        if ( current ) { // this is the outermost address-of in a chain
     304                                PRINT( std::cerr << "current, depth is: " << refDepth << std::endl; )
    277305                                Expression * ret = addrExpr;
    278306                                while ( refDepth ) {
     307                                        // add one dereference for each
    279308                                        ret = mkDeref( ret );
    280309                                        refDepth--;
    281310                                }
     311
     312                                if ( addCast ) {
     313                                        PRINT( std::cerr << "adding cast..." << std::endl; )
     314                                        return new CastExpr( ret, addrExpr->result->clone() );
     315                                }
    282316                                return ret;
    283317                        }
     318                        PRINT( std::cerr << "not current..." << std::endl; )
    284319                        return addrExpr;
    285320                }
     321
     322                void AddrRef::premutate( ApplicationExpr * appExpr ) {
     323                        visit_children = false;
     324                        GuardValue( addCast );
     325                        handleNonAddr( appExpr );
     326                        for ( Expression *& arg : appExpr->args ) {
     327                                // each argument with address-of requires a cast
     328                                addCast = true;
     329                                arg = arg->acceptMutator( *visitor );
     330                        }
     331                }
     332
     333                void AddrRef::premutate( SingleInit * ) {
     334                        GuardValue( addCast );
     335                        // each initialization context with address-of requires a cast
     336                        addCast = true;
     337                }
     338
    286339
    287340                Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
     
    391444                                assert( diff == 0 );
    392445                                // conversion between references of the same depth
     446                                if ( ResolvExpr::typesCompatible( castExpr->result, castExpr->arg->result, SymTab::Indexer() ) && castExpr->isGenerated ) {
     447                                        // Remove useless generated casts
     448                                        PRINT(
     449                                                std::cerr << "types are compatible, removing cast: " << castExpr << std::endl;
     450                                                std::cerr << "-- " << castExpr->result << std::endl;
     451                                                std::cerr << "-- " << castExpr->arg->result << std::endl;
     452                                        )
     453                                        Expression * ret = castExpr->arg;
     454                                        castExpr->arg = nullptr;
     455                                        std::swap( castExpr->env, ret->env );
     456                                        delete castExpr;
     457                                        return ret;
     458                                }
    393459                                return castExpr;
    394460                        }
Note: See TracChangeset for help on using the changeset viewer.