Changes in src/InitTweak/FixGlobalInit.cc [293dc1c:6fbe9a5]
- File:
-
- 1 edited
-
src/InitTweak/FixGlobalInit.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixGlobalInit.cc
r293dc1c r6fbe9a5 34 34 #include "SynTree/Visitor.h" // for acceptAll, Visitor 35 35 36 #include "AST/Expr.hpp"37 #include "AST/Node.hpp"38 #include "AST/Pass.hpp"39 40 36 namespace InitTweak { 41 37 class GlobalFixer : public WithShortCircuiting { … … 54 50 FunctionDecl * initFunction; 55 51 FunctionDecl * destroyFunction; 56 };57 58 class GlobalFixer_new : public ast::WithShortCircuiting {59 public:60 void previsit (const ast::ObjectDecl *);61 void previsit (const ast::FunctionDecl *) { visit_children = false; }62 void previsit (const ast::StructDecl *) { visit_children = false; }63 void previsit (const ast::UnionDecl *) { visit_children = false; }64 void previsit (const ast::EnumDecl *) { visit_children = false; }65 void previsit (const ast::TraitDecl *) { visit_children = false; }66 void previsit (const ast::TypeDecl *) { visit_children = false; }67 68 std::list< ast::ptr<ast::Stmt> > initStmts;69 std::list< ast::ptr<ast::Stmt> > destroyStmts;70 52 }; 71 53 … … 109 91 } 110 92 111 void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {112 ast::Pass<GlobalFixer_new> fixer;113 accept_all(translationUnit, fixer);114 115 if ( !fixer.core.initStmts.empty() ) {116 std::vector<ast::ptr<ast::Expr>> ctorParams;117 if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));118 auto initFunction = new ast::FunctionDecl({}, "__global_init__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.initStmts)),119 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("constructor", std::move(ctorParams))});120 121 translationUnit.decls.emplace_back( initFunction );122 } // if123 124 if ( !fixer.core.destroyStmts.empty() ) {125 std::vector<ast::ptr<ast::Expr>> dtorParams;126 if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));127 auto destroyFunction = new ast::FunctionDecl({}, "__global_destroy__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.destroyStmts)),128 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("destructor", std::move(dtorParams))});129 130 translationUnit.decls.emplace_back(destroyFunction);131 } // if132 }133 134 93 void GlobalFixer::previsit( ObjectDecl *objDecl ) { 135 94 std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids(); … … 153 112 } // if 154 113 if ( Statement * ctor = ctorInit->ctor ) { 155 addDataSectonAttribute( objDecl ); 114 // Translation 1: Add this attribute on the global declaration: 115 // __attribute__((section (".data#"))) 116 // which makes gcc put the global in the data section, 117 // so that the global is writeable (via a const cast) in the init function. 118 // The trailing # is an injected assembly comment, to suppress the "a" in 119 // .section .data,"a" 120 // .section .data#,"a" 121 // to avoid assembler warning "ignoring changed section attributes for .data" 122 Type *strLitT = new PointerType( Type::Qualifiers( ), 123 new BasicType( Type::Qualifiers( ), BasicType::Char ) ); 124 std::list< Expression * > attr_params; 125 attr_params.push_back( 126 new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) ); 127 objDecl->attributes.push_back(new Attribute("section", attr_params)); 128 // Translation 2: Move the initizliation off the global declaration, 129 // into the startup function. 156 130 initStatements.push_back( ctor ); 157 131 objDecl->init = nullptr; … … 165 139 } // if 166 140 delete ctorInit; 167 } // if168 }169 170 void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) {171 auto mutDecl = mutate(objDecl);172 assertf(mutDecl == objDecl, "Global object decl must be unique");173 if ( auto ctorInit = objDecl->init.as<ast::ConstructorInit>() ) {174 // a decision should have been made by the resolver, so ctor and init are not both non-NULL175 assert( ! ctorInit->ctor || ! ctorInit->init );176 177 const ast::Stmt * dtor = ctorInit->dtor;178 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {179 // don't need to call intrinsic dtor, because it does nothing, but180 // non-intrinsic dtors must be called181 destroyStmts.push_front( dtor );182 // ctorInit->dtor = nullptr;183 } // if184 if ( const ast::Stmt * ctor = ctorInit->ctor ) {185 initStmts.push_back( ctor );186 mutDecl->init = nullptr;187 // ctorInit->ctor = nullptr;188 } else if ( const ast::Init * init = ctorInit->init ) {189 mutDecl->init = init;190 // ctorInit->init = nullptr;191 } else {192 // no constructor and no initializer, which is okay193 mutDecl->init = nullptr;194 } // if195 // delete ctorInit;196 141 } // if 197 142 }
Note:
See TracChangeset
for help on using the changeset viewer.