Changeset 8a6cf7e for src/GenPoly


Ignore:
Timestamp:
Jul 26, 2017, 4:26:08 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:
2afec66
Parents:
d335627
Message:

Fix various reference features.

  • Eliminate multiple address-ofs resulting from &(T&) [address-of reference-cast].
  • Keep rvalue cast if reference base type is incompatible with rvalue type.
  • Keep pointer qualifiers when eliminating reference types.
  • Add VariableExpr::functionPointer helper function to create variable expressions with function pointer type.
  • Change ConstructorExpr? translation so that it temporarily generates a 'fake' assignment operator rather than use UntypedExpr?, so that the correct transformations occur in the Lvalue pass. This is a hack that can be fixed once PassVisitor? properly supports Indexer.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Lvalue.cc

    rd335627 r8a6cf7e  
    6666                struct ReferenceConversions final {
    6767                        Expression * postmutate( CastExpr * castExpr );
     68                        Expression * postmutate( AddressExpr * addrExpr );
    6869                };
    6970
     
    102103                mutateAll( translationUnit, refCvt );
    103104                mutateAll( translationUnit, fixer );
    104                 mutateAll( translationUnit, elim );
    105105                mutateAll( translationUnit, genLval );
    106106                mutateAll( translationUnit, collapser );
     107                mutateAll( translationUnit, elim );  // last because other passes need reference types to work
    107108        }
    108109
    109110        namespace {
    110                 Type* isLvalueRet( FunctionType *function ) {
    111                         if ( function->get_returnVals().empty() ) return 0;
    112                         Type *ty = function->get_returnVals().front()->get_type();
    113                         return dynamic_cast< ReferenceType * >( ty ) ;
    114                 }
    115 
    116                 bool isIntrinsicApp( ApplicationExpr *appExpr ) {
    117                         if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) {
    118                                 return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic;
    119                         } else {
    120                                 return false;
    121                         } // if
    122                 }
    123 
    124                 bool isDeref( Expression * expr ) {
     111                // true for intrinsic function calls that return a reference
     112                bool isIntrinsicReference( Expression * expr ) {
    125113                        if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    126                                 return InitTweak::getFunctionName( untyped ) == "*?";
     114                                std::string fname = InitTweak::getFunctionName( untyped );
     115                                // known intrinsic-reference prelude functions
     116                                return fname == "*?" || fname == "?[?]";
    127117                        } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    128118                                if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    129                                         return func->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getFunctionName( appExpr ) == "*?";
    130                                 }
    131                         }
    132                         return false;
    133                 }
    134 
    135                 bool isIntrinsicReference( Expression * expr ) {
    136                         if ( isDeref( expr ) ) return true;
    137                         else if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
    138                                 return InitTweak::getFunctionName( untyped ) == "?[?]";
    139                         } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    140                                 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
    141                                         return func->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getFunctionName( appExpr ) == "?[?]";
     119                                        // use type of return variable rather than expr result type, since it may have been changed to a pointer type
     120                                        FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
     121                                        Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type();
     122                                        return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
    142123                                }
    143124                        }
     
    186167                }
    187168
     169                Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
     170                        // Inner expression may have been lvalue to reference conversion, which becomes an address expression.
     171                        // In this case, remove the outer address expression and return the argument.
     172                        // TODO: It's possible that this might catch too much and require a more sophisticated check.
     173                        if ( dynamic_cast<AddressExpr*>( addrExpr->get_arg() ) ) {
     174                                Expression * arg = addrExpr->get_arg();
     175                                arg->set_env( addrExpr->get_env() );
     176                                addrExpr->set_arg( nullptr );
     177                                addrExpr->set_env( nullptr );
     178                                delete addrExpr;
     179                                return arg;
     180                        }
     181                        return addrExpr;
     182                }
     183
    188184                Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
    189185                        // xxx - is it possible to convert directly between reference types with a different base? E.g.,
     
    244240                                (void)refType;
    245241                                // conversion from reference to rvalue
    246                                 PRINT( std::cerr << "convert reference to rvalue -- *" << std::endl; )
    247                                 PRINT( std::cerr << "was = " << castExpr << std::endl; )
     242                                PRINT(
     243                                        std::cerr << "convert reference to rvalue -- *" << std::endl;
     244                                        std::cerr << "was = " << castExpr << std::endl;
     245                                )
    248246                                Expression * ret = castExpr->get_arg();
     247                                TypeSubstitution * env = castExpr->get_env();
     248                                castExpr->set_env( nullptr );
    249249                                if ( ! isIntrinsicReference( ret ) ) {
    250250                                        // dereference if not already dereferenced
    251251                                        ret = mkDeref( ret );
    252252                                }
    253                                 ret->set_env( castExpr->get_env() );
    254                                 castExpr->set_arg( nullptr );
    255                                 castExpr->set_env( nullptr );
    256                                 delete castExpr;
     253                                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {
     254                                        // can remove cast if types are compatible
     255                                        castExpr->set_arg( nullptr );
     256                                        delete castExpr;
     257                                } else {
     258                                        // must keep cast if types are different
     259                                        castExpr->set_arg( ret );
     260                                        ret = castExpr;
     261                                }
     262                                ret->set_env( env );
    257263                                PRINT( std::cerr << "now: " << ret << std::endl; )
    258264                                return ret;
     
    263269                Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
    264270                        Type * base = refType->get_base();
     271                        Type::Qualifiers qualifiers = refType->get_qualifiers();
    265272                        refType->set_base( nullptr );
    266273                        delete refType;
    267                         return new PointerType( Type::Qualifiers(), base );
     274                        return new PointerType( qualifiers, base );
    268275                }
    269276
Note: See TracChangeset for help on using the changeset viewer.