Ignore:
Timestamp:
Sep 26, 2017, 11:27:38 PM (4 years ago)
Author:
Peter A. Buhr <pabuhr@…>
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:
5dc26f5
Parents:
201aeb9
Message:

merge

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r201aeb9 rd67cdb7  
    3636#include "FixGlobalInit.h"             // for fixGlobalInit
    3737#include "GenInit.h"                   // for genCtorDtor
    38 #include "GenPoly/DeclMutator.h"       // for DeclMutator
    3938#include "GenPoly/GenPoly.h"           // for getFunctionType
    40 #include "GenPoly/PolyMutator.h"       // for PolyMutator
    4139#include "InitTweak.h"                 // for getFunctionName, getCallArg
    4240#include "Parser/LinkageSpec.h"        // for C, Spec, Cforall, isBuiltin
     
    4644#include "SymTab/Indexer.h"            // for Indexer
    4745#include "SymTab/Mangler.h"            // for Mangler
    48 #include "SynTree/AddStmtVisitor.h"    // for AddStmtVisitor
    4946#include "SynTree/Attribute.h"         // for Attribute
    5047#include "SynTree/Constant.h"          // for Constant
     
    5855#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
    5956#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    60 #include "Tuples/Tuples.h"             // for isTtype
    6157
    6258bool ctordtorp = false; // print all debug
     
    187183                };
    188184
    189                 class FixCopyCtors final : public GenPoly::PolyMutator {
     185                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
    190186                  public:
    191187                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     
    194190                        static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
    195191
    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;
     192                        Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     193                        void premutate( StmtExpr * stmtExpr );
     194                        void premutate( UniqueExpr * unqExpr );
    201195
    202196                        UnqCount & unqCount;
     
    243237                };
    244238
    245                 class FixCtorExprs final : public GenPoly::DeclMutator {
    246                   public:
     239                struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer {
    247240                        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    248241                        static void fix( std::list< Declaration * > & translationUnit );
    249242
    250                         using GenPoly::DeclMutator::mutate;
    251                         virtual Expression * mutate( ConstructorExpr * ctorExpr ) override;
     243                        Expression * postmutate( ConstructorExpr * ctorExpr );
    252244                };
    253245        } // namespace
     
    316308
    317309                void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    318                         FixCopyCtors fixer( unqCount );
     310                        PassVisitor<FixCopyCtors> fixer( unqCount );
    319311                        mutateAll( translationUnit, fixer );
    320312                }
     
    326318
    327319                void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) {
    328                         FixCtorExprs fixer;
    329                         fixer.mutateDeclarationList( translationUnit );
     320                        PassVisitor<FixCtorExprs> fixer;
     321                        mutateAll( translationUnit, fixer );
    330322                }
    331323
     
    339331                                } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
    340332                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    341                                         assert( ftype );
     333                                        assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
    342334                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    343335                                                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
     
    368360                }
    369361
    370                 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    371                         return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    372                 }
     362                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); }
    373363
    374364                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     
    407397                        result = result->clone();
    408398                        env->apply( result );
    409                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     399                        ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
    410400                        tmp->get_type()->set_const( false );
    411401
     
    421411                                if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
    422412                        }
     413
     414                        // set a unique name for the temporary once it's certain the call is necessary
     415                        tmp->name = tempNamer.newName();
    423416
    424417                        // replace argument to function call with temporary
     
    450443                                result = result->clone();
    451444                                env->apply( result );
    452                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     445                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    453446                                ret->get_type()->set_const( false );
    454447                                impCpCtorExpr->get_returnDecls().push_back( ret );
    455448                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    456449                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    457                                         // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
     450                                        // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    458451                                        destructRet( ret, impCpCtorExpr );
    459452                                }
     
    472465                                result = result->clone();
    473466                                env->apply( result );
    474                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     467                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    475468                                ret->get_type()->set_const( false );
    476469                                stmtExpr->get_returnDecls().push_front( ret );
     
    509502                        } else {
    510503                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    511                                 unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
     504                                unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), nullptr ) );
    512505                                unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
    513506                        }
     
    515508                }
    516509
    517                 Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     510                Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    518511                        CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
    519512
    520                         impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );
    521513                        std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
    522514                        std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     
    525517                        // add all temporary declarations and their constructors
    526518                        for ( ObjectDecl * obj : tempDecls ) {
    527                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     519                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    528520                        } // for
    529521                        for ( ObjectDecl * obj : returnDecls ) {
    530                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     522                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    531523                        } // for
    532524
     
    536528                        } // for
    537529
    538                         // xxx - update to work with multiple return values
    539530                        ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
    540531                        Expression * callExpr = impCpCtorExpr->get_callExpr();
     
    569560                }
    570561
    571                 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {
     562                void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
    572563                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    573564                        // since temporaries can be shared across sub-expressions, e.g.
    574565                        //   [A, A] f();
    575566                        //   g([A] x, [A] y);
    576                         //   f(g());
     567                        //   g(f());
    577568                        // 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;
    578572                        std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
    579573                        for ( Statement *& stmt : stmts ) {
    580                                 stmt = stmt->acceptMutator( *this );
     574                                stmt = stmt->acceptMutator( *visitor );
    581575                        } // for
    582                         // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );
    583576                        assert( stmtExpr->get_result() );
    584577                        Type * result = stmtExpr->get_result();
    585578                        if ( ! result->isVoid() ) {
    586579                                for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
    587                                         stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     580                                        stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    588581                                } // for
    589582                                // add destructors after current statement
     
    592585                                } // for
    593586                                // must have a non-empty body, otherwise it wouldn't have a result
    594                                 CompoundStmt * body = stmtExpr->get_statements();
    595                                 assert( ! body->get_kids().empty() );
     587                                assert( ! stmts.empty() );
    596588                                assert( ! stmtExpr->get_returnDecls().empty() );
    597                                 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
     589                                stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
    598590                                stmtExpr->get_returnDecls().clear();
    599591                                stmtExpr->get_dtors().clear();
     
    601593                        assert( stmtExpr->get_returnDecls().empty() );
    602594                        assert( stmtExpr->get_dtors().empty() );
    603                         return stmtExpr;
    604                 }
    605 
    606                 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
     595                }
     596
     597                void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
     598                        visit_children = false;
    607599                        unqCount[ unqExpr->get_id() ]--;
    608600                        static std::unordered_map< int, std::list< Statement * > > dtors;
    609601                        static std::unordered_map< int, UniqueExpr * > unqMap;
    610                         static std::unordered_set< int > addDeref;
    611602                        // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    612603                        if ( unqMap.count( unqExpr->get_id() ) ) {
     
    619610                                        stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    620611                                }
    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 );
     612                                return;
     613                        }
     614                        PassVisitor<FixCopyCtors> fixer( unqCount );
    628615                        unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
    629                         stmtsToAdd.splice( stmtsToAdd.end(), fixer.stmtsToAdd );
     616                        stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
    630617                        unqMap[unqExpr->get_id()] = unqExpr;
    631618                        if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
    632619                                stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    633620                        } else { // remember dtors for last instance of unique expr
    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;
     621                                dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
     622                        }
     623                        return;
    647624                }
    648625
     
    819796                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    820797                                        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
    821800                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    822                                                 // don't need to call intrinsic dtor, because it does nothing, but
    823                                                 // non-intrinsic dtors must be called
     801                                                // set dtor location to the object's location for error messages
     802                                                ctorInit->dtor->location = objDecl->location;
    824803                                                reverseDeclOrder.front().push_front( objDecl );
    825804                                        } // if
     
    1012991                                        // skip non-DWT members
    1013992                                        if ( ! field ) continue;
     993                                        // skip non-constructable members
     994                                        if ( ! tryConstruct( field ) ) continue;
    1014995                                        // skip handled members
    1015996                                        if ( ! unhandled.count( field ) ) continue;
     
    11421123                }
    11431124
    1144                 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
     1125                Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) {
    11451126                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    11461127                        // xxx - is the size check necessary?
     
    11481129
    11491130                        // 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.
    1150                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
    1151                         addDeclaration( tmp );
     1131                        ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr );
     1132                        declsToAddBefore.push_back( tmp );
    11521133
    11531134                        // xxx - this can be TupleAssignExpr now. Need to properly handle this case.
     
    11581139                        delete ctorExpr;
    11591140
     1141                        // build assignment and replace constructor's first argument with new temporary
    11601142                        Expression *& firstArg = callExpr->get_args().front();
    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 );
     1143                        Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } );
    11811144                        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;
    11821151
    11831152                        // for constructor expr:
     
    11881157                        //   T & tmp;
    11891158                        //   &tmp = &x, ?{}(tmp), tmp
    1190                         CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
     1159                        CommaExpr * commaExpr = new CommaExpr( resolvedAssign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    11911160                        commaExpr->set_env( env );
    11921161                        return commaExpr;
Note: See TracChangeset for help on using the changeset viewer.