Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r888339e r698ec72  
    3636#include "FixGlobalInit.h"             // for fixGlobalInit
    3737#include "GenInit.h"                   // for genCtorDtor
     38#include "GenPoly/DeclMutator.h"       // for DeclMutator
    3839#include "GenPoly/GenPoly.h"           // for getFunctionType
     40#include "GenPoly/PolyMutator.h"       // for PolyMutator
    3941#include "InitTweak.h"                 // for getFunctionName, getCallArg
    4042#include "Parser/LinkageSpec.h"        // for C, Spec, Cforall, isBuiltin
     
    4446#include "SymTab/Indexer.h"            // for Indexer
    4547#include "SymTab/Mangler.h"            // for Mangler
     48#include "SynTree/AddStmtVisitor.h"    // for AddStmtVisitor
    4649#include "SynTree/Attribute.h"         // for Attribute
    4750#include "SynTree/Constant.h"          // for Constant
     
    5558#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
    5659#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
     60#include "Tuples/Tuples.h"             // for isTtype
    5761
    5862bool ctordtorp = false; // print all debug
     
    183187                };
    184188
    185                 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
     189                class FixCopyCtors final : public GenPoly::PolyMutator {
    186190                  public:
    187191                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     
    190194                        static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
    191195
    192                         Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
    193                         void premutate( StmtExpr * stmtExpr );
    194                         void premutate( UniqueExpr * unqExpr );
     196                        typedef GenPoly::PolyMutator Parent;
     197                        using Parent::mutate;
     198                        virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
     199                        virtual Expression * mutate( UniqueExpr * unqExpr ) override;
     200                        virtual Expression * mutate( StmtExpr * stmtExpr ) override;
    195201
    196202                        UnqCount & unqCount;
     
    237243                };
    238244
    239                 struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer {
     245                class FixCtorExprs final : public GenPoly::DeclMutator {
     246                  public:
    240247                        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    241248                        static void fix( std::list< Declaration * > & translationUnit );
    242249
    243                         Expression * postmutate( ConstructorExpr * ctorExpr );
     250                        using GenPoly::DeclMutator::mutate;
     251                        virtual Expression * mutate( ConstructorExpr * ctorExpr ) override;
    244252                };
    245253        } // namespace
     
    308316
    309317                void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    310                         PassVisitor<FixCopyCtors> fixer( unqCount );
     318                        FixCopyCtors fixer( unqCount );
    311319                        mutateAll( translationUnit, fixer );
    312320                }
     
    318326
    319327                void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) {
    320                         PassVisitor<FixCtorExprs> fixer;
    321                         mutateAll( translationUnit, fixer );
     328                        FixCtorExprs fixer;
     329                        fixer.mutateDeclarationList( translationUnit );
    322330                }
    323331
     
    331339                                } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
    332340                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    333                                         assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
     341                                        assert( ftype );
    334342                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    335343                                                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
     
    360368                }
    361369
    362                 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); }
     370                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
     371                        return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
     372                }
    363373
    364374                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     
    397407                        result = result->clone();
    398408                        env->apply( result );
    399                         ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
     409                        ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
    400410                        tmp->get_type()->set_const( false );
    401411
     
    411421                                if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
    412422                        }
    413 
    414                         // set a unique name for the temporary once it's certain the call is necessary
    415                         tmp->name = tempNamer.newName();
    416423
    417424                        // replace argument to function call with temporary
     
    443450                                result = result->clone();
    444451                                env->apply( result );
    445                                 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
     452                                ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
    446453                                ret->get_type()->set_const( false );
    447454                                impCpCtorExpr->get_returnDecls().push_back( ret );
    448455                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    449456                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    450                                         // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
     457                                        // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    451458                                        destructRet( ret, impCpCtorExpr );
    452459                                }
     
    465472                                result = result->clone();
    466473                                env->apply( result );
    467                                 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
     474                                ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
    468475                                ret->get_type()->set_const( false );
    469476                                stmtExpr->get_returnDecls().push_front( ret );
     
    502509                        } else {
    503510                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    504                                 unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), nullptr ) );
     511                                unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
    505512                                unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
    506513                        }
     
    508515                }
    509516
    510                 Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     517                Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    511518                        CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
    512519
     520                        impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );
    513521                        std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
    514522                        std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     
    517525                        // add all temporary declarations and their constructors
    518526                        for ( ObjectDecl * obj : tempDecls ) {
    519                                 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
     527                                stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
    520528                        } // for
    521529                        for ( ObjectDecl * obj : returnDecls ) {
    522                                 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
     530                                stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
    523531                        } // for
    524532
     
    528536                        } // for
    529537
     538                        // xxx - update to work with multiple return values
    530539                        ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
    531540                        Expression * callExpr = impCpCtorExpr->get_callExpr();
     
    560569                }
    561570
    562                 void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
     571                Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {
    563572                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    564573                        // since temporaries can be shared across sub-expressions, e.g.
    565574                        //   [A, A] f();
    566575                        //   g([A] x, [A] y);
    567                         //   g(f());
     576                        //   f(g());
    568577                        // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
    569                         // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added
    570                         // to the outer context, rather than inside of the statement expression.
    571                         visit_children = false;
    572578                        std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
    573579                        for ( Statement *& stmt : stmts ) {
    574                                 stmt = stmt->acceptMutator( *visitor );
     580                                stmt = stmt->acceptMutator( *this );
    575581                        } // for
     582                        // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );
    576583                        assert( stmtExpr->get_result() );
    577584                        Type * result = stmtExpr->get_result();
    578585                        if ( ! result->isVoid() ) {
    579586                                for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
    580                                         stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
     587                                        stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
    581588                                } // for
    582589                                // add destructors after current statement
     
    585592                                } // for
    586593                                // must have a non-empty body, otherwise it wouldn't have a result
    587                                 assert( ! stmts.empty() );
     594                                CompoundStmt * body = stmtExpr->get_statements();
     595                                assert( ! body->get_kids().empty() );
    588596                                assert( ! stmtExpr->get_returnDecls().empty() );
    589                                 stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
     597                                body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
    590598                                stmtExpr->get_returnDecls().clear();
    591599                                stmtExpr->get_dtors().clear();
     
    593601                        assert( stmtExpr->get_returnDecls().empty() );
    594602                        assert( stmtExpr->get_dtors().empty() );
    595                 }
    596 
    597                 void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
    598                         visit_children = false;
     603                        return stmtExpr;
     604                }
     605
     606                Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
    599607                        unqCount[ unqExpr->get_id() ]--;
    600608                        static std::unordered_map< int, std::list< Statement * > > dtors;
    601609                        static std::unordered_map< int, UniqueExpr * > unqMap;
     610                        static std::unordered_set< int > addDeref;
    602611                        // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    603612                        if ( unqMap.count( unqExpr->get_id() ) ) {
     
    610619                                        stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    611620                                }
    612                                 return;
    613                         }
    614                         PassVisitor<FixCopyCtors> fixer( unqCount );
     621                                if ( addDeref.count( unqExpr->get_id() ) ) {
     622                                        // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too
     623                                        return UntypedExpr::createDeref( unqExpr );
     624                                }
     625                                return unqExpr;
     626                        }
     627                        FixCopyCtors fixer( unqCount );
    615628                        unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
    616                         stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
     629                        stmtsToAdd.splice( stmtsToAdd.end(), fixer.stmtsToAdd );
    617630                        unqMap[unqExpr->get_id()] = unqExpr;
    618631                        if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
    619632                                stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    620633                        } else { // remember dtors for last instance of unique expr
    621                                 dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
    622                         }
    623                         return;
     634                                dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter;
     635                        }
     636                        if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
     637                                // unique expression is now a dereference, because the inner expression is an lvalue returning function call.
     638                                // Normalize the expression by dereferencing the unique expression, rather than the inner expression
     639                                // (i.e. move the dereference out a level)
     640                                assert( getFunctionName( deref ) == "*?" );
     641                                unqExpr->set_expr( getCallArg( deref, 0 ) );
     642                                getCallArg( deref, 0 ) = unqExpr;
     643                                addDeref.insert( unqExpr->get_id() );
     644                                return deref;
     645                        }
     646                        return unqExpr;
    624647                }
    625648
     
    796819                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    797820                                        Statement * dtor = ctorInit->get_dtor();
    798                                         // don't need to call intrinsic dtor, because it does nothing, but
    799                                         // non-intrinsic dtors must be called
    800821                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    801                                                 // set dtor location to the object's location for error messages
    802                                                 ctorInit->dtor->location = objDecl->location;
     822                                                // don't need to call intrinsic dtor, because it does nothing, but
     823                                                // non-intrinsic dtors must be called
    803824                                                reverseDeclOrder.front().push_front( objDecl );
    804825                                        } // if
     
    9911012                                        // skip non-DWT members
    9921013                                        if ( ! field ) continue;
    993                                         // skip non-constructable members
    994                                         if ( ! tryConstruct( field ) ) continue;
    9951014                                        // skip handled members
    9961015                                        if ( ! unhandled.count( field ) ) continue;
     
    11231142                }
    11241143
    1125                 Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) {
     1144                Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
    11261145                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    11271146                        // xxx - is the size check necessary?
     
    11291148
    11301149                        // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.
    1131                         ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr );
    1132                         declsToAddBefore.push_back( tmp );
     1150                        ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
     1151                        addDeclaration( tmp );
    11331152
    11341153                        // xxx - this can be TupleAssignExpr now. Need to properly handle this case.
     
    11391158                        delete ctorExpr;
    11401159
    1141                         // build assignment and replace constructor's first argument with new temporary
    11421160                        Expression *& firstArg = callExpr->get_args().front();
    1143                         Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } );
     1161
     1162                        // 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.
     1163
     1164                        // generate the type of assignment operator using the type of tmp minus any reference types
     1165                        Type * type = tmp->get_type()->stripReferences();
     1166                        FunctionType * ftype = SymTab::genAssignType( type );
     1167
     1168                        // generate fake assignment decl and call it using &tmp and &firstArg
     1169                        // since tmp is guaranteed to be a reference and we want to assign pointers
     1170                        FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
     1171                        ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
     1172                        assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
     1173                        Expression * addrArg = new AddressExpr( firstArg );
     1174                        // if firstArg has type T&&, then &firstArg has type T*&.
     1175                        // Cast away the reference to a value type so that the argument
     1176                        // matches the assignment's parameter types
     1177                        if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
     1178                                addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
     1179                        }
     1180                        assign->get_args().push_back( addrArg );
    11441181                        firstArg = new VariableExpr( tmp );
    1145 
    1146                         // resolve assignment and dispose of new env
    1147                         Expression * resolvedAssign = ResolvExpr::findVoidExpression( assign, indexer );
    1148                         delete resolvedAssign->env;
    1149                         resolvedAssign->env = nullptr;
    1150                         delete assign;
    11511182
    11521183                        // for constructor expr:
     
    11571188                        //   T & tmp;
    11581189                        //   &tmp = &x, ?{}(tmp), tmp
    1159                         CommaExpr * commaExpr = new CommaExpr( resolvedAssign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
     1190                        CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    11601191                        commaExpr->set_env( env );
    11611192                        return commaExpr;
Note: See TracChangeset for help on using the changeset viewer.