Changeset 8a6cf7e


Ignore:
Timestamp:
Jul 26, 2017, 4:26:08 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, 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.
Location:
src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    rd335627 r8a6cf7e  
    661661                extension( commaExpr );
    662662                output << "(";
     663                if ( genC ) {
     664                        // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
     665                        commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
     666                }
    663667                commaExpr->get_arg1()->accept( *this );
    664668                output << " , ";
     
    724728                for ( Statement * stmt : stmts ) {
    725729                        output << lineDirective( stmt ) << indent;
    726             output << printLabels( stmt->get_labels() );
     730                        output << printLabels( stmt->get_labels() );
    727731                        if ( i+1 == numStmts ) {
    728732                                // last statement in a statement expression needs to be handled specially -
     
    769773        void CodeGenerator::visit( ExprStmt * exprStmt ) {
    770774                assert( exprStmt );
    771                 Expression * expr = exprStmt->get_expr();
    772775                if ( genC ) {
    773776                        // cast the top-level expression to void to reduce gcc warnings.
    774                         expr = new CastExpr( expr );
    775                 }
    776                 expr->accept( *this );
     777                        exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
     778                }
     779                exprStmt->get_expr()->accept( *this );
    777780                output << ";";
    778781        }
  • 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
  • src/InitTweak/FixInit.cc

    rd335627 r8a6cf7e  
    11821182                        ctorExpr->set_callExpr( nullptr );
    11831183                        ctorExpr->set_env( nullptr );
     1184                        delete ctorExpr;
    11841185
    11851186                        Expression *& firstArg = callExpr->get_args().front();
    1186                         UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) );
    1187                         assign->get_args().push_back( new VariableExpr( tmp ) );
    1188                         assign->get_args().push_back( firstArg );
    1189                         assign->set_result( ctorExpr->get_result()->clone() );
    1190                         firstArg = assign;
    1191 
    1192                         CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) );
     1187
     1188                        // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away.
     1189
     1190                        // generate the type of assignment operator using the type of tmp minus any reference types
     1191                        Type * type = tmp->get_type()->stripReferences();
     1192                        FunctionType * ftype = SymTab::genAssignType( type );
     1193
     1194                        // generate fake assignment decl and call it using &tmp and &firstArg
     1195                        // since tmp is guaranteed to be a reference and we want to assign pointers
     1196                        FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
     1197                        ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
     1198                        assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
     1199                        Expression * addrArg = new AddressExpr( firstArg );
     1200                        // if firstArg has type T&&, then &firstArg has type T*&.
     1201                        // Cast away the reference to a value type so that the argument
     1202                        // matches the assignment's parameter types
     1203                        if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
     1204                                addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
     1205                        }
     1206                        assign->get_args().push_back( addrArg );
     1207                        firstArg = new VariableExpr( tmp );
     1208
     1209                        // for constructor expr:
     1210                        //   T x;
     1211                        //   x{};
     1212                        // results in:
     1213                        //   T x;
     1214                        //   T & tmp;
     1215                        //   &tmp = &x, ?{}(tmp), tmp
     1216                        CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    11931217                        commaExpr->set_env( env );
    1194                         delete ctorExpr;
    11951218                        return commaExpr;
    11961219                }
  • src/SymTab/Autogen.h

    rd335627 r8a6cf7e  
    3838        /// Useful for creating dereference ApplicationExprs without a full resolver pass.
    3939        extern FunctionDecl * dereferenceOperator;
     40
     41        // temporary
     42        FunctionType * genAssignType( Type * paramType );
    4043
    4144        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
  • src/SynTree/Expression.cc

    rd335627 r8a6cf7e  
    9292}
    9393
     94VariableExpr * VariableExpr::functionPointer( FunctionDecl * func ) {
     95        VariableExpr * funcExpr = new VariableExpr( func );
     96        funcExpr->set_result( new PointerType( Type::Qualifiers(), funcExpr->get_result() ) );
     97        return funcExpr;
     98}
     99
    94100void VariableExpr::print( std::ostream &os, int indent ) const {
    95101        os << "Variable Expression: ";
  • src/SynTree/Expression.h

    rd335627 r8a6cf7e  
    259259        void set_var( DeclarationWithType * newValue ) { var = newValue; }
    260260
     261        static VariableExpr * functionPointer( FunctionDecl * decl );
     262
    261263        virtual VariableExpr * clone() const { return new VariableExpr( * this ); }
    262264        virtual void accept( Visitor & v ) { v.visit( this ); }
Note: See TracChangeset for help on using the changeset viewer.