Changeset c28ea4e for src/InitTweak
- Timestamp:
- Nov 4, 2020, 2:56:30 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- eeb5023
- Parents:
- 4b30e8cc (diff), a3f5208a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src/InitTweak
- Files:
-
- 1 added
- 9 edited
-
FixGlobalInit.cc (modified) (5 diffs)
-
FixGlobalInit.h (modified) (2 diffs)
-
FixInit.cc (modified) (2 diffs)
-
FixInit.h (modified) (1 diff)
-
FixInitNew.cpp (added)
-
GenInit.cc (modified) (1 diff)
-
GenInit.h (modified) (1 diff)
-
InitTweak.cc (modified) (7 diffs)
-
InitTweak.h (modified) (4 diffs)
-
module.mk (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixGlobalInit.cc
r4b30e8cc rc28ea4e 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 36 40 namespace InitTweak { 37 41 class GlobalFixer : public WithShortCircuiting { … … 50 54 FunctionDecl * initFunction; 51 55 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; 52 70 }; 53 71 … … 91 109 } 92 110 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 } // if 123 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 } // if 132 } 133 93 134 void GlobalFixer::previsit( ObjectDecl *objDecl ) { 94 135 std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids(); … … 112 153 } // if 113 154 if ( Statement * ctor = ctorInit->ctor ) { 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. 155 addDataSectonAttribute( objDecl ); 130 156 initStatements.push_back( ctor ); 131 157 objDecl->init = nullptr; … … 142 168 } 143 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-NULL 175 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, but 180 // non-intrinsic dtors must be called 181 destroyStmts.push_front( dtor ); 182 // ctorInit->dtor = nullptr; 183 } // if 184 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 okay 193 mutDecl->init = nullptr; 194 } // if 195 // delete ctorInit; 196 } // if 197 } 198 144 199 // only modify global variables 145 200 void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; } -
src/InitTweak/FixGlobalInit.h
r4b30e8cc rc28ea4e 19 19 #include <string> // for string 20 20 21 #include <AST/Fwd.hpp> 22 23 21 24 class Declaration; 22 25 … … 26 29 /// function is for library code. 27 30 void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ); 31 void fixGlobalInit( ast::TranslationUnit & translationUnit, bool inLibrary ); 28 32 } // namespace 29 33 -
src/InitTweak/FixInit.cc
r4b30e8cc rc28ea4e 219 219 }; 220 220 221 struct SplitExpressions : public WithShortCircuiting, public WithTypeSubstitution,public WithStmtsToAdd {221 struct SplitExpressions : public WithShortCircuiting, /*public WithTypeSubstitution, */public WithStmtsToAdd { 222 222 /// add CompoundStmts around top-level expressions so that temporaries are destroyed in the correct places. 223 223 static void split( std::list< Declaration * > &translationUnit ); … … 802 802 if ( Statement * ctor = ctorInit->get_ctor() ) { 803 803 if ( objDecl->get_storageClasses().is_static ) { 804 805 // The ojbect needs to go in the data section, regardless of dtor complexity below. 806 // The attribute works, and is meant to apply, both for leaving the static local alone, 807 // and for hoisting it out as a static global. 808 addDataSectonAttribute( objDecl ); 809 804 810 // originally wanted to take advantage of gcc nested functions, but 805 811 // we get memory errors with this approach. To remedy this, the static -
src/InitTweak/FixInit.h
r4b30e8cc rc28ea4e 20 20 21 21 class Declaration; 22 namespace ast { 23 class TranslationUnit; 24 } 22 25 23 26 namespace InitTweak { 24 27 /// replace constructor initializers with expression statements and unwrap basic C-style initializers 25 28 void fix( std::list< Declaration * > & translationUnit, bool inLibrary ); 29 30 void fix( ast::TranslationUnit & translationUnit, bool inLibrary); 26 31 } // namespace 27 32 -
src/InitTweak/GenInit.cc
r4b30e8cc rc28ea4e 283 283 assert( stmts.size() <= 1 ); 284 284 return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr; 285 286 } 287 288 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) { 289 assertf(objDecl, "genCtorDtor passed null objDecl"); 290 InitExpander_new srcParam(arg); 291 return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl); 285 292 } 286 293 -
src/InitTweak/GenInit.h
r4b30e8cc rc28ea4e 33 33 /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument 34 34 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr ); 35 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr); 35 36 36 37 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer -
src/InitTweak/InitTweak.cc
r4b30e8cc rc28ea4e 498 498 } 499 499 500 const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) { 501 assertf( func, "getParamThis: nullptr ftype" ); 502 auto & params = func->params; 503 assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str()); 504 return params.front().strict_as<ast::ObjectDecl>(); 505 } 506 500 507 bool tryConstruct( DeclarationWithType * dwt ) { 501 508 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt ); … … 511 518 } 512 519 520 bool tryConstruct( const ast::DeclWithType * dwt ) { 521 auto objDecl = dynamic_cast< const ast::ObjectDecl * >( dwt ); 522 if ( ! objDecl ) return false; 523 return (objDecl->init == nullptr || 524 ( objDecl->init != nullptr && objDecl->init->maybeConstructed )) 525 && ! objDecl->storage.is_extern 526 && isConstructable( objDecl->type ); 527 } 528 529 bool isConstructable( const ast::Type * type ) { 530 return ! dynamic_cast< const ast::VarArgsType * >( type ) && ! dynamic_cast< const ast::ReferenceType * >( type ) 531 && ! dynamic_cast< const ast::FunctionType * >( type ) && ! Tuples::isTtype( type ); 532 } 533 513 534 struct CallFinder_old { 514 535 CallFinder_old( const std::list< std::string > & names ) : names( names ) {} … … 536 557 537 558 struct CallFinder_new final { 538 std::vector< ast::ptr< ast::Expr >> matches;559 std::vector< const ast::Expr * > matches; 539 560 const std::vector< std::string > names; 540 561 … … 558 579 } 559 580 560 std::vector< ast::ptr< ast::Expr >> collectCtorDtorCalls( const ast::Stmt * stmt ) {581 std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) { 561 582 ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } }; 562 583 maybe_accept( stmt, finder ); … … 696 717 template <typename Predicate> 697 718 bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) { 698 std::vector< ast::ptr< ast::Expr >> callExprs = collectCtorDtorCalls( stmt );719 std::vector< const ast::Expr * > callExprs = collectCtorDtorCalls( stmt ); 699 720 return std::all_of( callExprs.begin(), callExprs.end(), pred ); 700 721 } … … 939 960 } 940 961 962 // looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards 963 // following passes may accidentally resolve this expression if returned as untyped... 964 ast::Expr * createBitwiseAssignment (const ast::Expr * dst, const ast::Expr * src) { 965 static ast::ptr<ast::FunctionDecl> assign = nullptr; 966 if (!assign) { 967 auto td = new ast::TypeDecl({}, "T", {}, nullptr, ast::TypeDecl::Dtype, true); 968 assign = new ast::FunctionDecl({}, "?=?", {}, 969 { new ast::ObjectDecl({}, "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))), 970 new ast::ObjectDecl({}, "_src", new ast::TypeInstType("T", td))}, 971 { new ast::ObjectDecl({}, "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic); 972 } 973 if (dst->result.as<ast::ReferenceType>()) { 974 for (int depth = dst->result->referenceDepth(); depth > 0; depth--) { 975 dst = new ast::AddressExpr(dst); 976 } 977 } 978 else { 979 dst = new ast::CastExpr(dst, new ast::ReferenceType(dst->result, {})); 980 } 981 if (src->result.as<ast::ReferenceType>()) { 982 for (int depth = src->result->referenceDepth(); depth > 0; depth--) { 983 src = new ast::AddressExpr(src); 984 } 985 } 986 return new ast::ApplicationExpr(dst->location, ast::VariableExpr::functionPointer(dst->location, assign), {dst, src}); 987 } 988 941 989 struct ConstExprChecker : public WithShortCircuiting { 942 990 // most expressions are not const expr … … 1055 1103 return isCopyFunction( decl, "?{}" ); 1056 1104 } 1105 1106 void addDataSectonAttribute( ObjectDecl * objDecl ) { 1107 Type *strLitT = new PointerType( Type::Qualifiers( ), 1108 new BasicType( Type::Qualifiers( ), BasicType::Char ) ); 1109 std::list< Expression * > attr_params; 1110 attr_params.push_back( 1111 new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) ); 1112 objDecl->attributes.push_back(new Attribute("section", attr_params)); 1113 } 1114 1057 1115 } -
src/InitTweak/InitTweak.h
r4b30e8cc rc28ea4e 38 38 /// returns the first parameter of a constructor/destructor/assignment function 39 39 ObjectDecl * getParamThis( FunctionType * ftype ); 40 const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func); 40 41 41 42 /// generate a bitwise assignment operation. 42 43 ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src ); 44 45 ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src); 43 46 44 47 /// transform Initializer into an argument list that can be passed to a call expression … … 48 51 /// True if the resolver should try to construct dwt 49 52 bool tryConstruct( DeclarationWithType * dwt ); 53 bool tryConstruct( const ast::DeclWithType * dwt ); 50 54 51 55 /// True if the type can have a user-defined constructor 52 56 bool isConstructable( Type * t ); 57 bool isConstructable( const ast::Type * t ); 53 58 54 59 /// True if the Initializer contains designations … … 79 84 /// get all Ctor/Dtor call expressions from a Statement 80 85 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ); 81 std::vector< ast::ptr< ast::Expr >> collectCtorDtorCalls( const ast::Stmt * stmt );86 std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ); 82 87 83 88 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call … … 102 107 bool isConstExpr( Expression * expr ); 103 108 bool isConstExpr( Initializer * init ); 109 110 /// Modifies objDecl to have: 111 /// __attribute__((section (".data#"))) 112 /// which makes gcc put the declared variable in the data section, 113 /// which is helpful for global constants on newer gcc versions, 114 /// so that CFA's generated initialization won't segfault when writing it via a const cast. 115 /// The trailing # is an injected assembly comment, to suppress the "a" in 116 /// .section .data,"a" 117 /// .section .data#,"a" 118 /// to avoid assembler warning "ignoring changed section attributes for .data" 119 void addDataSectonAttribute( ObjectDecl * objDecl ); 104 120 105 121 class InitExpander_old { -
src/InitTweak/module.mk
r4b30e8cc rc28ea4e 23 23 InitTweak/GenInit.h \ 24 24 InitTweak/InitTweak.cc \ 25 InitTweak/InitTweak.h 25 InitTweak/InitTweak.h \ 26 InitTweak/FixInitNew.cpp 26 27 27 28 SRCDEMANGLE += \
Note:
See TracChangeset
for help on using the changeset viewer.