Changeset f9cebb5 for src/InitTweak


Ignore:
Timestamp:
Aug 4, 2016, 4:10:06 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:
4819cac
Parents:
73bf8cf2
Message:

add gcc attributes to ObjectDecl, hoist destructed static variables, add breaks to end of generated switch

Location:
src/InitTweak
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixGlobalInit.cc

    r73bf8cf2 rf9cebb5  
    107107
    108108                        Statement * dtor = ctorInit->get_dtor();
    109                         if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
     109                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    110110                                // don't need to call intrinsic dtor, because it does nothing, but
    111111                                // non-intrinsic dtors must be called
  • src/InitTweak/FixInit.cc

    r73bf8cf2 rf9cebb5  
    2626#include "SynTree/Type.h"
    2727#include "SynTree/Expression.h"
     28#include "SynTree/Attribute.h"
    2829#include "SynTree/Statement.h"
    2930#include "SynTree/Initializer.h"
     
    208209                                try {
    209210                                        *i = maybeMutate( *i, fixer );
    210                                         // if (! fixer.staticDtorDecls.empty() ) {
    211                                                 translationUnit.splice( i, fixer.staticDtorDecls );
    212                                         // }
     211                                        translationUnit.splice( i, fixer.staticDtorDecls );
    213212                                } catch( SemanticError &e ) {
    214213                                        errors.append( e );
     
    446445                                        if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
    447446                                                // 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.
     447                                                // we get memory errors with this approach. To remedy this, the static
     448                                                // variable is hoisted when the destructor needs to be called.
    451449                                                //
    452450                                                // generate:
    453                                                 // T * __objName_static_ptrN;
     451                                                // static T __objName_static_varN;
    454452                                                // void __objName_dtor_atexitN() {
    455                                                 //   __dtor(__objName_static_ptrN);
     453                                                //   __dtor__...;
    456454                                                // }
    457455                                                // int f(...) {
    458456                                                //   ...
    459                                                 //   static T __objName;
    460457                                                //   static bool __objName_uninitialized = true;
    461458                                                //   if (__objName_uninitialized) {
    462                                                 //     __objName_ptr = &__objName;
    463459                                                //     __ctor(__objName);
    464                                                 //     on_exit(__objName_dtor_atexitN, &__objName);
    465460                                                //     __objName_uninitialized = false;
     461                                                //     atexit(__objName_dtor_atexitN);
    466462                                                //   }
    467463                                                //   ...
    468464                                                // }
    469465
    470                                                 static UniqueName ptrNamer( "_static_ptr" );
    471466                                                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 );
    488467
    489468                                                // static bool __objName_uninitialized = true
     
    493472                                                isUninitializedVar->fixUniqueId();
    494473
    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);
    501                                                 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
    502                                                 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
    503 
    504474                                                // __objName_uninitialized = false;
    505475                                                UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) );
     
    511481                                                std::list< Statement * > & body = initStmts->get_kids();
    512482                                                body.push_back( ctor );
    513                                                 body.push_back( new ExprStmt( noLabels, ptrAssign ) );
    514                                                 body.push_back( new ExprStmt( noLabels, callAtexit ) );
    515483                                                body.push_back( new ExprStmt( noLabels, setTrue ) );
    516484
     
    520488                                                stmtsToAddAfter.push_back( ifStmt );
    521489
    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 );
     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                                                }
    525528                                        } else {
    526529                                                stmtsToAddAfter.push_back( ctor );
     
    582585                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    583586                                        Statement * dtor = ctorInit->get_dtor();
    584                                         if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
     587                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    585588                                                // don't need to call intrinsic dtor, because it does nothing, but
    586589                                                // non-intrinsic dtors must be called
  • src/InitTweak/GenInit.cc

    r73bf8cf2 rf9cebb5  
    172172                // if in function, generate const size_t var
    173173                static UniqueName dimensionName( "_array_dim" );
     174
     175                // C doesn't allow variable sized arrays at global scope or for static variables,
     176                // so don't hoist dimension.
     177                if ( ! inFunction ) return;
     178                if ( storageclass == DeclarationNode::Static ) return;
     179
    174180                if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    175                         if ( ! inFunction ) return;
    176 
    177181                        if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
    178182
     
    203207                CtorDtor ctordtor;
    204208                mutateAll( translationUnit, ctordtor );
    205         }
    206 
    207         namespace {
    208                 Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) {
    209                         UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) );
    210                         expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
    211                         expr->get_args().splice( expr->get_args().end(), args );
    212                         return expr;
    213                 }
    214209        }
    215210
  • src/InitTweak/InitTweak.cc

    r73bf8cf2 rf9cebb5  
    55#include "SynTree/Initializer.h"
    66#include "SynTree/Expression.h"
     7#include "SynTree/Attribute.h"
    78#include "GenPoly/GenPoly.h"
    89
     
    125126
    126127        namespace {
     128                /// given index i, dimension d, initializer init, and callExpr f, generates
     129                ///   if (i < d) f(..., init)
     130                ///   ++i;
     131                /// so that only elements within the range of the array are constructed
    127132                template< typename OutIterator >
    128                 void dothething( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
     133                void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
    129134                        UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
    130135                        cond->get_args().push_back( index->clone() );
     
    148153                        Expression * dimension = *idx++;
    149154
     155                        // xxx - may want to eventually issue a warning here if we can detect
     156                        // that the number of elements exceeds to dimension of the array
    150157                        if ( idx == idxEnd ) {
    151158                                if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
    152159                                        for ( Initializer * init : *listInit ) {
    153                                                 dothething( callExpr->clone(), index, dimension, init, out );
     160                                                buildCallExpr( callExpr->clone(), index, dimension, init, out );
    154161                                        }
    155162                                } else {
    156                                         dothething( callExpr->clone(), index, dimension, init, out );
     163                                        buildCallExpr( callExpr->clone(), index, dimension, init, out );
    157164                                }
    158165                        } else {
     
    166173                                        throw SemanticError( "unbalanced list initializers" );
    167174                                }
     175
     176                                static UniqueName targetLabel( "L__autogen__" );
     177                                Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } );
    168178                                for ( Initializer * init : *listInit ) {
    169179                                        Expression * condition;
     
    178188                                        std::list< Statement * > stmts;
    179189                                        build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
     190                                        stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );
    180191                                        CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
    181192                                        branches.push_back( caseStmt );
    182193                                }
    183194                                *out++ = new SwitchStmt( noLabels, index->clone(), branches );
     195                                *out++ = new NullStmt( std::list<Label>{ switchLabel } );
    184196                        }
    185197                }
     
    194206        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    195207                if ( ! init ) return NULL;
    196                 std::list< Statement * > results;
    197                 build( dst, indices.begin(), indices.end(), init, back_inserter( results ) );
    198                 assert( results.size() <= 1 );
    199                 if ( results.empty() ) {
     208                CompoundStmt * block = new CompoundStmt( noLabels );
     209                build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
     210                if ( block->get_kids().empty() ) {
     211                        delete block;
    200212                        return NULL;
    201213                } else {
    202214                        init = NULL; // init was consumed in creating the list init
    203                         return results.front();
    204                 }
    205                 return ! results.empty() ? results.front() : NULL;
     215                        return block;
     216                }
    206217        }
    207218
     
    280291        }
    281292
    282         bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
     293        bool isIntrinsicSingleArgCallStmt( Statement * stmt ) {
    283294                std::list< Expression * > callExprs;
    284295                collectCtorDtorCalls( stmt, callExprs );
  • src/InitTweak/InitTweak.h

    r73bf8cf2 rf9cebb5  
    4141        /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
    4242        /// Currently has assertions that make it less than fully general.
    43         bool isInstrinsicSingleArgCallStmt( Statement * expr );
     43        bool isIntrinsicSingleArgCallStmt( Statement * expr );
    4444
    4545        /// get all Ctor/Dtor call expressions from a Statement
Note: See TracChangeset for help on using the changeset viewer.