Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    rf9cebb5 r4e06c1e  
    1818#include <iterator>
    1919#include <algorithm>
     20#include "FixInit.h"
    2021#include "InitTweak.h"
    21 #include "FixInit.h"
    22 #include "FixGlobalInit.h"
    2322#include "ResolvExpr/Resolver.h"
    2423#include "ResolvExpr/typeops.h"
     
    2625#include "SynTree/Type.h"
    2726#include "SynTree/Expression.h"
    28 #include "SynTree/Attribute.h"
    2927#include "SynTree/Statement.h"
    3028#include "SynTree/Initializer.h"
     
    8583                };
    8684
    87                 // debug
    8885                struct printSet {
    8986                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    162159
    163160                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
    164 
    165                         std::list< Declaration * > staticDtorDecls;
    166161                };
    167162
     
    176171        } // namespace
    177172
    178         void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
    179                 // fixes ConstructorInit for global variables. should happen before fixInitializers.
    180                 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
    181 
     173        void fix( std::list< Declaration * > & translationUnit ) {
    182174                InsertImplicitCalls::insert( translationUnit );
    183175                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
     
    202194                void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
    203195                        FixInit fixer;
    204 
    205                         // can't use mutateAll, because need to insert declarations at top-level
    206                         // can't use DeclMutator, because sometimes need to insert IfStmt, etc.
    207                         SemanticError errors;
    208                         for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    209                                 try {
    210                                         *i = maybeMutate( *i, fixer );
    211                                         translationUnit.splice( i, fixer.staticDtorDecls );
    212                                 } catch( SemanticError &e ) {
    213                                         errors.append( e );
    214                                 } // try
    215                         } // for
    216                         if ( ! errors.isEmpty() ) {
    217                                 throw errors;
    218                         } // if
     196                        mutateAll( translationUnit, fixer );
    219197                }
    220198
     
    444422                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    445423                                        if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
    446                                                 // originally wanted to take advantage of gcc nested functions, but
    447                                                 // we get memory errors with this approach. To remedy this, the static
    448                                                 // variable is hoisted when the destructor needs to be called.
    449                                                 //
    450424                                                // generate:
    451                                                 // static T __objName_static_varN;
    452                                                 // void __objName_dtor_atexitN() {
    453                                                 //   __dtor__...;
     425                                                // static bool __objName_uninitialized = true;
     426                                                // if (__objName_uninitialized) {
     427                                                //   __ctor(__objName);
     428                                                //   void dtor_atexit() {
     429                                                //     __dtor(__objName);
     430                                                //   }
     431                                                //   on_exit(dtorOnExit, &__objName);
     432                                                //   __objName_uninitialized = false;
    454433                                                // }
    455                                                 // int f(...) {
    456                                                 //   ...
    457                                                 //   static bool __objName_uninitialized = true;
    458                                                 //   if (__objName_uninitialized) {
    459                                                 //     __ctor(__objName);
    460                                                 //     __objName_uninitialized = false;
    461                                                 //     atexit(__objName_dtor_atexitN);
    462                                                 //   }
    463                                                 //   ...
    464                                                 // }
    465 
    466                                                 static UniqueName dtorCallerNamer( "_dtor_atexit" );
    467 
    468                                                 // static bool __objName_uninitialized = true
     434
     435                                                // generate first line
    469436                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    470437                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
     
    472439                                                isUninitializedVar->fixUniqueId();
    473440
     441                                                // void dtor_atexit(...) {...}
     442                                                FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + "_dtor_atexit", DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
     443                                                dtorCaller->fixUniqueId();
     444                                                dtorCaller->get_statements()->get_kids().push_back( ctorInit->get_dtor()->clone() );
     445
     446                                                // on_exit(dtor_atexit);
     447                                                UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
     448                                                callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
     449
    474450                                                // __objName_uninitialized = false;
    475451                                                UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) );
     
    481457                                                std::list< Statement * > & body = initStmts->get_kids();
    482458                                                body.push_back( ctor );
     459                                                body.push_back( new DeclStmt( noLabels, dtorCaller ) );
     460                                                body.push_back( new ExprStmt( noLabels, callAtexit ) );
    483461                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
    484462
     
    487465                                                stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
    488466                                                stmtsToAddAfter.push_back( ifStmt );
    489 
    490                                                 if ( ctorInit->get_dtor() ) {
    491                                                         // if the object has a non-trivial destructor, have to
    492                                                         // hoist it and the object into the global space and
    493                                                         // call the destructor function with atexit.
    494 
    495                                                         Statement * dtorStmt = ctorInit->get_dtor()->clone();
    496 
    497                                                         // void __objName_dtor_atexitN(...) {...}
    498                                                         FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
    499                                                         dtorCaller->fixUniqueId();
    500                                                         dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
    501 
    502                                                         // atexit(dtor_atexit);
    503                                                         UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
    504                                                         callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
    505 
    506                                                         body.push_back( new ExprStmt( noLabels, callAtexit ) );
    507 
    508                                                         // hoist variable and dtor caller decls to list of decls that will be added into global scope
    509                                                         staticDtorDecls.push_back( objDecl );
    510                                                         staticDtorDecls.push_back( dtorCaller );
    511 
    512                                                         // need to rename object uniquely since it now appears
    513                                                         // at global scope and there could be multiple function-scoped
    514                                                         // static variables with the same name in different functions.
    515                                                         static UniqueName staticNamer( "_static_var" );
    516                                                         objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
    517 
    518                                                         objDecl->set_init( NULL );
    519                                                         ctorInit->set_ctor( NULL );
    520                                                         delete ctorInit;
    521 
    522                                                         // xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope
    523                                                         // create a new object which is never used
    524                                                         static UniqueName dummyNamer( "_dummy" );
    525                                                         ObjectDecl * dummy = new ObjectDecl( dummyNamer.newName(), DeclarationNode::Static, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), 0, std::list< Attribute * >{ new Attribute("unused") } );
    526                                                         return dummy;
    527                                                 }
    528467                                        } else {
    529468                                                stmtsToAddAfter.push_back( ctor );
     
    585524                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    586525                                        Statement * dtor = ctorInit->get_dtor();
    587                                         if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
     526                                        if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
    588527                                                // don't need to call intrinsic dtor, because it does nothing, but
    589528                                                // non-intrinsic dtors must be called
Note: See TracChangeset for help on using the changeset viewer.