Ignore:
Timestamp:
Aug 5, 2016, 11:03:04 AM (8 years ago)
Author:
Aaron Moss <a3moss@…>
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:
a2f920f
Parents:
5070fe4 (diff), 1b0020a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge changes from master

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r5070fe4 rc331406  
    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"
     
    2526#include "SynTree/Type.h"
    2627#include "SynTree/Expression.h"
     28#include "SynTree/Attribute.h"
    2729#include "SynTree/Statement.h"
    2830#include "SynTree/Initializer.h"
     
    8385                };
    8486
     87                // debug
    8588                struct printSet {
    8689                        typedef ObjDeclCollector::ObjectSet ObjectSet;
     
    159162
    160163                        virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
     164
     165                        std::list< Declaration * > staticDtorDecls;
    161166                };
    162167
     
    171176        } // namespace
    172177
    173         void fix( std::list< Declaration * > & translationUnit ) {
     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
    174182                InsertImplicitCalls::insert( translationUnit );
    175183                ResolveCopyCtors::resolveImplicitCalls( translationUnit );
     
    194202                void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
    195203                        FixInit fixer;
    196                         mutateAll( translationUnit, 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
    197219                }
    198220
     
    422444                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    423445                                        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                                                //
    424450                                                // generate:
    425                                                 // static bool __objName_uninitialized = true;
    426                                                 // if (__objName_uninitialized) {
    427                                                 //   __ctor(__objName);
    428                                                 //   void dtor_atexit() {
    429                                                 //     __dtor(__objName);
     451                                                // static T __objName_static_varN;
     452                                                // void __objName_dtor_atexitN() {
     453                                                //   __dtor__...;
     454                                                // }
     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);
    430462                                                //   }
    431                                                 //   on_exit(dtorOnExit, &__objName);
    432                                                 //   __objName_uninitialized = false;
     463                                                //   ...
    433464                                                // }
    434465
    435                                                 // generate first line
     466                                                static UniqueName dtorCallerNamer( "_dtor_atexit" );
     467
     468                                                // static bool __objName_uninitialized = true
    436469                                                BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
    437470                                                SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
     
    439472                                                isUninitializedVar->fixUniqueId();
    440473
    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 
    450474                                                // __objName_uninitialized = false;
    451475                                                UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) );
     
    457481                                                std::list< Statement * > & body = initStmts->get_kids();
    458482                                                body.push_back( ctor );
    459                                                 body.push_back( new DeclStmt( noLabels, dtorCaller ) );
    460                                                 body.push_back( new ExprStmt( noLabels, callAtexit ) );
    461483                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
    462484
     
    465487                                                stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
    466488                                                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                                                }
    467528                                        } else {
    468529                                                stmtsToAddAfter.push_back( ctor );
     
    524585                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    525586                                        Statement * dtor = ctorInit->get_dtor();
    526                                         if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
     587                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    527588                                                // don't need to call intrinsic dtor, because it does nothing, but
    528589                                                // non-intrinsic dtors must be called
Note: See TracChangeset for help on using the changeset viewer.