Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    r8499c707 racd7c5dd  
    2727#include "SynTree/Mutator.h"
    2828#include "SymTab/Indexer.h"
    29 #include "SymTab/Autogen.h"
    3029
    3130#include "ResolvExpr/Resolver.h"
     31#include "ResolvExpr/TypeEnvironment.h"
    3232#include "ResolvExpr/typeops.h"
     33#include "ResolvExpr/Unify.h"
    3334
    3435#include "Common/UniqueName.h"
    3536#include "Common/utility.h"
    36 #include "Common/PassVisitor.h"
    37 
    38 #include "InitTweak/InitTweak.h"
    39 
    40 #if 0
    41 #define PRINT(x) x
    42 #else
    43 #define PRINT(x)
    44 #endif
    4537
    4638namespace GenPoly {
    4739        namespace {
    48                 // TODO: fold this into the general createDeref function??
    49                 Expression * mkDeref( Expression * arg ) {
    50                         if ( SymTab::dereferenceOperator ) {
    51                                 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
    52                                 deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) );
    53                                 Type * base = InitTweak::getPointerBase( arg->get_result() );
    54                                 assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() );
    55                                 ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
    56                                 delete ret->get_result();
    57                                 ret->set_result( base->clone() );
    58                                 ret->get_result()->set_lvalue( true );
    59                                 return ret;
    60                         } else {
    61                                 return UntypedExpr::createDeref( arg );
    62                         }
    63                 }
    64 
    65                 struct ReferenceConversions final {
    66                         void premutate( AddressExpr * addrExpr );
    67 
    68                         Expression * postmutate( CastExpr * castExpr );
    69                         Expression * postmutate( AddressExpr * addrExpr );
     40                /// Replace uses of lvalue returns with appropriate pointers
     41                class Pass1 : public Mutator {
     42                  public:
     43                        Pass1();
     44
     45                        virtual Expression *mutate( ApplicationExpr *appExpr );
     46                        virtual Statement *mutate( ReturnStmt *appExpr );
     47                        virtual DeclarationWithType *mutate( FunctionDecl *funDecl );
     48                  private:
     49                        DeclarationWithType* retval;
    7050                };
    7151
    72                 /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
    73                 struct FixIntrinsicArgs final {
    74                         Expression * postmutate( ApplicationExpr * appExpr );
    75                 };
    76 
    77                 struct FixIntrinsicResult final {
    78                         Expression * postmutate( ApplicationExpr * appExpr );
    79                 };
    80 
    81                 /// Replace reference types with pointer types
    82                 struct ReferenceTypeElimination final {
    83                         Type * postmutate( ReferenceType * refType );
     52                /// Replace declarations of lvalue returns with appropriate pointers
     53                class Pass2 : public Visitor {
     54                  public:
     55                        virtual void visit( FunctionType *funType );
     56                  private:
    8457                };
    8558
     
    8760                /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
    8861                /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
    89                 struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
    90                         Expression * postmutate( AddressExpr * addressExpr );
    91                 };
    92 
    93                 /// Removes redundant &*/*& pattern that this pass can generate
    94                 struct CollapseAddrDeref final {
    95                         Expression * postmutate( AddressExpr * addressExpr );
    96                         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;
     62                class GeneralizedLvalue : public Mutator {
     63                        typedef Mutator Parent;
     64
     65                        virtual Expression * mutate( MemberExpr * memExpr );
     66                        virtual Expression * mutate( AddressExpr * addressExpr );
     67
     68                        template<typename Func>
     69                        Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr );
    10770                };
    10871        } // namespace
    10972
    110         static bool referencesEliminated = false;
    111         // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type.
    112         bool referencesPermissable() {
    113                 return ! referencesEliminated;
     73        void convertLvalue( std::list< Declaration* >& translationUnit ) {
     74                Pass1 p1;
     75                Pass2 p2;
     76                GeneralizedLvalue genLval;
     77                mutateAll( translationUnit, p1 );
     78                acceptAll( translationUnit, p2 );
     79                mutateAll( translationUnit, genLval );
    11480        }
    11581
    116         void convertLvalue( std::list< Declaration* >& translationUnit ) {
    117                 std::cerr << "convertLvalue" << std::endl;
    118                 PassVisitor<ReferenceConversions> refCvt;
    119                 PassVisitor<ReferenceTypeElimination> elim;
    120                 PassVisitor<GeneralizedLvalue> genLval;
    121                 PassVisitor<FixIntrinsicArgs> fixer;
    122                 PassVisitor<CollapseAddrDeref> collapser;
    123                 PassVisitor<AddrRef> addrRef;
    124                 PassVisitor<FixIntrinsicResult> intrinsicResults;
    125                 mutateAll( translationUnit, intrinsicResults );
    126                 mutateAll( translationUnit, addrRef );
    127                 mutateAll( translationUnit, refCvt );
    128                 mutateAll( translationUnit, fixer );
    129                 mutateAll( translationUnit, collapser );
    130                 mutateAll( translationUnit, genLval );
    131                 mutateAll( translationUnit, elim );  // last because other passes need reference types to work
    132 
    133                 // from this point forward, no other pass should create reference types.
    134                 referencesEliminated = true;
     82        Expression * generalizedLvalue( Expression * expr ) {
     83                GeneralizedLvalue genLval;
     84                return expr->acceptMutator( genLval );
    13585        }
    13686
    13787        namespace {
    138                 // true for intrinsic function calls that return a reference
    139                 bool isIntrinsicReference( Expression * expr ) {
    140                         if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    141                                 std::string fname = InitTweak::getFunctionName( untyped );
    142                                 // known intrinsic-reference prelude functions
    143                                 return fname == "*?" || fname == "?[?]";
    144                         } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    145                                 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    146                                         // use type of return variable rather than expr result type, since it may have been changed to a pointer type
    147                                         FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
    148                                         Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type();
    149                                         return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
     88                Type* isLvalueRet( FunctionType *function ) {
     89                        if ( function->get_returnVals().empty() ) return 0;
     90                        Type *ty = function->get_returnVals().front()->get_type();
     91                        return ty->get_lvalue() ? ty : 0;
     92                }
     93
     94                bool isIntrinsicApp( ApplicationExpr *appExpr ) {
     95                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) {
     96                                return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic;
     97                        } else {
     98                                return false;
     99                        } // if
     100                }
     101
     102                Pass1::Pass1() {
     103                }
     104
     105                DeclarationWithType * Pass1::mutate( FunctionDecl *funcDecl ) {
     106                        if ( funcDecl->get_statements() ) {
     107                                DeclarationWithType* oldRetval = retval;
     108                                retval = 0;
     109                                if ( ! LinkageSpec::isBuiltin( funcDecl->get_linkage() ) && isLvalueRet( funcDecl->get_functionType() ) ) {
     110                                        retval = funcDecl->get_functionType()->get_returnVals().front();
    150111                                }
    151                         }
    152                         return false;
    153                 }
    154 
    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 
    169                 Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
    170                         // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
    171                         if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
    172                                 FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
    173                                 assertf( ftype, "Function declaration does not have function type." );
    174                                 // can be of differing lengths only when function is variadic
    175                                 assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
    176 
    177 
    178                                 unsigned int i = 0;
    179                                 const unsigned int end = ftype->get_parameters().size();
    180                                 for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
    181                                         if (i == end) break;
    182                                         Expression *& arg = std::get<0>( p );
    183                                         Type * formal = std::get<1>( p )->get_type();
    184                                         PRINT(
    185                                                 std::cerr << "pair<0>: " << arg << std::endl;
    186                                                 std::cerr << "pair<1>: " << formal << std::endl;
    187                                         )
    188                                         if ( dynamic_cast<ReferenceType*>( formal ) ) {
    189                                                 if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if
    190                                                         if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
    191                                                                 // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
    192                                                                 PRINT(
    193                                                                         std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
    194                                                                 )
    195                                                                 arg = new AddressExpr( arg );
    196                                                         }
    197                                                 } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
    198                                                         // std::cerr << "===adding deref to arg" << std::endl;
    199                                                         // if the parameter is a reference, add a dereference to the reference-typed argument.
    200                                                         Type * baseType = InitTweak::getPointerBase( arg->get_result() );
    201                                                         assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() );
    202                                                         PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
    203                                                         delete arg->get_result();
    204                                                         arg->set_result( ptrType );
    205                                                         arg = mkDeref( arg );
    206                                                 }
    207                                         }
    208                                         ++i;
     112                                // fix expressions and return statements in this function
     113                                funcDecl->set_statements( funcDecl->get_statements()->acceptMutator( *this ) );
     114                                retval = oldRetval;
     115                        } // if
     116                        return funcDecl;
     117                }
     118
     119                Expression * Pass1::mutate( ApplicationExpr *appExpr ) {
     120                        appExpr->get_function()->acceptMutator( *this );
     121                        mutateAll( appExpr->get_args(), *this );
     122
     123                        PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
     124                        FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
     125
     126                        Type *funType = isLvalueRet( function );
     127                        if ( funType && ! isIntrinsicApp( appExpr ) ) {
     128                                Expression *expr = appExpr;
     129                                Type *appType = appExpr->get_result();
     130                                if ( isPolyType( funType ) && ! isPolyType( appType ) ) {
     131                                        // make sure cast for polymorphic type is inside dereference
     132                                        expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) );
    209133                                }
    210                         }
    211                         return appExpr;
    212                 }
    213 
    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 
    253                 Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
    254                         // Inner expression may have been lvalue to reference conversion, which becomes an address expression.
    255                         // In this case, remove the outer address expression and return the argument.
    256                         // TODO: It's possible that this might catch too much and require a more sophisticated check.
    257                         return addrExpr;
    258                 }
    259 
    260                 Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
    261                         // xxx - is it possible to convert directly between reference types with a different base? E.g.,
    262                         //   int x;
    263                         //   (double&)x;
    264                         // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant
    265                         // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct
    266                         // pointer casts in the right places.
    267 
    268                         // conversion to reference type
    269                         if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) {
    270                                 (void)refType;
    271                                 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
    272                                         // nothing to do if casting from reference to reference.
    273                                         (void)otherRef;
    274                                         PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; )
    275                                         if ( isIntrinsicReference( castExpr->get_arg() ) ) {
    276                                                 Expression * callExpr = castExpr->get_arg();
    277                                                 PRINT(
    278                                                         std::cerr << "but arg is deref -- &" << std::endl;
    279                                                         std::cerr << callExpr << std::endl;
    280                                                 )
    281                                                 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts
    282                                                 delete callExpr->get_result();
    283                                                 callExpr->set_result( refType->clone() );
    284                                                 // move environment out to new top-level
    285                                                 callExpr->set_env( castExpr->get_env() );
    286                                                 castExpr->set_arg( nullptr );
    287                                                 castExpr->set_env( nullptr );
    288                                                 delete castExpr;
    289                                                 return callExpr;
    290                                         }
    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() );
    294                                         PRINT( std::cerr << castExpr << std::endl; )
    295                                         return castExpr;
    296                                 } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
    297                                         // conversion from lvalue to reference
    298                                         // xxx - keep cast, but turn into pointer cast??
    299                                         // xxx - memory
    300                                         PRINT(
    301                                                 std::cerr << "convert lvalue to reference -- &" << std::endl;
    302                                                 std::cerr << castExpr->get_arg() << std::endl;
    303                                         )
    304                                         AddressExpr * ret = new AddressExpr( castExpr->get_arg() );
    305                                         if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {
    306                                                 // must keep cast if cast-to type is different from the actual type
    307                                                 castExpr->set_arg( ret );
    308                                                 return castExpr;
    309                                         }
    310                                         ret->set_env( castExpr->get_env() );
    311                                         delete ret->get_result();
    312                                         ret->set_result( castExpr->get_result() );
    313                                         castExpr->set_env( nullptr );
    314                                         castExpr->set_arg( nullptr );
    315                                         castExpr->set_result( nullptr );
    316                                         delete castExpr;
    317                                         return ret;
     134                                UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
     135                                deref->set_result( appType->clone() );
     136                                appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) );
     137                                deref->get_args().push_back( expr );
     138                                return deref;
     139                        } else {
     140                                return appExpr;
     141                        } // if
     142                }
     143
     144                Statement * Pass1::mutate(ReturnStmt *retStmt) {
     145                        if ( retval && retStmt->get_expr() ) {
     146                                if ( retStmt->get_expr()->get_result()->get_lvalue() ) {
     147                                        // ***** Code Removal ***** because casts may be stripped already
     148
     149                                        // strip casts because not allowed to take address of cast
     150                                        // while ( CastExpr *castExpr = dynamic_cast< CastExpr* >( retStmt->get_expr() ) ) {
     151                                        //      retStmt->set_expr( castExpr->get_arg() );
     152                                        //      retStmt->get_expr()->set_env( castExpr->get_env() );
     153                                        //      castExpr->set_env( 0 );
     154                                        //      castExpr->set_arg( 0 );
     155                                        //      delete castExpr;
     156                                        // } // while
     157                                        retStmt->set_expr( new AddressExpr( retStmt->get_expr()->acceptMutator( *this ) ) );
    318158                                } else {
    319                                         // rvalue to reference conversion -- introduce temporary
    320                                 }
    321                                 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
    322                         } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
    323                                 (void)refType;
    324                                 // conversion from reference to rvalue
    325                                 PRINT(
    326                                         std::cerr << "convert reference to rvalue -- *" << std::endl;
    327                                         std::cerr << "was = " << castExpr << std::endl;
    328                                 )
    329                                 Expression * ret = castExpr->get_arg();
    330                                 TypeSubstitution * env = castExpr->get_env();
    331                                 castExpr->set_env( nullptr );
    332                                 if ( ! isIntrinsicReference( ret ) ) {
    333                                         // dereference if not already dereferenced
    334                                         ret = mkDeref( ret );
    335                                 }
    336                                 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {
    337                                         // can remove cast if types are compatible, changing expression type to value type
    338                                         ret->set_result( castExpr->get_result()->clone() );
    339                                         castExpr->set_arg( nullptr );
    340                                         delete castExpr;
    341                                 } else {
    342                                         // must keep cast if types are different
    343                                         castExpr->set_arg( ret );
    344                                         ret = castExpr;
    345                                 }
    346                                 ret->set_env( env );
    347                                 PRINT( std::cerr << "now: " << ret << std::endl; )
    348                                 return ret;
    349                         }
    350                         return castExpr;
    351                 }
    352 
    353                 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
    354                         Type * base = refType->get_base();
    355                         Type::Qualifiers qualifiers = refType->get_qualifiers();
    356                         refType->set_base( nullptr );
    357                         delete refType;
    358                         return new PointerType( qualifiers, base );
    359                 }
    360 
    361                 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
    362                         if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( addrExpr->get_arg() ) ) {
     159                                        throw SemanticError( "Attempt to return non-lvalue from an lvalue-qualified function" );
     160                                } // if
     161                        } // if
     162                        return retStmt;
     163                }
     164
     165                void Pass2::visit( FunctionType *funType ) {
     166                        std::string typeName;
     167                        if ( isLvalueRet( funType ) ) {
     168                                DeclarationWithType *retParm = funType->get_returnVals().front();
     169
     170                                // make a new parameter that is a pointer to the type of the old return value
     171                                retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
     172                        } // if
     173
     174                        Visitor::visit( funType );
     175                }
     176
     177                template<typename Func>
     178                Expression * GeneralizedLvalue::applyTransformation( Expression * expr, Expression * arg, Func mkExpr ) {
     179                        if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( arg ) ) {
    363180                                Expression * arg1 = commaExpr->get_arg1()->clone();
    364181                                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 );
    368                                 delete addrExpr;
    369                                 return ret;
    370                         } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( addrExpr->get_arg() ) ) {
     182                                Expression * ret = new CommaExpr( arg1, mkExpr( arg2 ) );
     183                                ret->set_env( expr->get_env() );
     184                                expr->set_env( nullptr );
     185                                delete expr;
     186                                return ret->acceptMutator( *this );
     187                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) {
    371188                                Expression * arg1 = condExpr->get_arg1()->clone();
    372189                                Expression * arg2 = condExpr->get_arg2()->clone();
    373190                                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 );
    377                                 delete addrExpr;
    378                                 return ret;
     191                                ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 ), mkExpr( arg3 ) );
     192                                ret->set_env( expr->get_env() );
     193                                expr->set_env( nullptr );
     194                                delete expr;
     195
     196                                // conditional expr type may not be either of the argument types, need to unify
     197                                using namespace ResolvExpr;
     198                                Type* commonType = nullptr;
     199                                TypeEnvironment newEnv;
     200                                AssertionSet needAssertions, haveAssertions;
     201                                OpenVarSet openVars;
     202                                unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );
     203                                ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() );
     204                                return ret->acceptMutator( *this );
    379205                        }
    380                         return addrExpr;
    381                 }
    382 
    383                 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) {
    384                         Expression * arg = addrExpr->get_arg();
    385                         if ( isIntrinsicReference( arg ) ) {
    386                                 std::string fname = InitTweak::getFunctionName( arg );
    387                                 if ( fname == "*?" ) {
    388                                         Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
    389                                         Expression * ret = arg0;
    390                                         ret->set_env( addrExpr->get_env() );
    391                                         arg0 = nullptr;
    392                                         addrExpr->set_env( nullptr );
    393                                         delete addrExpr;
    394                                         return ret;
    395                                 }
    396                         }
    397                         return addrExpr;
    398                 }
    399 
    400                 Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) {
    401                         if ( isIntrinsicReference( appExpr ) ) {
    402                                 std::string fname = InitTweak::getFunctionName( appExpr );
    403                                 if ( fname == "*?" ) {
    404                                         Expression * arg = InitTweak::getCallArg( appExpr, 0 );
    405                                         // xxx - this isn't right, because it can remove casts that should be there...
    406                                         // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
    407                                         //      arg = castExpr->get_arg();
    408                                         // }
    409                                         if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) {
    410                                                 Expression * ret = addrExpr->get_arg();
    411                                                 ret->set_env( appExpr->get_env() );
    412                                                 addrExpr->set_arg( nullptr );
    413                                                 appExpr->set_env( nullptr );
    414                                                 delete appExpr;
    415                                                 return ret;
    416                                         }
    417                                 }
    418                         }
    419                         return appExpr;
     206                        return expr;
     207                }
     208
     209                Expression * GeneralizedLvalue::mutate( MemberExpr * memExpr ) {
     210                        Parent::mutate( memExpr );
     211                        return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } );
     212                }
     213
     214                Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) {
     215                        addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) );
     216                        return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } );
    420217                }
    421218        } // namespace
Note: See TracChangeset for help on using the changeset viewer.