Changeset cb43451


Ignore:
Timestamp:
Jul 21, 2017, 9:51:17 AM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
53a8e68
Parents:
17f22e78
Message:

Fix reference conversion cost for qualified references and add pass that removes redundant *&/&* pattern

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    r17f22e78 rcb43451  
    3939// need to be careful about polymorphic references... e.g. in *? (___operator_deref__A0_1_0_0__Fd0_Pd0_intrinsic___1)
    4040// the variable is automatically dereferenced and this causes errors dereferencing void*.
     41
     42#if 0
     43#define PRINT(x) x
     44#else
     45#define PRINT(x)
     46#endif
    4147
    4248namespace GenPoly {
     
    7985                        Expression * postmutate( AddressExpr * addressExpr );
    8086                };
     87
     88                /// Removes redundant &*/*& pattern that this pass can generate
     89                struct CollapseAddrDeref final {
     90                        Expression * postmutate( AddressExpr * addressExpr );
     91                        Expression * postmutate( ApplicationExpr * appExpr );
     92                };
    8193        } // namespace
    8294
     
    8799                PassVisitor<GeneralizedLvalue> genLval;
    88100                PassVisitor<FixIntrinsicArgs> fixer;
     101                PassVisitor<CollapseAddrDeref> collapser;
    89102                mutateAll( translationUnit, refCvt );
    90103                mutateAll( translationUnit, fixer );
    91104                mutateAll( translationUnit, elim );
    92105                mutateAll( translationUnit, genLval );
     106                mutateAll( translationUnit, collapser );
    93107        }
    94108
     
    139153                                delete arg->get_result();
    140154                                arg->set_result( ptrType );
    141                                 arg = mkDeref( new CastExpr( arg, arg->get_result()->clone() ) );
    142                         }
    143                 }
    144 
     155                                arg = mkDeref( arg );
     156                        }
     157                }
     158
     159                // xxx - might need to & every * (or every * that is an arg to non-intrinsic function??)
    145160                Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
    146161                        // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
     
    152167                                                Expression *& arg = std::get<0>( p );
    153168                                                DeclarationWithType * formal = std::get<1>( p );
    154                                                 std::cerr << "pair<0>: " << arg << std::endl;
    155                                                 std::cerr << "pair<1>: " << formal->get_type() << std::endl;
     169                                                PRINT(
     170                                                        std::cerr << "pair<0>: " << arg << std::endl;
     171                                                        std::cerr << "pair<1>: " << formal->get_type() << std::endl;
     172                                                )
    156173                                                if ( isIntrinsicReference( arg ) ) { // intrinsic functions that turn pointers into references
    157174                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
    158                                                         std::cerr << "skipping intrinsic reference" << std::endl;
     175                                                        PRINT( std::cerr << "skipping intrinsic reference" << std::endl; )
    159176                                                        continue;
    160177                                                } else {
     
    181198                                        // nothing to do if casting from reference to reference.
    182199                                        (void)otherRef;
    183                                         std::cerr << "convert reference to reference -- nop" << std::endl;
     200                                        PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; )
    184201                                        if ( isIntrinsicReference( castExpr->get_arg() ) ) {
    185202                                                Expression * callExpr = castExpr->get_arg();
    186                                                 std::cerr << "but arg is deref -- &" << std::endl;
    187                                                 std::cerr << callExpr << std::endl;
     203                                                PRINT(
     204                                                        std::cerr << "but arg is deref -- &" << std::endl;
     205                                                        std::cerr << callExpr << std::endl;
     206                                                )
    188207                                                // move environment out to new top-level
    189208                                                callExpr->set_env( castExpr->get_env() );
     
    194213                                        }
    195214                                        assertf( false, "non-intrinsic reference with cast of reference to reference not yet supported: ", toString( castExpr ) );
    196                                         std::cerr << castExpr << std::endl;
     215                                        PRINT( std::cerr << castExpr << std::endl; )
    197216                                        return castExpr;
    198217                                } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
     
    200219                                        // xxx - keep cast, but turn into pointer cast??
    201220                                        // xxx - memory
    202                                         std::cerr << "convert lvalue to reference -- &" << std::endl;
    203                                         std::cerr << castExpr->get_arg() << std::endl;
    204                                         Expression * ret = new AddressExpr( castExpr->get_arg() );
     221                                        PRINT(
     222                                                std::cerr << "convert lvalue to reference -- &" << std::endl;
     223                                                std::cerr << castExpr->get_arg() << std::endl;
     224                                        )
     225                                        AddressExpr * ret = new AddressExpr( castExpr->get_arg() );
     226                                        if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {
     227                                                // must keep cast if cast-to type is different from the actual type
     228                                                castExpr->set_arg( ret );
     229
     230                                                return castExpr;
     231                                        }
    205232                                        ret->set_env( castExpr->get_env() );
    206233                                        castExpr->set_env( nullptr );
     
    215242                                // conversion from reference to rvalue
    216243                                // should be easy, just need to move deref code up here?
    217                                 std::cerr << "convert reference to rvalue -- *" << std::endl;
     244                                PRINT( std::cerr << "convert reference to rvalue -- *" << std::endl; )
    218245                                if ( isIntrinsicReference( castExpr->get_arg() ) ) {
    219                                         std::cerr << "but arg is intrinsic reference -- nop" << std::endl;
     246                                        PRINT( std::cerr << "but arg is intrinsic reference -- nop" << std::endl; )
    220247                                        return castExpr;
    221248                                }
    222                                 std::cerr << "was = " << castExpr << std::endl;
     249                                PRINT( std::cerr << "was = " << castExpr << std::endl; )
    223250
    224251                                Expression * deref = mkDeref( castExpr->get_arg() );
     
    227254                                castExpr->set_env( nullptr );
    228255                                delete castExpr;
    229                                 std::cerr << "now: " << deref << std::endl;
     256                                PRINT( std::cerr << "now: " << deref << std::endl; )
    230257                                return deref;
    231258                        }
     
    255282                        return addrExpr;
    256283                }
     284
     285                Expression * CollapseAddrDeref::postmutate( AddressExpr * addressExpr ) {
     286                        Expression * arg = addressExpr->get_arg();
     287                        if ( isIntrinsicReference( arg ) ) {
     288                                std::string fname = InitTweak::getFunctionName( arg );
     289                                if ( fname == "*?" ) {
     290                                        Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
     291                                        Expression * ret = arg0;
     292                                        ret->set_env( addressExpr->get_env() );
     293                                        arg0 = nullptr;
     294                                        addressExpr->set_env( nullptr );
     295                                        delete addressExpr;
     296                                        return ret;
     297                                }
     298                        }
     299                        return addressExpr;
     300                }
     301
     302                Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) {
     303                        if ( isIntrinsicReference( appExpr ) ) {
     304                                std::string fname = InitTweak::getFunctionName( appExpr );
     305                                if ( fname == "*?" ) {
     306                                        Expression * arg = InitTweak::getCallArg( appExpr, 0 );
     307                                        // xxx - this isn't right, because it can remove casts that should be there...
     308                                        // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
     309                                        //      arg = castExpr->get_arg();
     310                                        // }
     311                                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) {
     312                                                Expression * ret = addrExpr->get_arg();
     313                                                ret->set_env( appExpr->get_env() );
     314                                                addrExpr->set_arg( nullptr );
     315                                                appExpr->set_env( nullptr );
     316                                                delete appExpr;
     317                                                return ret;
     318                                        }
     319                                }
     320                        }
     321                        return appExpr;
     322                }
    257323        } // namespace
    258324} // namespace GenPoly
  • src/ResolvExpr/ConversionCost.cc

    r17f22e78 rcb43451  
    248248        void ConversionCost::visit(PointerType *pointerType) {
    249249                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    250                         if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    251                                 cost = Cost::safe;
    252                         } else {  // xxx - this discards pointer qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
     250                        // std::cerr << pointerType << " ===> " << destAsPtr;
     251                        Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
     252                        Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
     253                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     254                                if ( tq1 == tq2 ) {
     255                                        // types are the same
     256                                        cost = Cost::zero;
     257                                } else {
     258                                        // types are the same, except otherPointer has more qualifiers
     259                                        // std::cerr << " :: compatible and good qualifiers" << std::endl;
     260                                        cost = Cost::safe;
     261                                }
     262                        } else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    253263                                int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
    254                                 if ( assignResult < 0 ) {
     264                                // std::cerr << " :: " << assignResult << std::endl;
     265                                if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
    255266                                        cost = Cost::safe;
    256267                                } else if ( assignResult > 0 ) {
    257268                                        cost = Cost::unsafe;
    258269                                } // if
     270                                // assignResult == 0 means Cost::Infinity
    259271                        } // if
    260272                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
     
    272284                // cv can be safely dropped because of 'implicit dereference' behavior.
    273285                refType->get_base()->accept( *this );
    274                 cost.incReference();
     286                if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) {
     287                        cost.incReference();  // prefer exact qualifiers
     288                } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) {
     289                        cost.incSafe(); // then gaining qualifiers
     290                } else {
     291                        cost.incUnsafe(); // lose qualifiers as last resort
     292                }
     293                // std::cerr << refType << " ==> " << dest << " " << cost << std::endl;
    275294        }
    276295
Note: See TracChangeset for help on using the changeset viewer.