Changes in src/InitTweak/FixGlobalInit.cc [0bd3faf:720f2fe2]
- File:
-
- 1 edited
-
src/InitTweak/FixGlobalInit.cc (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixGlobalInit.cc
r0bd3faf r720f2fe2 20 20 #include <algorithm> // for replace_if 21 21 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 22 36 #include "AST/Expr.hpp" 23 37 #include "AST/Node.hpp" 24 38 #include "AST/Pass.hpp" 25 #include "Common/UniqueName.h" // for UniqueName26 #include "InitTweak.h" // for isIntrinsicSingleArgCallStmt27 39 28 40 namespace 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 { 30 59 public: 31 60 void previsit (const ast::ObjectDecl *); … … 41 70 }; 42 71 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 43 111 void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) { 44 ast::Pass<GlobalFixer > fixer;112 ast::Pass<GlobalFixer_new> fixer; 45 113 accept_all(translationUnit, fixer); 46 114 … … 73 141 } 74 142 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) { 76 180 auto mutDecl = mutate(objDecl); 77 181 assertf(mutDecl == objDecl, "Global object decl must be unique"); … … 103 207 } 104 208 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 105 217 } // namespace InitTweak 106 218
Note:
See TracChangeset
for help on using the changeset viewer.