Changeset 0b5d871


Ignore:
Timestamp:
Aug 22, 2017, 7:07:22 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, resolv-new, with_gc
Children:
5fb6830
Parents:
5ccb10d
Message:

Update explode for references

Location:
src/Tuples
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.cc

    r5ccb10d r0b5d871  
    1616#include "Explode.h"
    1717#include "SynTree/Mutator.h"
     18#include "Common/PassVisitor.h"
    1819
    1920namespace Tuples {
    2021        namespace {
    21                 struct AddrExploder : public Mutator {
     22                // remove one level of reference from a reference type -- may be useful elsewhere.
     23                Type * getReferenceBase( Type * t ) {
     24                        if ( ReferenceType * refType = dynamic_cast<ReferenceType *>( t ) ) {
     25                                return refType->get_base();
     26                        } else {
     27                                // for the moment, I want to know immediately if a non-reference type is ever passed in here.
     28                                assertf( false, "getReferenceBase for non-ref: %s", toString( refType ).c_str() );
     29                                return nullptr;
     30                        }
     31                }
     32
     33                struct CastExploder {
     34                        bool castAdded = false;
    2235                        bool foundUniqueExpr = false;
    23                         Expression * applyAddr( Expression * expr, bool first = true ) {
     36                        Expression * applyCast( Expression * expr, bool first = true ) {
    2437                                if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){
    2538                                        foundUniqueExpr = true;
    2639                                        std::list< Expression * > exprs;
    2740                                        for ( Expression *& expr : tupleExpr->get_exprs() ) {
    28                                                 // move & into tuple exprs
    29                                                 exprs.push_back( applyAddr( expr, false ) );
     41                                                // move cast into tuple exprs
     42                                                exprs.push_back( applyCast( expr, false ) );
    3043                                        }
    31                                         // want the top-level expression to be address-taken, but not nested
     44                                        // want the top-level expression to be cast to reference type, but not nested
    3245                                        // tuple expressions
    3346                                        if ( first ) {
    34                                                 return new AddressExpr( new TupleExpr( exprs ) );
     47                                                castAdded = true;
     48                                                Expression * tupleExpr = new TupleExpr( exprs );
     49                                                return new CastExpr( tupleExpr, new ReferenceType( Type::Qualifiers(), tupleExpr->result->clone() ) );
    3550                                        } else {
    3651                                                return new TupleExpr( exprs );
    3752                                        }
    3853                                }
    39                                 // anything else should be address-taken as normal
    40                                 return new AddressExpr( expr->clone() );
     54                                if ( dynamic_cast<ReferenceType*>( expr->result ) ) {
     55                                        // don't need to cast reference type to another reference type
     56                                        return expr->clone();
     57                                } else {
     58                                        // anything else should be cast to reference as normal
     59                                        castAdded = true;
     60                                        return new CastExpr( expr->clone(), new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
     61                                }
    4162                        }
    4263
    43                         virtual Expression * mutate( UniqueExpr * uniqueExpr ) {
    44                                 // move & into unique expr so that the unique expr has type T* rather than
     64                        Expression * postmutate( UniqueExpr * uniqueExpr ) {
     65                                // move cast into unique expr so that the unique expr has type T& rather than
    4566                                // type T. In particular, this transformation helps with generating the
    46                                 // correct code for address-taken member tuple expressions, since the result
    47                                 // should now be a tuple of addresses rather than the address of a tuple.
     67                                // correct code for reference-cast member tuple expressions, since the result
     68                                // should now be a tuple of references rather than a reference to a tuple.
    4869                                // Still, this code is a bit awkward, and could use some improvement.
    49                                 if ( dynamic_cast< AddressExpr * > ( uniqueExpr->get_expr() ) ) {
    50                                         // this unique expression has already been mutated or otherwise shouldn't be (can't take the address-of an address-of expression)
    51                                         return uniqueExpr;
     70                                UniqueExpr * newUniqueExpr = new UniqueExpr( applyCast( uniqueExpr->get_expr() ), uniqueExpr->get_id() );
     71                                delete uniqueExpr;
     72                                if ( castAdded ) {
     73                                        // if a cast was added by applyCast, then unique expr now has one more layer of reference
     74                                        // than it had coming into this function. To ensure types still match correctly, need to cast
     75                                        //  to reference base so that outer expressions are still correct.
     76                                        castAdded = false;
     77                                        Type * toType = getReferenceBase( newUniqueExpr->result );
     78                                        return new CastExpr( newUniqueExpr, toType->clone() );
    5279                                }
    53                                 UniqueExpr * newUniqueExpr = new UniqueExpr( applyAddr( uniqueExpr->get_expr() ), uniqueExpr->get_id() );
    54                                 delete uniqueExpr;
    55                                 UntypedExpr * deref = UntypedExpr::createDeref( Mutator::mutate( newUniqueExpr ) );
    56                                 return deref;
     80                                return newUniqueExpr;
    5781                        }
    5882
    59                         virtual Expression * mutate( TupleIndexExpr * tupleExpr ) {
     83
     84                        Expression * postmutate( TupleIndexExpr * tupleExpr ) {
    6085                                // tuple index expr needs to be rebuilt to ensure that the type of the
    6186                                // field is consistent with the type of the tuple expr, since the field
    62                                 // may have changed from type T to T*.
    63                                 Expression * expr = tupleExpr->get_tuple()->acceptMutator( *this );
     87                                // may have changed from type T to T&.
     88                                Expression * expr = tupleExpr->get_tuple();
    6489                                tupleExpr->set_tuple( nullptr );
    6590                                TupleIndexExpr * ret = new TupleIndexExpr( expr, tupleExpr->get_index() );
     
    7095        } // namespace
    7196
    72         Expression * distributeAddr( Expression * expr ) {
    73                 AddrExploder addrExploder;
    74                 expr = expr->acceptMutator( addrExploder );
    75                 if ( ! addrExploder.foundUniqueExpr ) {
    76                         expr = new AddressExpr( expr );
     97        Expression * distributeReference( Expression * expr ) {
     98                PassVisitor<CastExploder> exploder;
     99                expr = expr->acceptMutator( exploder );
     100                if ( ! exploder.pass.foundUniqueExpr ) {
     101                        // if a UniqueExpr was found, then the cast has already been added inside the UniqueExpr as appropriate
     102                        expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
    77103                }
    78104                return expr;
  • src/Tuples/Explode.h

    r5ccb10d r0b5d871  
    2626
    2727namespace Tuples {
     28        Expression * distributeReference( Expression * );
     29
    2830        /// helper function used by explode
    2931        template< typename OutputIterator >
    3032        void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign ) {
     33                if ( isTupleAssign ) {
     34                        // tuple assignment needs CastExprs to be recursively exploded to easily get at all of the components
     35                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     36                                ResolvExpr::AltList alts;
     37                                explodeUnique( castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );
     38                                for ( ResolvExpr::Alternative & alt : alts ) {
     39                                        // distribute reference cast over all components
     40                                        alt.expr = distributeReference( alt.expr );
     41                                        *out++ = alt;
     42                                }
     43                                // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives)
     44                                return;
     45                        }
     46                }
    3147                Type * res = expr->get_result()->stripReferences();
    3248                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) {
     
    4056                                // if expr type is reference, convert to value type
    4157                                Expression * arg = expr->clone();
    42 
    43                                 if ( dynamic_cast<ReferenceType *>( arg->get_result() ) ) {
    44                                         // TODO: does this go here (inside uniqueexpr) or outside uniqueexpr? I'm guessing probably should go after...
    45                                         arg = new CastExpr( arg, tupleType->clone() );
    46                                 }
    47                                 if ( Tuples::maybeImpure( arg ) && ! dynamic_cast< UniqueExpr * >( arg ) ) {
     58                                if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    4859                                        // expressions which may contain side effects require a single unique instance of the expression.
    4960                                        arg = new UniqueExpr( arg );
     61                                }
     62                                // cast reference to value type to facilitate further explosion
     63                                if ( dynamic_cast<ReferenceType *>( arg->get_result() ) ) {
     64                                        arg = new CastExpr( arg, tupleType->clone() );
    5065                                }
    5166                                for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
Note: See TracChangeset for help on using the changeset viewer.