Ignore:
Timestamp:
Jul 21, 2016, 2:07:01 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, 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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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        }
Note: See TracChangeset for help on using the changeset viewer.