Changeset c6b4432 for src/InitTweak/FixGlobalInit.cc
- Timestamp:
- Nov 8, 2023, 2:01:11 PM (8 months ago)
- Branches:
- master
- Children:
- 3e4bf0d, f5ec35a
- Parents:
- 790d835
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixGlobalInit.cc
r790d835 rc6b4432 20 20 #include <algorithm> // for replace_if 21 21 22 #include "Common/PassVisitor.h"23 #include "Common/UniqueName.h" // for UniqueName24 #include "InitTweak.h" // for isIntrinsicSingleArgCallStmt25 #include "SynTree/LinkageSpec.h" // for C26 #include "SynTree/Attribute.h" // for Attribute27 #include "SynTree/Constant.h" // for Constant28 #include "SynTree/Declaration.h" // for FunctionDecl, ObjectDecl, Declaration29 #include "SynTree/Expression.h" // for ConstantExpr, Expression (ptr only)30 #include "SynTree/Initializer.h" // for ConstructorInit, Initializer31 #include "SynTree/Label.h" // for Label32 #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, Visitor35 36 22 #include "AST/Expr.hpp" 37 23 #include "AST/Node.hpp" 38 24 #include "AST/Pass.hpp" 25 #include "Common/UniqueName.h" // for UniqueName 26 #include "InitTweak.h" // for isIntrinsicSingleArgCallStmt 39 27 40 28 namespace InitTweak { 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 29 class GlobalFixer_new : public ast::WithShortCircuiting { 59 30 public: … … 69 40 std::list< ast::ptr<ast::Stmt> > destroyStmts; 70 41 }; 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 empty77 if ( fixer.initFunction->get_statements()->get_kids().empty() ) {78 delete fixer.initFunction;79 } else {80 translationUnit.push_back( fixer.initFunction );81 } // if82 83 if ( fixer.destroyFunction->get_statements()->get_kids().empty() ) {84 delete fixer.destroyFunction;85 } else {86 translationUnit.push_back( fixer.destroyFunction );87 } // if88 }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 which95 // is the priority, with lower numbers meaning higher priority.96 // Functions specified with priority are guaranteed to run before97 // functions without a priority. To ensure that constructors and destructors98 // 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 42 111 43 void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) { … … 141 73 } 142 74 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 expressions148 // xxx - this is an optimization. Need to first resolve constructors before we decide149 // 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-NULL154 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, but159 // non-intrinsic dtors must be called160 destroyStatements.push_front( dtor );161 ctorInit->dtor = nullptr;162 } // if163 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 okay173 objDecl->init = nullptr;174 } // if175 delete ctorInit;176 } // if177 }178 179 75 void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) { 180 76 auto mutDecl = mutate(objDecl); … … 207 103 } 208 104 209 // only modify global variables210 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 217 105 } // namespace InitTweak 218 106
Note: See TracChangeset
for help on using the changeset viewer.