Changeset 72e9222


Ignore:
Timestamp:
Jul 22, 2016, 3:55:51 PM (5 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, ctor, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
aedfd91
Parents:
ccb447e
Message:

change codegen for function-scoped static variable destruction to eliminate memory errors

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    rccb447e r72e9222  
    161161
    162162                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
     163
     164                        std::list< Declaration * > staticDtorDecls;
    163165                };
    164166
     
    199201                void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
    200202                        FixInit fixer;
    201                         mutateAll( translationUnit, fixer );
     203
     204                        // can't use mutateAll, because need to insert declarations at top-level
     205                        // can't use DeclMutator, because sometimes need to insert IfStmt, etc.
     206                        SemanticError errors;
     207                        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
     208                                try {
     209                                        *i = maybeMutate( *i, fixer );
     210                                        // if (! fixer.staticDtorDecls.empty() ) {
     211                                                translationUnit.splice( i, fixer.staticDtorDecls );
     212                                        // }
     213                                } catch( SemanticError &e ) {
     214                                        errors.append( e );
     215                                } // try
     216                        } // for
     217                        if ( ! errors.isEmpty() ) {
     218                                throw errors;
     219                        } // if
    202220                }
    203221
     
    427445                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    428446                                        if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
     447                                                // originally wanted to take advantage of gcc nested functions, but
     448                                                // we get memory errors with this approach. To remedy this, create a
     449                                                // global static pointer that is set to refer to the object and make
     450                                                // the dtor-caller function global so that.
     451                                                //
    429452                                                // generate:
    430                                                 // static bool __objName_uninitialized = true;
    431                                                 // if (__objName_uninitialized) {
    432                                                 //   __ctor(__objName);
    433                                                 //   void dtor_atexit() {
    434                                                 //     __dtor(__objName);
     453                                                // T * __objName_static_ptrN;
     454                                                // void __objName_dtor_atexitN() {
     455                                                //   __dtor(__objName_static_ptrN);
     456                                                // }
     457                                                // int f(...) {
     458                                                //   ...
     459                                                //   static T __objName;
     460                                                //   static bool __objName_uninitialized = true;
     461                                                //   if (__objName_uninitialized) {
     462                                                //     __objName_ptr = &__objName;
     463                                                //     __ctor(__objName);
     464                                                //     on_exit(__objName_dtor_atexitN, &__objName);
     465                                                //     __objName_uninitialized = false;
    435466                                                //   }
    436                                                 //   on_exit(dtorOnExit, &__objName);
    437                                                 //   __objName_uninitialized = false;
     467                                                //   ...
    438468                                                // }
    439469
    440                                                 // generate first line
     470                                                static UniqueName ptrNamer( "_static_ptr" );
     471                                                static UniqueName dtorCallerNamer( "_dtor_atexit" );
     472
     473                                                // T * __objName_ptrN
     474                                                ObjectDecl * objPtr = new ObjectDecl( objDecl->get_mangleName() + ptrNamer.newName(), DeclarationNode::Static, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), objDecl->get_type()->clone() ), 0 );
     475                                                objPtr->fixUniqueId();
     476
     477                                                // void __objName_dtor_atexitN(...) {...}
     478                                                // need to modify dtor call so that it refers to objPtr, since function will be global
     479                                                Statement * dtorStmt = ctorInit->get_dtor()->clone();
     480                                                ApplicationExpr * dtor = dynamic_cast< ApplicationExpr * >( InitTweak::getCtorDtorCall( dtorStmt ) );
     481                                                assert( dtor );
     482                                                delete dtor->get_args().front();
     483                                                dtor->get_args().front() = new VariableExpr( objPtr );
     484
     485                                                FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
     486                                                dtorCaller->fixUniqueId();
     487                                                dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
     488
     489                                                // static bool __objName_uninitialized = true
    441490                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    442491                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
     
    444493                                                isUninitializedVar->fixUniqueId();
    445494
    446                                                 // void dtor_atexit(...) {...}
    447                                                 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + "_dtor_atexit", DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
    448                                                 dtorCaller->fixUniqueId();
    449                                                 dtorCaller->get_statements()->get_kids().push_back( ctorInit->get_dtor()->clone() );
    450 
    451                                                 // on_exit(dtor_atexit);
     495                                                // __objName_static_ptrN = &__objName;
     496                                                UntypedExpr * ptrAssign = new UntypedExpr( new NameExpr( "?=?" ) );
     497                                                ptrAssign->get_args().push_back( new VariableExpr( objPtr ) );
     498                                                ptrAssign->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
     499
     500                                                // atexit(dtor_atexit);
    452501                                                UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
    453502                                                callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
     
    462511                                                std::list< Statement * > & body = initStmts->get_kids();
    463512                                                body.push_back( ctor );
    464                                                 body.push_back( new DeclStmt( noLabels, dtorCaller ) );
     513                                                body.push_back( new ExprStmt( noLabels, ptrAssign ) );
    465514                                                body.push_back( new ExprStmt( noLabels, callAtexit ) );
    466515                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
     
    470519                                                stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
    471520                                                stmtsToAddAfter.push_back( ifStmt );
     521
     522                                                // add pointer and dtor caller decls to list of decls that will be added into global scope
     523                                                staticDtorDecls.push_back( objPtr );
     524                                                staticDtorDecls.push_back( dtorCaller );
    472525                                        } else {
    473526                                                stmtsToAddAfter.push_back( ctor );
  • src/tests/init_once.c

    rccb447e r72e9222  
    9292init_once y = x;
    9393
     94void static_variable() {
     95        static init_once x;
     96}
     97
    9498int main() {
    9599        // local variables
     
    179183                }
    180184        }
     185
     186        // function-scoped static variable
     187        for (int i = 0; i < 10; i++) {
     188                static_variable();
     189        }
    181190}
    182191
Note: See TracChangeset for help on using the changeset viewer.