Ignore:
Timestamp:
Apr 14, 2016, 3:22:42 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
70a06f6
Parents:
7eabc25
Message:

add ImplicitCopyCtorExpr? node, implicit copy constructors are inserted into the right places (but there is room for elision)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r7eabc25 rdb4ecc5  
    1010// Created On       : Wed Jan 13 16:29:30 2016
    1111// Last Modified By : Rob Schluntz
    12 // Last Modified On : Thu Mar 31 13:54:58 2016
     12// Last Modified On : Thu Apr 14 15:19:11 2016
    1313// Update Count     : 30
    1414//
     
    1717#include <list>
    1818#include "RemoveInit.h"
     19#include "ResolvExpr/Resolver.h"
    1920#include "SynTree/Declaration.h"
    2021#include "SynTree/Type.h"
     
    2324#include "SynTree/Initializer.h"
    2425#include "SynTree/Mutator.h"
     26#include "SymTab/Indexer.h"
    2527#include "GenPoly/PolyMutator.h"
    2628
     
    3133        }
    3234
     35        class InsertImplicitCalls : public Mutator {
     36        public:
     37                /// wrap function application expressions as ImplicitCopyCtorExpr nodes
     38                /// so that it is easy to identify which function calls need their parameters
     39                /// to be copy constructed
     40                static void insert( std::list< Declaration * > & translationUnit );
     41
     42                virtual Expression * mutate( ApplicationExpr * appExpr );
     43        };
     44
     45        class ResolveCopyCtors : public SymTab::Indexer {
     46        public:
     47                /// generate temporary ObjectDecls for each argument and return value of each
     48                /// ImplicitCopyCtorExpr, generate/resolve copy construction expressions for each,
     49                /// and generate/resolve destructors for both arguments and return value temporaries
     50                static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
     51
     52                virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
     53
     54                /// create and resolve ctor/dtor expression: fname(var, [cpArg])
     55                ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
     56        };
     57
    3358        class FixInit : public GenPoly::PolyMutator {
    3459          public:
     60                /// expand each object declaration to use its constructor after it is declared.
     61                /// insert destructor calls at the appropriate places
    3562                static void fixInitializers( std::list< Declaration * > &translationUnit );
    3663
    37                 virtual ObjectDecl * mutate( ObjectDecl *objDecl );
     64                virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
    3865
    3966                virtual CompoundStmt * mutate( CompoundStmt * compoundStmt );
     
    4673        };
    4774
     75        class FixCopyCtors : public GenPoly::PolyMutator {
     76          public:
     77                /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors,
     78                /// call expression, and destructors
     79                static void fixCopyCtors( std::list< Declaration * > &translationUnit );
     80
     81                virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     82
     83          private:
     84                // stack of list of statements - used to differentiate scopes
     85                std::list< std::list< Statement * > > dtorStmts;
     86        };
     87
    4888        void fix( std::list< Declaration * > & translationUnit ) {
     89                InsertImplicitCalls::insert( translationUnit );
     90                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
    4991                FixInit::fixInitializers( translationUnit );
     92                // FixCopyCtors must happen after FixInit, so that destructors are placed correctly
     93                FixCopyCtors::fixCopyCtors( translationUnit );
     94        }
     95
     96        void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) {
     97                InsertImplicitCalls inserter;
     98                mutateAll( translationUnit, inserter );
     99        }
     100
     101        void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) {
     102                ResolveCopyCtors resolver;
     103                acceptAll( translationUnit, resolver );
    50104        }
    51105
     
    55109        }
    56110
    57         ObjectDecl *FixInit::mutate( ObjectDecl *objDecl ) {
     111        void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit ) {
     112                FixCopyCtors fixer;
     113                mutateAll( translationUnit, fixer );
     114        }
     115
     116        Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) {
     117                if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) {
     118                        if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
     119                                // optimization: don't need to copy construct in order to call intrinsic functions
     120                                return appExpr;
     121                        } else if ( FunctionDecl * func = dynamic_cast< FunctionDecl * > ( function->get_var() ) ) {
     122                                // if (  )
     123                                // // optimization: don't need to copy construct in order to call a copy constructor
     124                                // return appExpr;
     125                        }
     126                }
     127                // wrap each function call so that it is easy to identify nodes that have to be copy constructed
     128                appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) );
     129                assert( appExpr );
     130                return new ImplicitCopyCtorExpr( appExpr );
     131        }
     132
     133        ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     134                assert( var );
     135                UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) );
     136                untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) );
     137                if (cpArg) untyped->get_args().push_back( cpArg );
     138
     139                // resolve copy constructor
     140                // should only be one alternative for copy ctor and dtor expressions, since
     141                // all arguments are fixed (VariableExpr and already resolved expression)
     142                ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) );
     143
     144                assert( resolved );
     145                delete untyped;
     146                return resolved;
     147        }
     148
     149        void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
     150                static UniqueName tempNamer("_tmp_cp");
     151                static UniqueName retNamer("_tmp_cp_ret");
     152
     153                // resolve function call
     154                Expression * newExpr = ResolvExpr::findVoidExpression( impCpCtorExpr->get_callExpr(), *this );
     155                delete impCpCtorExpr->get_callExpr();
     156                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( newExpr );
     157                assert( appExpr );
     158                impCpCtorExpr->set_callExpr( appExpr );
     159
     160                // take each argument and attempt to copy construct it.
     161                for ( Expression * & arg : appExpr->get_args() ) {
     162                        // xxx - need to handle tuple arguments
     163                        assert( ! arg->get_results().empty() );
     164                        ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, arg->get_results().front()->clone(), 0 );
     165
     166                        // create and resolve copy constructor
     167                        ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg );
     168
     169                        // if the chosen constructor is intrinsic, the copy is unnecessary, so
     170                        // don't create the temporary and don't call the copy constructor
     171                        VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() );
     172                        assert( function );
     173                        if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) {
     174                                // replace argument to function call with temporary
     175                                arg = new VariableExpr( tmp );
     176                                impCpCtorExpr->get_tempDecls().push_back( tmp );
     177                                impCpCtorExpr->get_copyCtors().push_back( cpCtor );
     178                                impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
     179                        }
     180                }
     181
     182                // each return value from the call needs to be connected with an ObjectDecl
     183                // at the call site, which is initialized with the return value and is destructed
     184                // later
     185                // xxx - handle multiple return values
     186                for ( Type * result : appExpr->get_results() ) {
     187                        ObjectDecl * ret = new ObjectDecl( retNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result->clone(), new SingleInit( impCpCtorExpr->get_callExpr() ) );
     188                        impCpCtorExpr->get_returnDecls().push_back( ret );
     189                        impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
     190                }
     191        }
     192
     193
     194        Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     195                impCpCtorExpr = dynamic_cast< ImplicitCopyCtorExpr * >( Mutator::mutate( impCpCtorExpr ) );
     196                assert( impCpCtorExpr );
     197                std::cerr << "Running FixCopyCtors on implicit copy ctor..." << std::endl;
     198
     199                std::list< Expression * > & copyCtors = impCpCtorExpr->get_copyCtors();
     200                std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
     201                std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     202                std::list< Expression * > & dtors = impCpCtorExpr->get_dtors();
     203
     204                // add all temporary declarations and their constructors
     205                for ( ObjectDecl * obj : tempDecls ) {
     206                        assert( ! copyCtors.empty() );
     207                        stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     208                        stmtsToAdd.push_back( new ExprStmt( noLabels, copyCtors.front() ) );
     209                        copyCtors.pop_front();
     210                }
     211
     212                // add destructors after current statement
     213                for ( Expression * dtor : dtors ) {
     214                        stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) );
     215                }
     216
     217                // xxx - update to work with multiple return values
     218                ObjectDecl * returnDecl = returnDecls.empty() ? NULL : returnDecls.front();
     219
     220                // xxx - some of these aren't necessary, and can be removed once this is stable
     221                copyCtors.clear();
     222                dtors.clear();
     223                tempDecls.clear();
     224                returnDecls.clear();
     225
     226                if ( returnDecl ) {
     227                        // call is currently attached to first returnDecl
     228                        stmtsToAdd.push_back( new DeclStmt( noLabels, returnDecl ) );
     229                        return new VariableExpr( returnDecl );
     230                } else {
     231                        // add call expression - if no return values, can call directly
     232                        return impCpCtorExpr->get_callExpr();
     233                }
     234        }
     235
     236        DeclarationWithType *FixInit::mutate( ObjectDecl *objDecl ) {
     237                // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors
     238                // when the init is removed from the ObjectDecl
     239                objDecl = dynamic_cast< ObjectDecl * >( Mutator::mutate( objDecl ) );
     240
    58241                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    59242                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     
    170353                        insertDtors( list->begin(), list->end(), back_inserter( stmtsToAdd ) );
    171354                }
    172                 return returnStmt;
     355                return Mutator::mutate( returnStmt );
    173356        }
    174357
     
    189372                                assert( false );
    190373                }
    191                 return branchStmt;
     374                return Mutator::mutate( branchStmt );
    192375        }
    193376
Note: See TracChangeset for help on using the changeset viewer.