Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixGlobalInit.cc

    r0bd3faf r720f2fe2  
    2020#include <algorithm>               // for replace_if
    2121
     22#include "Common/PassVisitor.h"
     23#include "Common/UniqueName.h"     // for UniqueName
     24#include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
     25#include "SynTree/LinkageSpec.h"   // for C
     26#include "SynTree/Attribute.h"     // for Attribute
     27#include "SynTree/Constant.h"      // for Constant
     28#include "SynTree/Declaration.h"   // for FunctionDecl, ObjectDecl, Declaration
     29#include "SynTree/Expression.h"    // for ConstantExpr, Expression (ptr only)
     30#include "SynTree/Initializer.h"   // for ConstructorInit, Initializer
     31#include "SynTree/Label.h"         // for Label
     32#include "SynTree/Statement.h"     // for CompoundStmt, Statement (ptr only)
     33#include "SynTree/Type.h"          // for Type, Type::StorageClasses, Functi...
     34#include "SynTree/Visitor.h"       // for acceptAll, Visitor
     35
    2236#include "AST/Expr.hpp"
    2337#include "AST/Node.hpp"
    2438#include "AST/Pass.hpp"
    25 #include "Common/UniqueName.h"     // for UniqueName
    26 #include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
    2739
    2840namespace InitTweak {
    29         class GlobalFixer : public ast::WithShortCircuiting {
     41        class GlobalFixer : public WithShortCircuiting {
     42          public:
     43                GlobalFixer( bool inLibrary );
     44
     45                void previsit( ObjectDecl *objDecl );
     46                void previsit( FunctionDecl *functionDecl );
     47                void previsit( StructDecl *aggregateDecl );
     48                void previsit( UnionDecl *aggregateDecl );
     49                void previsit( EnumDecl *aggregateDecl );
     50                void previsit( TraitDecl *aggregateDecl );
     51                void previsit( TypeDecl *typeDecl );
     52
     53                UniqueName tempNamer;
     54                FunctionDecl * initFunction;
     55                FunctionDecl * destroyFunction;
     56        };
     57
     58        class GlobalFixer_new : public ast::WithShortCircuiting {
    3059        public:
    3160                void previsit (const ast::ObjectDecl *);
     
    4170        };
    4271
     72        void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ) {
     73                PassVisitor<GlobalFixer> visitor( inLibrary );
     74                acceptAll( translationUnit, visitor );
     75                GlobalFixer & fixer = visitor.pass;
     76                // don't need to include function if it's empty
     77                if ( fixer.initFunction->get_statements()->get_kids().empty() ) {
     78                        delete fixer.initFunction;
     79                } else {
     80                        translationUnit.push_back( fixer.initFunction );
     81                } // if
     82
     83                if ( fixer.destroyFunction->get_statements()->get_kids().empty() ) {
     84                        delete fixer.destroyFunction;
     85                } else {
     86                        translationUnit.push_back( fixer.destroyFunction );
     87                } // if
     88        }
     89
     90        GlobalFixer::GlobalFixer( bool inLibrary ) : tempNamer( "_global_init" ) {
     91                std::list< Expression * > ctorParameters;
     92                std::list< Expression * > dtorParameters;
     93                if ( inLibrary ) {
     94                        // Constructor/destructor attributes take a single parameter which
     95                        // is the priority, with lower numbers meaning higher priority.
     96                        // Functions specified with priority are guaranteed to run before
     97                        // functions without a priority. To ensure that constructors and destructors
     98                        // for library code are run before constructors and destructors for user code,
     99                        // specify a priority when building the library. Priorities 0-100 are reserved by gcc.
     100                        // Priorities 101-200 are reserved by cfa, so use priority 200 for CFA library globals,
     101                        // allowing room for overriding with a higher priority.
     102                        ctorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
     103                        dtorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
     104                }
     105                initFunction = new FunctionDecl( "__global_init__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
     106                initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) );
     107                destroyFunction = new FunctionDecl( "__global_destroy__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
     108                destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) );
     109        }
     110
    43111        void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
    44                 ast::Pass<GlobalFixer> fixer;
     112                ast::Pass<GlobalFixer_new> fixer;
    45113                accept_all(translationUnit, fixer);
    46114
     
    73141        }
    74142
    75         void GlobalFixer::previsit(const ast::ObjectDecl * objDecl) {
     143        void GlobalFixer::previsit( ObjectDecl *objDecl ) {
     144                std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids();
     145                std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
     146
     147                // C allows you to initialize objects with constant expressions
     148                // xxx - this is an optimization. Need to first resolve constructors before we decide
     149                // to keep C-style initializer.
     150                // if ( isConstExpr( objDecl->get_init() ) ) return;
     151
     152                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
     153                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     154                        assert( ! ctorInit->ctor || ! ctorInit->init );
     155
     156                        Statement * dtor = ctorInit->dtor;
     157                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
     158                                // don't need to call intrinsic dtor, because it does nothing, but
     159                                // non-intrinsic dtors must be called
     160                                destroyStatements.push_front( dtor );
     161                                ctorInit->dtor = nullptr;
     162                        } // if
     163                        if ( Statement * ctor = ctorInit->ctor ) {
     164                                addDataSectionAttribute( objDecl );
     165                                initStatements.push_back( ctor );
     166                                objDecl->init = nullptr;
     167                                ctorInit->ctor = nullptr;
     168                        } else if ( Initializer * init = ctorInit->init ) {
     169                                objDecl->init = init;
     170                                ctorInit->init = nullptr;
     171                        } else {
     172                                // no constructor and no initializer, which is okay
     173                                objDecl->init = nullptr;
     174                        } // if
     175                        delete ctorInit;
     176                } // if
     177        }
     178
     179        void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) {
    76180                auto mutDecl = mutate(objDecl);
    77181                assertf(mutDecl == objDecl, "Global object decl must be unique");
     
    103207        }
    104208
     209        // only modify global variables
     210        void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; }
     211        void GlobalFixer::previsit( StructDecl * ) { visit_children = false; }
     212        void GlobalFixer::previsit( UnionDecl * ) { visit_children = false; }
     213        void GlobalFixer::previsit( EnumDecl * ) { visit_children = false; }
     214        void GlobalFixer::previsit( TraitDecl * ) { visit_children = false; }
     215        void GlobalFixer::previsit( TypeDecl * ) { visit_children = false; }
     216
    105217} // namespace InitTweak
    106218
Note: See TracChangeset for help on using the changeset viewer.