Changeset 9a34b5a


Ignore:
Timestamp:
Jul 18, 2017, 5:02:20 PM (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:
17f22e78
Parents:
d1685588
git-author:
Rob Schluntz <rschlunt@…> (07/18/17 16:59:34)
git-committer:
Rob Schluntz <rschlunt@…> (07/18/17 17:02:20)
Message:

Remove redundant casts from reference translation and generate dereference ApplicationExpr? instead of UntypedExpr?

Generating ApplicationExpr? in this context is necessary so that the Box pass correctly removes dereferences from polymorphic code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    rd1685588 r9a34b5a  
    2727#include "SynTree/Mutator.h"
    2828#include "SymTab/Indexer.h"
     29#include "SymTab/Autogen.h"
    2930#include "ResolvExpr/Resolver.h"
    3031#include "ResolvExpr/typeops.h"
     
    4142namespace GenPoly {
    4243        namespace {
     44                // TODO: fold this into the general createDeref function??
     45                Expression * mkDeref( Expression * arg ) {
     46                        if ( SymTab::dereferenceOperator ) {
     47                                VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
     48                                deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) );
     49                                Type * base = InitTweak::getPointerBase( arg->get_result() );
     50                                assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() );
     51                                ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
     52                                delete ret->get_result();
     53                                ret->set_result( new ReferenceType( Type::Qualifiers(), base->clone() ) );
     54                                return ret;
     55                        } else {
     56                                return UntypedExpr::createDeref( arg );
     57                        }
     58                }
     59
    4360                struct ReferenceConversions final {
    4461                        Expression * postmutate( CastExpr * castExpr );
     
    115132
    116133                void fixArg( Expression *& arg, Type * formal ) {
    117                         // if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
    118                                 if ( dynamic_cast<ReferenceType*>( formal ) ) { // xxx - but might be deref, in which case result isn't REALLY a reference, at least not in the sense that we need to add another deref...
    119                                         // doesn't work, for some reason left arg is skipped in assign
    120                                         ReferenceType * refType = safe_dynamic_cast< ReferenceType * >( arg->get_result() ) ;
    121                                         std::cerr << "appexpr arg is non-deref/index intrinsic call" << std::endl;
    122                                         std::cerr << arg << std::endl;
    123                                         PointerType * ptrType = new PointerType( Type::Qualifiers(), refType->get_base()->clone() );
    124                                         delete refType;
    125                                         arg->set_result( ptrType );
    126                                         arg = UntypedExpr::createDeref( arg );
    127                                 }
    128 
    129                         // }
     134                        if ( dynamic_cast<ReferenceType*>( formal ) ) {
     135                                // if the parameter is a reference, add a dereference to the reference-typed argument.
     136                                Type * baseType = InitTweak::getPointerBase( arg->get_result() );
     137                                assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ) );
     138                                PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
     139                                delete arg->get_result();
     140                                arg->set_result( ptrType );
     141                                arg = mkDeref( new CastExpr( arg, arg->get_result()->clone() ) );
     142                        }
    130143                }
    131144
    132145                Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
     146                        // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
    133147                        if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
    134                                 if ( function->get_linkage() == LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
     148                                if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
    135149                                        FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
    136150                                        assertf( ftype, "Function declaration does not have function type." );
     
    140154                                                std::cerr << "pair<0>: " << arg << std::endl;
    141155                                                std::cerr << "pair<1>: " << formal->get_type() << std::endl;
    142                                                 if ( isIntrinsicReference( arg ) ) {
     156                                                if ( isIntrinsicReference( arg ) ) { // intrinsic functions that turn pointers into references
     157                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
    143158                                                        std::cerr << "skipping intrinsic reference" << std::endl;
    144159                                                        continue;
     
    153168
    154169                Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
     170                        // xxx - is it possible to convert directly between reference types with a different base? E.g.,
     171                        //   int x;
     172                        //   (double&)x;
     173                        // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant
     174                        // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct
     175                        // pointer casts in the right places.
     176
    155177                        // conversion to reference type
    156178                        if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) {
     
    162184                                        if ( isIntrinsicReference( castExpr->get_arg() ) ) {
    163185                                                Expression * callExpr = castExpr->get_arg();
    164                                                 Expression ** arg = nullptr;
    165                                                 Expression *& arg0 = InitTweak::getCallArg( callExpr, 0 );
    166                                                 if ( dynamic_cast<PointerType *>( arg0->get_result() ) ) {
    167                                                         arg = &arg0;
    168                                                 } else {
    169                                                         arg = &InitTweak::getCallArg( callExpr, 1 );
    170                                                 }
    171 
    172                                                 castExpr->set_arg( *arg );
    173                                                 *arg = castExpr;
    174186                                                std::cerr << "but arg is deref -- &" << std::endl;
    175187                                                std::cerr << callExpr << std::endl;
    176                                                 // castExpr->set_arg( new AddressExpr( castExpr->get_arg() ) );
    177 
    178188                                                // move environment out to new top-level
    179189                                                callExpr->set_env( castExpr->get_env() );
     190                                                castExpr->set_arg( nullptr );
    180191                                                castExpr->set_env( nullptr );
     192                                                delete castExpr;
    181193                                                return callExpr;
    182194                                        }
     195                                        assertf( false, "non-intrinsic reference with cast of reference to reference not yet supported: ", toString( castExpr ) );
    183196                                        std::cerr << castExpr << std::endl;
    184197                                        return castExpr;
     
    189202                                        std::cerr << "convert lvalue to reference -- &" << std::endl;
    190203                                        std::cerr << castExpr->get_arg() << std::endl;
    191                                         castExpr->set_arg( new AddressExpr( castExpr->get_arg() ) );
    192                                         // return new AddressExpr( castExpr->get_arg() );
    193                                         return castExpr;
     204                                        Expression * ret = new AddressExpr( castExpr->get_arg() );
     205                                        ret->set_env( castExpr->get_env() );
     206                                        castExpr->set_env( nullptr );
     207                                        castExpr->set_arg( nullptr );
     208                                        delete castExpr;
     209                                        return ret;
    194210                                } else {
    195211                                        // rvalue to reference conversion -- introduce temporary
     
    197213                                assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
    198214                        } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
     215                                // conversion from reference to rvalue
    199216                                // should be easy, just need to move deref code up here?
    200217                                std::cerr << "convert reference to rvalue -- *" << std::endl;
     
    203220                                        return castExpr;
    204221                                }
    205                                 std::cerr << castExpr << std::endl;
    206 
    207                                 PointerType * ptrType = new PointerType( refType->get_qualifiers(), refType->get_base()->clone() );
    208                                 delete castExpr->get_result();
    209                                 castExpr->set_result( ptrType );
    210                                 Expression * deref = UntypedExpr::createDeref( castExpr );
     222                                std::cerr << "was = " << castExpr << std::endl;
     223
     224                                Expression * deref = mkDeref( castExpr->get_arg() );
    211225                                deref->set_env( castExpr->get_env() );
     226                                castExpr->set_arg( nullptr );
    212227                                castExpr->set_env( nullptr );
     228                                delete castExpr;
     229                                std::cerr << "now: " << deref << std::endl;
    213230                                return deref;
    214                                 // assertf( false, "Conversions from reference types are not currently supported." );
    215231                        }
    216232                        return castExpr;
Note: See TracChangeset for help on using the changeset viewer.