Changeset 6cf27a07 for src/InitTweak


Ignore:
Timestamp:
Jul 21, 2016, 2:07:01 PM (9 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, 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:
ccb447e
Parents:
b81adcc4
Message:

reorganize global init so that it is simpler and generates less unnecessary code

Location:
src/InitTweak
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified src/InitTweak/FixGlobalInit.cc

    rb81adcc4 r6cf27a07  
    9797                std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
    9898
    99                 if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
    100                 if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
    10199                // C allows you to initialize objects with constant expressions
    102100                // xxx - this is an optimization. Need to first resolve constructors before we decide
     
    104102                // if ( isConstExpr( objDecl->get_init() ) ) return;
    105103
    106                 if ( dynamic_cast< ArrayType * > ( objDecl->get_type() ) ) {
    107                         // xxx - initialize each element of the array
    108                 } else {
    109                         // insert constructor for objDecl into global init function
    110                         UntypedExpr * init = new UntypedExpr( new NameExpr( "?{}" ) );
    111                         init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
    112                         init->get_args().splice( init->get_args().end(), makeInitList( objDecl->get_init() ) );
    113                         objDecl->set_init( NULL );
    114                         initStatements.push_back( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, init ) ) );
     104                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
     105                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     106                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    115107
    116                         // add destructor calls to global destroy function
    117                         UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) );
    118                         destroy->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
    119                         destroyStatements.push_front( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, destroy ) ) );
     108                        Statement * dtor = ctorInit->get_dtor();
     109                        if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
     110                                // don't need to call intrinsic dtor, because it does nothing, but
     111                                // non-intrinsic dtors must be called
     112                                destroyStatements.push_front( dtor );
     113                                ctorInit->set_dtor( NULL );
     114                        } // if
     115                        if ( Statement * ctor = ctorInit->get_ctor() ) {
     116                                initStatements.push_back( ctor );
     117                                objDecl->set_init( NULL );
     118                                ctorInit->set_ctor( NULL );
     119                        } else if ( Initializer * init = ctorInit->get_init() ) {
     120                                objDecl->set_init( init );
     121                                ctorInit->set_init( NULL );
     122                        } else {
     123                                // no constructor and no initializer, which is okay
     124                                objDecl->set_init( NULL );
     125                        } // if
     126                        delete ctorInit;
    120127                } // if
    121128        }
  • TabularUnified src/InitTweak/FixInit.cc

    rb81adcc4 r6cf27a07  
    1818#include <iterator>
    1919#include <algorithm>
     20#include "InitTweak.h"
    2021#include "FixInit.h"
    21 #include "InitTweak.h"
     22#include "FixGlobalInit.h"
    2223#include "ResolvExpr/Resolver.h"
    2324#include "ResolvExpr/typeops.h"
     
    8384                };
    8485
     86                // debug
    8587                struct printSet {
    8688                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    171173        } // namespace
    172174
    173         void fix( std::list< Declaration * > & translationUnit ) {
     175        void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     176                // fixes ConstructorInit for global variables. should happen before fixInitializers.
     177                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     178
    174179                InsertImplicitCalls::insert( translationUnit );
    175180                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
  • TabularUnified src/InitTweak/FixInit.h

    rb81adcc4 r6cf27a07  
    2727  /// replace constructor initializers with expression statements
    2828  /// and unwrap basic C-style initializers
    29         void fix( std::list< Declaration * > & translationUnit );
     29        void fix( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
    3030} // namespace
    3131
  • TabularUnified src/InitTweak/GenInit.cc

    rb81adcc4 r6cf27a07  
    6161                static void generateCtorDtor( std::list< Declaration * > &translationUnit );
    6262
    63                 CtorDtor() : inFunction( false ) {}
    64 
    6563                virtual DeclarationWithType * mutate( ObjectDecl * );
    6664                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
     
    7775
    7876          protected:
    79                 bool inFunction;
    8077        };
    8178
     
    216213
    217214        DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
    218                 // hands off if designated or if @=
     215                // hands off if designated, if @=, or if extern
    219216                if ( tryConstruct( objDecl ) ) {
    220                         if ( inFunction ) {
    221                                 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
    222                                         // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
    223                                         // TODO: walk initializers and generate appropriate ctor if element has initializer.
    224                                         // Initializer could be nested (depends on the depth of the array type on the object)
    225 
    226                                         std::list< Expression * > args = makeInitList( objDecl->get_init() );
    227                                         if ( args.empty() ) {
    228                                                 std::list< Statement * > ctor;
    229                                                 std::list< Statement * > dtor;
    230 
    231                                                 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    232                                                 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
    233 
    234                                                 // Currently genArrayCall produces a single Statement - a CompoundStmt
    235                                                 // which  wraps everything that needs to happen. As such, it's technically
    236                                                 // possible to use a Statement ** in the above calls, but this is inherently
    237                                                 // unsafe, so instead we take the slightly less efficient route, but will be
    238                                                 // immediately informed if somehow the above assumption is broken. In this case,
    239                                                 // we could always wrap the list of statements at this point with a CompoundStmt,
    240                                                 // but it seems reasonable at the moment for this to be done by genArrayCall
    241                                                 // itself
    242                                                 assert( ctor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( ctor.front() ) );
    243                                                 assert( dtor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( dtor.front() ) );
     217                        if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
     218                                // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
     219                                // TODO: walk initializers and generate appropriate ctor if element has initializer.
     220                                // Initializer could be nested (depends on the depth of the array type on the object)
     221
     222                                std::list< Expression * > args = makeInitList( objDecl->get_init() );
     223                                if ( args.empty() ) {
     224                                        std::list< Statement * > ctor;
     225                                        std::list< Statement * > dtor;
     226
     227                                        SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     228                                        SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     229
     230                                        // Currently genImplicitCall produces a single Statement - a CompoundStmt
     231                                        // which  wraps everything that needs to happen. As such, it's technically
     232                                        // possible to use a Statement ** in the above calls, but this is inherently
     233                                        // unsafe, so instead we take the slightly less efficient route, but will be
     234                                        // immediately informed if somehow the above assumption is broken. In this case,
     235                                        // we could always wrap the list of statements at this point with a CompoundStmt,
     236                                        // but it seems reasonable at the moment for this to be done by genImplicitCall
     237                                        // itself. It is possible that genImplicitCall produces no statements (e.g. if
     238                                        // an array type does not have a dimension). In this case, it's fine to ignore
     239                                        // the object for the purposes of construction.
     240                                        assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     241                                        if ( ctor.size() == 1 ) {
     242                                                assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    244243                                                objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
    245                                         } else {
    246                                                 // array came with an initializer list: initialize each element
    247                                                 // may have more initializers than elements in the array - need to check at each index that
    248                                                 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
    249                                                 // computation.
    250                                                 // may have fewer initializers than elements in the array - need to default construct
    251                                                 // remaining elements.
    252                                                 // might be able to merge this with the case above.
    253 
    254244                                        }
    255245                                } else {
    256                                         // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
    257                                         Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
    258                                         Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
    259 
    260                                         // need to remember init expression, in case no ctors exist
    261                                         // if ctor does exist, want to use ctor expression instead of init
    262                                         // push this decision to the resolver
    263                                         ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
    264                                         ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
    265                                         objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
     246                                        // array came with an initializer list: initialize each element
     247                                        // may have more initializers than elements in the array - need to check at each index that
     248                                        // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
     249                                        // computation.
     250                                        // may have fewer initializers than elements in the array - need to default construct
     251                                        // remaining elements.
     252                                        // might be able to merge this with the case above.
     253
    266254                                }
     255                        } else {
     256                                // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
     257                                Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
     258                                Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
     259
     260                                // need to remember init expression, in case no ctors exist
     261                                // if ctor does exist, want to use ctor expression instead of init
     262                                // push this decision to the resolver
     263                                ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
     264                                ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
     265                                objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
    267266                        }
    268267                }
     
    272271        DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
    273272                // parameters should not be constructed and destructed, so don't mutate FunctionType
    274                 bool oldInFunc = inFunction;
    275273                mutateAll( functionDecl->get_oldDecls(), *this );
    276                 inFunction = true;
    277274                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
    278                 inFunction = oldInFunc;
    279275                return functionDecl;
    280276        }
  • TabularUnified src/InitTweak/InitTweak.cc

    rb81adcc4 r6cf27a07  
    5757                        (objDecl->get_init() == NULL ||
    5858                                ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
    59                         ! isDesignated( objDecl->get_init() );
     59                        ! isDesignated( objDecl->get_init() )
     60                        && objDecl->get_storageClass() != DeclarationNode::Extern;
    6061        }
    6162
Note: See TracChangeset for help on using the changeset viewer.