Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    r08fc48f r9aaac6e9  
    1717#include <string>                        // for string
    1818
     19#include "Common/PassVisitor.h"
    1920#include "Common/SemanticError.h"        // for SemanticError
    2021#include "GenPoly.h"                     // for isPolyType
    2122#include "Lvalue.h"
     23
    2224#include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
    2325#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2426#include "ResolvExpr/Unify.h"            // for unify
     27#include "ResolvExpr/typeops.h"
     28#include "SymTab/Autogen.h"
    2529#include "SymTab/Indexer.h"              // for Indexer
    2630#include "SynTree/Declaration.h"         // for Declaration, FunctionDecl
     
    3135#include "SynTree/Visitor.h"             // for Visitor, acceptAll
    3236
     37#if 0
     38#define PRINT(x) x
     39#else
     40#define PRINT(x)
     41#endif
     42
    3343namespace GenPoly {
    3444        namespace {
    35                 /// Replace uses of lvalue returns with appropriate pointers
    36                 class Pass1 : public Mutator {
    37                   public:
    38                         Pass1();
    39 
    40                         virtual Expression *mutate( ApplicationExpr *appExpr );
    41                         virtual Statement *mutate( ReturnStmt *appExpr );
    42                         virtual DeclarationWithType *mutate( FunctionDecl *funDecl );
    43                   private:
    44                         DeclarationWithType* retval;
    45                 };
    46 
    47                 /// Replace declarations of lvalue returns with appropriate pointers
    48                 class Pass2 : public Visitor {
    49                   public:
    50                         virtual void visit( FunctionType *funType );
    51                   private:
     45                // TODO: fold this into the general createDeref function??
     46                Expression * mkDeref( Expression * arg ) {
     47                        if ( SymTab::dereferenceOperator ) {
     48                                VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
     49                                deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) );
     50                                Type * base = InitTweak::getPointerBase( arg->get_result() );
     51                                assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() );
     52                                ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
     53                                delete ret->get_result();
     54                                ret->set_result( base->clone() );
     55                                ret->get_result()->set_lvalue( true );
     56                                return ret;
     57                        } else {
     58                                return UntypedExpr::createDeref( arg );
     59                        }
     60                }
     61
     62                struct ReferenceConversions final {
     63                        Expression * postmutate( CastExpr * castExpr );
     64                        Expression * postmutate( AddressExpr * addrExpr );
     65                };
     66
     67                /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
     68                struct FixIntrinsicArgs final {
     69                        Expression * postmutate( ApplicationExpr * appExpr );
     70                };
     71
     72                struct FixIntrinsicResult final : public WithGuards {
     73                        Expression * postmutate( ApplicationExpr * appExpr );
     74                        void premutate( FunctionDecl * funcDecl );
     75                        bool inIntrinsic = false;
     76                };
     77
     78                /// Replace reference types with pointer types
     79                struct ReferenceTypeElimination final {
     80                        Type * postmutate( ReferenceType * refType );
    5281                };
    5382
     
    5584                /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
    5685                /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
    57                 class GeneralizedLvalue : public Mutator {
    58                         typedef Mutator Parent;
    59 
    60                         virtual Expression * mutate( MemberExpr * memExpr );
    61                         virtual Expression * mutate( AddressExpr * addressExpr );
     86                struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
     87                        Expression * postmutate( AddressExpr * addressExpr );
     88                        Expression * postmutate( MemberExpr * memExpr );
    6289
    6390                        template<typename Func>
    6491                        Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr );
    6592                };
     93
     94                /// Removes redundant &*/*& pattern that this pass can generate
     95                struct CollapseAddrDeref final {
     96                        Expression * postmutate( AddressExpr * addressExpr );
     97                        Expression * postmutate( ApplicationExpr * appExpr );
     98                };
     99
     100                struct AddrRef final : public WithGuards {
     101                        void premutate( AddressExpr * addrExpr );
     102                        Expression * postmutate( AddressExpr * addrExpr );
     103                        void premutate( Expression * expr );
     104
     105                        bool first = true;
     106                        bool current = false;
     107                        int refDepth = 0;
     108                };
    66109        } // namespace
    67110
     111        static bool referencesEliminated = false;
     112        // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type.
     113        bool referencesPermissable() {
     114                return ! referencesEliminated;
     115        }
     116
    68117        void convertLvalue( std::list< Declaration* >& translationUnit ) {
    69                 Pass1 p1;
    70                 Pass2 p2;
    71                 GeneralizedLvalue genLval;
    72                 mutateAll( translationUnit, p1 );
    73                 acceptAll( translationUnit, p2 );
     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 );
    74130                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;
    75135        }
    76136
    77137        Expression * generalizedLvalue( Expression * expr ) {
    78                 GeneralizedLvalue genLval;
     138                PassVisitor<GeneralizedLvalue> genLval;
    79139                return expr->acceptMutator( genLval );
    80140        }
    81141
    82142        namespace {
    83                 Type* isLvalueRet( FunctionType *function ) {
    84                         if ( function->get_returnVals().empty() ) return 0;
    85                         Type *ty = function->get_returnVals().front()->get_type();
    86                         return ty->get_lvalue() ? ty : 0;
    87                 }
    88 
    89                 bool isIntrinsicApp( ApplicationExpr *appExpr ) {
    90                         if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) {
    91                                 return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic;
    92                         } else {
    93                                 return false;
    94                         } // if
    95                 }
    96 
    97                 Pass1::Pass1() {
    98                 }
    99 
    100                 DeclarationWithType * Pass1::mutate( FunctionDecl *funcDecl ) {
    101                         if ( funcDecl->get_statements() ) {
    102                                 DeclarationWithType* oldRetval = retval;
    103                                 retval = 0;
    104                                 if ( ! LinkageSpec::isBuiltin( funcDecl->get_linkage() ) && isLvalueRet( funcDecl->get_functionType() ) ) {
    105                                         retval = funcDecl->get_functionType()->get_returnVals().front();
    106                                 }
    107                                 // fix expressions and return statements in this function
    108                                 funcDecl->set_statements( funcDecl->get_statements()->acceptMutator( *this ) );
    109                                 retval = oldRetval;
    110                         } // if
    111                         return funcDecl;
    112                 }
    113 
    114                 Expression * Pass1::mutate( ApplicationExpr *appExpr ) {
    115                         appExpr->get_function()->acceptMutator( *this );
    116                         mutateAll( appExpr->get_args(), *this );
    117 
    118                         PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    119                         FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    120 
    121                         Type *funType = isLvalueRet( function );
    122                         if ( funType && ! isIntrinsicApp( appExpr ) ) {
    123                                 Expression *expr = appExpr;
    124                                 Type *appType = appExpr->get_result();
    125                                 if ( isPolyType( funType ) && ! isPolyType( appType ) ) {
    126                                         // make sure cast for polymorphic type is inside dereference
    127                                         expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) );
    128                                 }
    129                                 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    130                                 deref->set_result( appType->clone() );
    131                                 appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) );
    132                                 deref->get_args().push_back( expr );
    133                                 return deref;
    134                         } else {
    135                                 return appExpr;
    136                         } // if
    137                 }
    138 
    139                 Statement * Pass1::mutate(ReturnStmt *retStmt) {
    140                         if ( retval && retStmt->get_expr() ) {
    141                                 if ( retStmt->get_expr()->get_result()->get_lvalue() ) {
    142                                         // ***** Code Removal ***** because casts may be stripped already
    143 
    144                                         // strip casts because not allowed to take address of cast
    145                                         // while ( CastExpr *castExpr = dynamic_cast< CastExpr* >( retStmt->get_expr() ) ) {
    146                                         //      retStmt->set_expr( castExpr->get_arg() );
    147                                         //      retStmt->get_expr()->set_env( castExpr->get_env() );
    148                                         //      castExpr->set_env( 0 );
    149                                         //      castExpr->set_arg( 0 );
    150                                         //      delete castExpr;
    151                                         // } // while
    152                                         retStmt->set_expr( new AddressExpr( retStmt->get_expr()->acceptMutator( *this ) ) );
     143                // true for intrinsic function calls that return a reference
     144                bool isIntrinsicReference( Expression * expr ) {
     145                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
     146                                std::string fname = InitTweak::getFunctionName( untyped );
     147                                // known intrinsic-reference prelude functions
     148                                return fname == "*?" || fname == "?[?]";
     149                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
     150                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
     151                                        // use type of return variable rather than expr result type, since it may have been changed to a pointer type
     152                                        FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
     153                                        Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type();
     154                                        return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
     155                                }
     156                        }
     157                        return false;
     158                }
     159
     160                Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) {
     161                        if ( isIntrinsicReference( appExpr ) ) {
     162                                // eliminate reference types from intrinsic applications - now they return lvalues
     163                                Type * result = appExpr->get_result();
     164                                appExpr->set_result( result->stripReferences()->clone() );
     165                                appExpr->get_result()->set_lvalue( true );
     166                                if ( ! inIntrinsic ) {
     167                                        // when not in an intrinsic function, add a cast to
     168                                        // don't add cast when in an intrinsic function, since they already have the cast
     169                                        Expression * ret = new CastExpr( appExpr, result );
     170                                        ret->set_env( appExpr->get_env() );
     171                                        appExpr->set_env( nullptr );
     172                                        return ret;
     173                                }
     174                                delete result;
     175                        }
     176                        return appExpr;
     177                }
     178
     179                void FixIntrinsicResult::premutate( FunctionDecl * funcDecl ) {
     180                        GuardValue( inIntrinsic );
     181                        inIntrinsic =  funcDecl->linkage == LinkageSpec::Intrinsic;
     182                }
     183
     184                Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
     185                        // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
     186                        if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
     187                                FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
     188                                assertf( ftype, "Function declaration does not have function type." );
     189                                // can be of differing lengths only when function is variadic
     190                                assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
     191
     192
     193                                unsigned int i = 0;
     194                                const unsigned int end = ftype->get_parameters().size();
     195                                for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
     196                                        if (i == end) break;
     197                                        Expression *& arg = std::get<0>( p );
     198                                        Type * formal = std::get<1>( p )->get_type();
     199                                        PRINT(
     200                                                std::cerr << "pair<0>: " << arg << std::endl;
     201                                                std::cerr << "pair<1>: " << formal << std::endl;
     202                                        )
     203                                        if ( dynamic_cast<ReferenceType*>( formal ) ) {
     204                                                if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if
     205                                                        if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
     206                                                                // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
     207                                                                PRINT(
     208                                                                        std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
     209                                                                )
     210                                                                arg = new AddressExpr( arg );
     211                                                        }
     212                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
     213                                                        // std::cerr << "===adding deref to arg" << std::endl;
     214                                                        // if the parameter is a reference, add a dereference to the reference-typed argument.
     215                                                        Type * baseType = InitTweak::getPointerBase( arg->get_result() );
     216                                                        assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() );
     217                                                        PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
     218                                                        delete arg->get_result();
     219                                                        arg->set_result( ptrType );
     220                                                        arg = mkDeref( arg );
     221                                                }
     222                                        }
     223                                        ++i;
     224                                }
     225                        }
     226                        return appExpr;
     227                }
     228
     229                // idea: &&&E: get outer &, inner &
     230                // at inner &, record depth D of reference type
     231                // at outer &, add D derefs.
     232                void AddrRef::premutate( Expression * ) {
     233                        GuardValue( current );
     234                        GuardValue( first );
     235                        current = false;
     236                        first = true;
     237                }
     238
     239                void AddrRef::premutate( AddressExpr * ) {
     240                        GuardValue( current );
     241                        GuardValue( first );
     242                        current = first;
     243                        first = false;
     244                        if ( current ) {
     245                                GuardValue( refDepth );
     246                                refDepth = 0;
     247                        }
     248                }
     249
     250                Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
     251                        if ( refDepth == 0 ) {
     252                                if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) {
     253                                        // try to avoid ?[?]
     254                                        refDepth = addrExpr->get_arg()->get_result()->referenceDepth();
     255                                }
     256                        }
     257                        if ( current ) {
     258                                Expression * ret = addrExpr;
     259                                while ( refDepth ) {
     260                                        ret = mkDeref( ret );
     261                                        refDepth--;
     262                                }
     263                                return ret;
     264                        }
     265                        return addrExpr;
     266                }
     267
     268                Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
     269                        // Inner expression may have been lvalue to reference conversion, which becomes an address expression.
     270                        // In this case, remove the outer address expression and return the argument.
     271                        // TODO: It's possible that this might catch too much and require a more sophisticated check.
     272                        return addrExpr;
     273                }
     274
     275                Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
     276                        // xxx - is it possible to convert directly between reference types with a different base? E.g.,
     277                        //   int x;
     278                        //   (double&)x;
     279                        // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant
     280                        // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct
     281                        // pointer casts in the right places.
     282
     283                        // conversion to reference type
     284                        if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) {
     285                                (void)refType;
     286                                if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     287                                        // nothing to do if casting from reference to reference.
     288                                        (void)otherRef;
     289                                        PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; )
     290                                        if ( isIntrinsicReference( castExpr->get_arg() ) ) {
     291                                                Expression * callExpr = castExpr->get_arg();
     292                                                PRINT(
     293                                                        std::cerr << "but arg is deref -- &" << std::endl;
     294                                                        std::cerr << callExpr << std::endl;
     295                                                )
     296                                                callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts
     297                                                delete callExpr->get_result();
     298                                                callExpr->set_result( refType->clone() );
     299                                                // move environment out to new top-level
     300                                                callExpr->set_env( castExpr->get_env() );
     301                                                castExpr->set_arg( nullptr );
     302                                                castExpr->set_env( nullptr );
     303                                                delete castExpr;
     304                                                return callExpr;
     305                                        }
     306                                        int depth1 = refType->referenceDepth();
     307                                        int depth2 = otherRef->referenceDepth();
     308                                        int diff = depth1-depth2;
     309                                        if ( diff == 0 ) {
     310                                                assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
     311                                                PRINT( std::cerr << castExpr << std::endl; )
     312                                                return castExpr;
     313                                        } else if ( diff < 0 ) {
     314                                                Expression * ret = castExpr->get_arg();
     315                                                for ( int i = 0; i < diff; ++i ) {
     316                                                        ret = mkDeref( ret );
     317                                                }
     318                                                ret->set_env( castExpr->get_env() );
     319                                                delete ret->get_result();
     320                                                ret->set_result( castExpr->get_result() );
     321                                                castExpr->set_env( nullptr );
     322                                                castExpr->set_arg( nullptr );
     323                                                castExpr->set_result( nullptr );
     324                                                delete castExpr;
     325                                                return ret;
     326                                        } else if ( diff > 0 ) {
     327                                                Expression * ret = castExpr->get_arg();
     328                                                for ( int i = 0; i < diff; ++i ) {
     329                                                        ret = new AddressExpr( ret );
     330                                                }
     331                                                ret->set_env( castExpr->get_env() );
     332                                                delete ret->get_result();
     333                                                ret->set_result( castExpr->get_result() );
     334                                                castExpr->set_env( nullptr );
     335                                                castExpr->set_arg( nullptr );
     336                                                castExpr->set_result( nullptr );
     337                                                delete castExpr;
     338                                                return ret;
     339                                        }
     340
     341                                        assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
     342                                        PRINT( std::cerr << castExpr << std::endl; )
     343                                        return castExpr;
     344                                } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
     345                                        // conversion from lvalue to reference
     346                                        // xxx - keep cast, but turn into pointer cast??
     347                                        // xxx - memory
     348                                        PRINT(
     349                                                std::cerr << "convert lvalue to reference -- &" << std::endl;
     350                                                std::cerr << castExpr->get_arg() << std::endl;
     351                                        )
     352                                        AddressExpr * ret = new AddressExpr( castExpr->get_arg() );
     353                                        if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {
     354                                                // must keep cast if cast-to type is different from the actual type
     355                                                castExpr->set_arg( ret );
     356                                                return castExpr;
     357                                        }
     358                                        ret->set_env( castExpr->get_env() );
     359                                        delete ret->get_result();
     360                                        ret->set_result( castExpr->get_result() );
     361                                        castExpr->set_env( nullptr );
     362                                        castExpr->set_arg( nullptr );
     363                                        castExpr->set_result( nullptr );
     364                                        delete castExpr;
     365                                        return ret;
    153366                                } else {
    154                                         throw SemanticError( "Attempt to return non-lvalue from an lvalue-qualified function" );
    155                                 } // if
    156                         } // if
    157                         return retStmt;
    158                 }
    159 
    160                 void Pass2::visit( FunctionType *funType ) {
    161                         std::string typeName;
    162                         if ( isLvalueRet( funType ) ) {
    163                                 DeclarationWithType *retParm = funType->get_returnVals().front();
    164 
    165                                 // make a new parameter that is a pointer to the type of the old return value
    166                                 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) );
    167                         } // if
    168 
    169                         Visitor::visit( funType );
     367                                        // rvalue to reference conversion -- introduce temporary
     368                                }
     369                                assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
     370                        } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     371                                (void)refType;
     372                                // conversion from reference to rvalue
     373                                PRINT(
     374                                        std::cerr << "convert reference to rvalue -- *" << std::endl;
     375                                        std::cerr << "was = " << castExpr << std::endl;
     376                                )
     377                                Expression * ret = castExpr->get_arg();
     378                                TypeSubstitution * env = castExpr->get_env();
     379                                castExpr->set_env( nullptr );
     380                                if ( ! isIntrinsicReference( ret ) ) {
     381                                        // dereference if not already dereferenced
     382                                        ret = mkDeref( ret );
     383                                }
     384                                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {
     385                                        // can remove cast if types are compatible, changing expression type to value type
     386                                        ret->set_result( castExpr->get_result()->clone() );
     387                                        castExpr->set_arg( nullptr );
     388                                        delete castExpr;
     389                                } else {
     390                                        // must keep cast if types are different
     391                                        castExpr->set_arg( ret );
     392                                        ret = castExpr;
     393                                }
     394                                ret->set_env( env );
     395                                PRINT( std::cerr << "now: " << ret << std::endl; )
     396                                return ret;
     397                        }
     398                        return castExpr;
     399                }
     400
     401                Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
     402                        Type * base = refType->get_base();
     403                        Type::Qualifiers qualifiers = refType->get_qualifiers();
     404                        refType->set_base( nullptr );
     405                        delete refType;
     406                        return new PointerType( qualifiers, base );
    170407                }
    171408
     
    175412                                Expression * arg1 = commaExpr->get_arg1()->clone();
    176413                                Expression * arg2 = commaExpr->get_arg2()->clone();
    177                                 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 ) );
     414                                Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) );
    178415                                ret->set_env( expr->get_env() );
    179416                                expr->set_env( nullptr );
    180417                                delete expr;
    181                                 return ret->acceptMutator( *this );
     418                                return ret;
    182419                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) {
    183420                                Expression * arg1 = condExpr->get_arg1()->clone();
    184421                                Expression * arg2 = condExpr->get_arg2()->clone();
    185422                                Expression * arg3 = condExpr->get_arg3()->clone();
    186                                 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 ), mkExpr( arg3 ) );
     423                                ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) );
    187424                                ret->set_env( expr->get_env() );
    188425                                expr->set_env( nullptr );
     
    197434                                unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );
    198435                                ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() );
    199                                 return ret->acceptMutator( *this );
     436                                return ret;
    200437                        }
    201438                        return expr;
    202439                }
    203440
    204                 Expression * GeneralizedLvalue::mutate( MemberExpr * memExpr ) {
    205                         Parent::mutate( memExpr );
     441                Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) {
    206442                        return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } );
    207443                }
    208444
    209                 Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) {
    210                         addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) );
     445                Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
    211446                        return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } );
     447                }
     448
     449                Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) {
     450                        Expression * arg = addrExpr->get_arg();
     451                        if ( isIntrinsicReference( arg ) ) {
     452                                std::string fname = InitTweak::getFunctionName( arg );
     453                                if ( fname == "*?" ) {
     454                                        Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
     455                                        Expression * ret = arg0;
     456                                        ret->set_env( addrExpr->get_env() );
     457                                        arg0 = nullptr;
     458                                        addrExpr->set_env( nullptr );
     459                                        delete addrExpr;
     460                                        return ret;
     461                                }
     462                        }
     463                        return addrExpr;
     464                }
     465
     466                Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) {
     467                        if ( isIntrinsicReference( appExpr ) ) {
     468                                std::string fname = InitTweak::getFunctionName( appExpr );
     469                                if ( fname == "*?" ) {
     470                                        Expression * arg = InitTweak::getCallArg( appExpr, 0 );
     471                                        // xxx - this isn't right, because it can remove casts that should be there...
     472                                        // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
     473                                        //      arg = castExpr->get_arg();
     474                                        // }
     475                                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) {
     476                                                Expression * ret = addrExpr->get_arg();
     477                                                ret->set_env( appExpr->get_env() );
     478                                                addrExpr->set_arg( nullptr );
     479                                                appExpr->set_env( nullptr );
     480                                                delete appExpr;
     481                                                return ret;
     482                                        }
     483                                }
     484                        }
     485                        return appExpr;
    212486                }
    213487        } // namespace
Note: See TracChangeset for help on using the changeset viewer.