Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixGlobalInit.cc

    r03e5d14 r7b3f66b  
    1010// Created On       : Mon May 04 15:14:56 2016
    1111// Last Modified By : Rob Schluntz
    12 // Last Modified On : Fri May 06 15:40:48 2016
     12// Last Modified On : Fri May 13 11:37:30 2016
    1313// Update Count     : 2
    1414//
    1515
    1616#include "FixGlobalInit.h"
     17#include "InitTweak.h"
    1718#include "SynTree/Declaration.h"
    1819#include "SynTree/Type.h"
     
    4243                UniqueName tempNamer;
    4344                FunctionDecl * initFunction;
     45                FunctionDecl * destroyFunction;
    4446        };
    4547
     
    9092                GlobalFixer fixer( name, inLibrary );
    9193                acceptAll( translationUnit, fixer );
    92                 translationUnit.push_back( fixer.initFunction );
     94                // don't need to include function if it's empty
     95                if ( fixer.initFunction->get_statements()->get_kids().empty() ) {
     96                        delete fixer.initFunction;
     97                } else {
     98                        translationUnit.push_back( fixer.initFunction );
     99                }
     100                if ( fixer.destroyFunction->get_statements()->get_kids().empty() ) {
     101                        delete fixer.destroyFunction;
     102                } else {
     103                        translationUnit.push_back( fixer.destroyFunction );
     104                }
    93105        }
    94106
    95   std::string initName( const std::string & name ) {
     107  std::string globalFunctionName( const std::string & name ) {
    96108        // get basename
    97109        std::string ret = name.substr( 0, name.find( '.' ) );
     
    99111                static std::string invalid = "/-";
    100112        replace_if( ret.begin(), ret.end(), []( char c ) { return invalid.find(c) != std::string::npos; }, '_' );
    101         return "_init_" + ret;
     113        return ret;
    102114  }
    103115
    104116        GlobalFixer::GlobalFixer( const std::string & name, bool inLibrary ) : tempNamer( "_global_init" ) {
    105                 initFunction = new FunctionDecl( initName( name ), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Constructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) );
     117                std::string fixedName = globalFunctionName( name );
     118                initFunction = new FunctionDecl( "_init_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Constructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) );
     119
     120                destroyFunction = new FunctionDecl( "_destroy_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Destructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) );
    106121        }
    107122
    108123        void GlobalFixer::visit( ObjectDecl *objDecl ) {
    109                 std::list< Statement * > & statements = initFunction->get_statements()->get_kids();
     124                std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids();
     125                std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
    110126
    111                 if ( objDecl->get_init() == NULL ) return;
     127                // if ( objDecl->get_init() == NULL ) return;
     128                if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
    112129                if ( objDecl->get_type()->get_isConst() ) return; // temporary: can't assign to a const variable
     130                if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
    113131                // C allows you to initialize objects with constant expressions
    114132                // xxx - this is an optimization. Need to first resolve constructors before we decide
     
    116134                // if ( isConstExpr( objDecl->get_init() ) ) return;
    117135
    118                 // steal initializer from object and attach it to a new temporary
    119                 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, objDecl->get_type()->clone(), objDecl->get_init() );
    120                 objDecl->set_init( NULL );
    121                 statements.push_back( new DeclStmt( noLabels, newObj ) );
     136                if ( ArrayType * at = dynamic_cast< ArrayType * > ( objDecl->get_type() ) ) {
     137                        // xxx - initialize each element of the array
     138                } else {
     139                        // steal initializer from object and attach it to a new temporary
     140                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, objDecl->get_type()->clone(), objDecl->get_init() );
     141                        objDecl->set_init( NULL );
     142                        initStatements.push_back( new DeclStmt( noLabels, newObj ) );
    122143
    123                 // assign (later: copy construct) objDecl using temporary
    124                 UntypedExpr * init = new UntypedExpr( new NameExpr( "?=?" ) );
    125                 init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
    126                 init->get_args().push_back( new VariableExpr( newObj ) );
    127                 statements.push_back( new ExprStmt( noLabels, init ) );
     144                        // copy construct objDecl using temporary
     145                        UntypedExpr * init = new UntypedExpr( new NameExpr( "?{}" ) );
     146                        init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
     147                        init->get_args().push_back( new VariableExpr( newObj ) );
     148                        initStatements.push_back( new ExprStmt( noLabels, init ) );
    128149
    129                 // xxx- need to destruct objDecl atexit
     150                        // add destructor calls to global destroy function
     151                        UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) );
     152                        destroy->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
     153                        destroyStatements.push_front( new ExprStmt( noLabels, destroy ) );
     154                }
    130155        }
    131156
Note: See TracChangeset for help on using the changeset viewer.