Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    racd7c5dd r8499c707  
    2727#include "SynTree/Mutator.h"
    2828#include "SymTab/Indexer.h"
     29#include "SymTab/Autogen.h"
    2930
    3031#include "ResolvExpr/Resolver.h"
    31 #include "ResolvExpr/TypeEnvironment.h"
    3232#include "ResolvExpr/typeops.h"
    33 #include "ResolvExpr/Unify.h"
    3433
    3534#include "Common/UniqueName.h"
    3635#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
    3745
    3846namespace GenPoly {
    3947        namespace {
    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;
    50                 };
    51 
    52                 /// Replace declarations of lvalue returns with appropriate pointers
    53                 class Pass2 : public Visitor {
    54                   public:
    55                         virtual void visit( FunctionType *funType );
    56                   private:
     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 );
     70                };
     71
     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 );
    5784                };
    5885
     
    6087                /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
    6188                /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
    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 );
     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;
    70107                };
    71108        } // namespace
    72109
     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;
     114        }
     115
    73116        void convertLvalue( std::list< Declaration* >& translationUnit ) {
    74                 Pass1 p1;
    75                 Pass2 p2;
    76                 GeneralizedLvalue genLval;
    77                 mutateAll( translationUnit, p1 );
    78                 acceptAll( translationUnit, p2 );
     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 );
    79130                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;
    80135        }
    81136
    82         Expression * generalizedLvalue( Expression * expr ) {
    83                 GeneralizedLvalue genLval;
    84                 return expr->acceptMutator( genLval );
    85         }
    86 
    87137        namespace {
    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();
    111                                 }
    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() ) );
    133                                 }
    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 ) ) );
     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 );
     150                                }
     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;
     209                                }
     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;
    158318                                } else {
    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 ) ) {
     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() ) ) {
    180363                                Expression * arg1 = commaExpr->get_arg1()->clone();
    181364                                Expression * arg2 = commaExpr->get_arg2()->clone();
    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 ) ) {
     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() ) ) {
    188371                                Expression * arg1 = condExpr->get_arg1()->clone();
    189372                                Expression * arg2 = condExpr->get_arg2()->clone();
    190373                                Expression * arg3 = condExpr->get_arg3()->clone();
    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 );
    205                         }
    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 ); } );
     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;
     379                        }
     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;
    217420                }
    218421        } // namespace
Note: See TracChangeset for help on using the changeset viewer.