Changeset 490fb92e for src/InitTweak
- Timestamp:
- Oct 23, 2020, 9:06:16 PM (3 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 37b7d95
- Parents:
- 41b8ea4
- Location:
- src/InitTweak
- Files:
-
- 1 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixGlobalInit.cc
r41b8ea4 r490fb92e 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(std::list<ast::ptr<ast::Decl>> & 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.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.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(); … … 126 167 } 127 168 169 void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) { 170 auto mutDecl = mutate(objDecl); 171 assertf(mutDecl == objDecl, "Global object decl must be unique"); 172 if ( auto ctorInit = objDecl->init.as<ast::ConstructorInit>() ) { 173 // a decision should have been made by the resolver, so ctor and init are not both non-NULL 174 assert( ! ctorInit->ctor || ! ctorInit->init ); 175 176 const ast::Stmt * dtor = ctorInit->dtor; 177 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 178 // don't need to call intrinsic dtor, because it does nothing, but 179 // non-intrinsic dtors must be called 180 destroyStmts.push_front( dtor ); 181 // ctorInit->dtor = nullptr; 182 } // if 183 if ( const ast::Stmt * ctor = ctorInit->ctor ) { 184 initStmts.push_back( ctor ); 185 mutDecl->init = nullptr; 186 // ctorInit->ctor = nullptr; 187 } else if ( const ast::Init * init = ctorInit->init ) { 188 mutDecl->init = init; 189 // ctorInit->init = nullptr; 190 } else { 191 // no constructor and no initializer, which is okay 192 mutDecl->init = nullptr; 193 } // if 194 // delete ctorInit; 195 } // if 196 } 197 128 198 // only modify global variables 129 199 void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; } -
src/InitTweak/FixGlobalInit.h
r41b8ea4 r490fb92e 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( std::list< ast::ptr<ast::Decl> > & translationUnit, bool inLibrary ); 28 32 } // namespace 29 33 -
src/InitTweak/FixInit.cc
r41b8ea4 r490fb92e 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 ); -
src/InitTweak/FixInit.h
r41b8ea4 r490fb92e 19 19 #include <string> // for string 20 20 21 #include <AST/Fwd.hpp> 22 21 23 class Declaration; 22 24 … … 24 26 /// replace constructor initializers with expression statements and unwrap basic C-style initializers 25 27 void fix( std::list< Declaration * > & translationUnit, bool inLibrary ); 28 29 void fix( std::list<ast::ptr<ast::Decl>> & translationUnit, bool inLibrary); 26 30 } // namespace 27 31 -
src/InitTweak/GenInit.cc
r41b8ea4 r490fb92e 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
r41b8ea4 r490fb92e 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
r41b8ea4 r490fb92e 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 -
src/InitTweak/InitTweak.h
r41b8ea4 r490fb92e 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 -
src/InitTweak/module.mk
r41b8ea4 r490fb92e 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.