Changeset eef8dfb for src/InitTweak
- Timestamp:
- Jan 7, 2021, 2:55:57 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, stuck-waitfor-destruct
- Children:
- 58fe85a
- Parents:
- bdfc032 (diff), 44e37ef (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) (4 diffs)
-
FixInit.h (modified) (2 diffs)
-
FixInitNew.cpp (added)
-
GenInit.cc (modified) (8 diffs)
-
GenInit.h (modified) (2 diffs)
-
InitTweak.cc (modified) (13 diffs)
-
InitTweak.h (modified) (4 diffs)
-
module.mk (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixGlobalInit.cc
rbdfc032 reef8dfb 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 ) { 155 addDataSectonAttribute( objDecl ); 114 156 initStatements.push_back( ctor ); 115 157 objDecl->init = nullptr; … … 126 168 } 127 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 addDataSectionAttribute(mutDecl); 186 initStmts.push_back( ctor ); 187 mutDecl->init = nullptr; 188 // ctorInit->ctor = nullptr; 189 } else if ( const ast::Init * init = ctorInit->init ) { 190 mutDecl->init = init; 191 // ctorInit->init = nullptr; 192 } else { 193 // no constructor and no initializer, which is okay 194 mutDecl->init = nullptr; 195 } // if 196 // delete ctorInit; 197 } // if 198 } 199 128 200 // only modify global variables 129 201 void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; } -
src/InitTweak/FixGlobalInit.h
rbdfc032 reef8dfb 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
rbdfc032 reef8dfb 10 10 // Created On : Wed Jan 13 16:29:30 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 13 23:41:27 201913 // Update Count : 7712 // Last Modified On : Sun Feb 16 04:17:07 2020 13 // Update Count : 82 14 14 // 15 15 #include "FixInit.h" … … 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 ); … … 745 745 } 746 746 747 // to prevent warnings ( ‘_unq0’may be used uninitialized in this function),747 // to prevent warnings ('_unq0' may be used uninitialized in this function), 748 748 // insert an appropriate zero initializer for UniqueExpr temporaries. 749 749 Initializer * makeInit( Type * t ) { … … 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
rbdfc032 reef8dfb 10 10 // Created On : Wed Jan 13 16:29:30 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : S at Jul 22 09:31:06 201713 // Update Count : 612 // Last Modified On : Sun Feb 16 07:54:50 2020 13 // Update Count : 8 14 14 // 15 15 … … 20 20 21 21 class Declaration; 22 namespace ast { 23 struct TranslationUnit; 24 } 22 25 23 26 namespace InitTweak { 24 /// replace constructor initializers with expression statements 25 /// and unwrap basic C-style initializers 27 /// replace constructor initializers with expression statements and unwrap basic C-style initializers 26 28 void fix( std::list< Declaration * > & translationUnit, bool inLibrary ); 29 30 void fix( ast::TranslationUnit & translationUnit, bool inLibrary); 27 31 } // namespace 28 32 -
src/InitTweak/GenInit.cc
rbdfc032 reef8dfb 26 26 #include "AST/Node.hpp" 27 27 #include "AST/Stmt.hpp" 28 #include "CompilationState.h" 28 29 #include "CodeGen/OperatorTable.h" 29 30 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... … … 121 122 }; 122 123 124 struct HoistArrayDimension_NoResolve final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards { 125 /// hoist dimension from array types in object declaration so that it uses a single 126 /// const variable of type size_t, so that side effecting array dimensions are only 127 /// computed once. 128 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 129 130 void premutate( ObjectDecl * objectDecl ); 131 DeclarationWithType * postmutate( ObjectDecl * objectDecl ); 132 void premutate( FunctionDecl *functionDecl ); 133 // should not traverse into any of these declarations to find objects 134 // that need to be constructed or destructed 135 void premutate( AggregateDecl * ) { visit_children = false; } 136 void premutate( NamedTypeDecl * ) { visit_children = false; } 137 void premutate( FunctionType * ) { visit_children = false; } 138 139 void hoist( Type * type ); 140 141 Type::StorageClasses storageClasses; 142 bool inFunction = false; 143 }; 144 123 145 void genInit( std::list< Declaration * > & translationUnit ) { 146 if (!useNewAST) { 147 HoistArrayDimension::hoistArrayDimension( translationUnit ); 148 } 149 else { 150 HoistArrayDimension_NoResolve::hoistArrayDimension( translationUnit ); 151 } 124 152 fixReturnStatements( translationUnit ); 125 HoistArrayDimension::hoistArrayDimension( translationUnit ); 126 CtorDtor::generateCtorDtor( translationUnit ); 153 154 if (!useNewAST) { 155 CtorDtor::generateCtorDtor( translationUnit ); 156 } 127 157 } 128 158 … … 196 226 arrayType->isVarLen = ! isConstExpr( arrayType->dimension ); 197 227 // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects. 228 // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve 229 // still try to detect constant expressions 198 230 if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 199 231 … … 210 242 211 243 void HoistArrayDimension::premutate( FunctionDecl * ) { 244 GuardValue( inFunction ); 245 inFunction = true; 246 } 247 248 // precompute array dimension expression, because constructor generation may duplicate it, 249 // which would be incorrect if it is a side-effecting computation. 250 void HoistArrayDimension_NoResolve::hoistArrayDimension( std::list< Declaration * > & translationUnit ) { 251 PassVisitor<HoistArrayDimension_NoResolve> hoister; 252 mutateAll( translationUnit, hoister ); 253 } 254 255 void HoistArrayDimension_NoResolve::premutate( ObjectDecl * objectDecl ) { 256 GuardValue( storageClasses ); 257 storageClasses = objectDecl->get_storageClasses(); 258 } 259 260 DeclarationWithType * HoistArrayDimension_NoResolve::postmutate( ObjectDecl * objectDecl ) { 261 hoist( objectDecl->get_type() ); 262 return objectDecl; 263 } 264 265 void HoistArrayDimension_NoResolve::hoist( Type * type ) { 266 // if in function, generate const size_t var 267 static UniqueName dimensionName( "_array_dim" ); 268 269 // C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension. 270 if ( ! inFunction ) return; 271 if ( storageClasses.is_static ) return; 272 273 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 274 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist? 275 // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects. 276 // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve 277 // still try to detect constant expressions 278 if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return; 279 280 ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) ); 281 arrayDimension->get_type()->set_const( true ); 282 283 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 284 declsToAddBefore.push_back( arrayDimension ); 285 286 hoist( arrayType->get_base() ); 287 return; 288 } 289 } 290 291 void HoistArrayDimension_NoResolve::premutate( FunctionDecl * ) { 212 292 GuardValue( inFunction ); 213 293 inFunction = true; … … 245 325 } 246 326 327 // why is this not just on FunctionDecl? 247 328 void ManagedTypes::handleDWT( DeclarationWithType * dwt ) { 248 329 // if this function is a user-defined constructor or destructor, mark down the type as "managed" … … 275 356 void ManagedTypes::endScope() { managedTypes.endScope(); } 276 357 358 bool ManagedTypes_new::isManaged( const ast::Type * type ) const { 359 // references are never constructed 360 if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false; 361 if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) { 362 // tuple is also managed if any of its components are managed 363 for (auto & component : tupleType->types) { 364 if (isManaged(component)) return true; 365 } 366 } 367 // need to clear and reset qualifiers when determining if a type is managed 368 // ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() ); 369 auto tmp = shallowCopy(type); 370 tmp->qualifiers = {}; 371 // delete tmp at return 372 ast::ptr<ast::Type> guard = tmp; 373 // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable) 374 return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp ); 375 } 376 377 bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const { 378 const ast::Type * type = objDecl->type; 379 while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) { 380 // must always construct VLAs with an initializer, since this is an error in C 381 if ( at->isVarLen && objDecl->init ) return true; 382 type = at->base; 383 } 384 return isManaged( type ); 385 } 386 387 void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) { 388 // if this function is a user-defined constructor or destructor, mark down the type as "managed" 389 if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) { 390 auto & params = GenPoly::getFunctionType( dwt->get_type())->params; 391 assert( ! params.empty() ); 392 // Type * type = InitTweak::getPointerBase( params.front() ); 393 // assert( type ); 394 managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ); 395 } 396 } 397 398 void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) { 399 // don't construct members, but need to take note if there is a managed member, 400 // because that means that this type is also managed 401 for ( auto & member : aggregateDecl->members ) { 402 if ( auto field = member.as<ast::ObjectDecl>() ) { 403 if ( isManaged( field ) ) { 404 // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that 405 // polymorphic constructors make generic types managed types 406 ast::StructInstType inst( aggregateDecl ); 407 managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ); 408 break; 409 } 410 } 411 } 412 } 413 414 void ManagedTypes_new::beginScope() { managedTypes.beginScope(); } 415 void ManagedTypes_new::endScope() { managedTypes.endScope(); } 416 277 417 ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) { 278 418 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor … … 283 423 assert( stmts.size() <= 1 ); 284 424 return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr; 425 426 } 427 428 ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) { 429 assertf(objDecl, "genCtorDtor passed null objDecl"); 430 InitExpander_new srcParam(arg); 431 return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl); 285 432 } 286 433 … … 363 510 // constructable object 364 511 InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr }; 512 ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl); 365 513 366 514 ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall( 367 srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );515 srcParam, dstParam, loc, "?{}", objDecl ); 368 516 ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall( 369 nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl,517 nullParam, dstParam, loc, "^?{}", objDecl, 370 518 SymTab::LoopBackward ); 371 519 -
src/InitTweak/GenInit.h
rbdfc032 reef8dfb 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 … … 51 52 GenPoly::ScopedSet< std::string > managedTypes; 52 53 }; 54 55 class ManagedTypes_new { 56 public: 57 bool isManaged( const ast::ObjectDecl * objDecl ) const ; // determine if object is managed 58 bool isManaged( const ast::Type * type ) const; // determine if type is managed 59 60 void handleDWT( const ast::DeclWithType * dwt ); // add type to managed if ctor/dtor 61 void handleStruct( const ast::StructDecl * aggregateDecl ); // add type to managed if child is managed 62 63 void beginScope(); 64 void endScope(); 65 private: 66 GenPoly::ScopedSet< std::string > managedTypes; 67 }; 53 68 } // namespace 54 69 -
src/InitTweak/InitTweak.cc
rbdfc032 reef8dfb 87 87 }; 88 88 89 struct HasDesignations_new : public ast::WithShortCircuiting { 90 bool result = false; 91 92 void previsit( const ast::Node * ) { 93 // short circuit if we already know there are designations 94 if ( result ) visit_children = false; 95 } 96 97 void previsit( const ast::Designation * des ) { 98 // short circuit if we already know there are designations 99 if ( result ) visit_children = false; 100 else if ( ! des->designators.empty() ) { 101 result = true; 102 visit_children = false; 103 } 104 } 105 }; 106 107 struct InitDepthChecker_new : public ast::WithGuards { 108 bool result = true; 109 const ast::Type * type; 110 int curDepth = 0, maxDepth = 0; 111 InitDepthChecker_new( const ast::Type * type ) : type( type ) { 112 const ast::Type * t = type; 113 while ( auto at = dynamic_cast< const ast::ArrayType * >( t ) ) { 114 maxDepth++; 115 t = at->base; 116 } 117 maxDepth++; 118 } 119 void previsit( ListInit * ) { 120 curDepth++; 121 GuardAction( [this]() { curDepth--; } ); 122 if ( curDepth > maxDepth ) result = false; 123 } 124 }; 125 89 126 struct InitFlattener_old : public WithShortCircuiting { 90 127 void previsit( SingleInit * singleInit ) { … … 124 161 } 125 162 163 bool isDesignated( const ast::Init * init ) { 164 ast::Pass<HasDesignations_new> finder; 165 maybe_accept( init, finder ); 166 return finder.core.result; 167 } 168 169 bool checkInitDepth( const ast::ObjectDecl * objDecl ) { 170 ast::Pass<InitDepthChecker_new> checker( objDecl->type ); 171 maybe_accept( objDecl->init.get(), checker ); 172 return checker.core.result; 173 } 174 126 175 std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) { 127 176 ast::Pass< InitFlattener_new > flattener; 128 177 maybe_accept( init, flattener ); 129 return std::move( flattener. pass.argList );178 return std::move( flattener.core.argList ); 130 179 } 131 180 … … 358 407 if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) { 359 408 for ( const ast::Init * init : *listInit ) { 360 buildCallExpr( callExpr, index, dimension, init, out );409 buildCallExpr( shallowCopy(callExpr), index, dimension, init, out ); 361 410 } 362 411 } else { 363 buildCallExpr( callExpr, index, dimension, init, out );412 buildCallExpr( shallowCopy(callExpr), index, dimension, init, out ); 364 413 } 365 414 } else { … … 498 547 } 499 548 549 const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) { 550 assertf( func, "getParamThis: nullptr ftype" ); 551 auto & params = func->params; 552 assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str()); 553 return params.front().strict_as<ast::ObjectDecl>(); 554 } 555 500 556 bool tryConstruct( DeclarationWithType * dwt ) { 501 557 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt ); … … 511 567 } 512 568 569 bool tryConstruct( const ast::DeclWithType * dwt ) { 570 auto objDecl = dynamic_cast< const ast::ObjectDecl * >( dwt ); 571 if ( ! objDecl ) return false; 572 return (objDecl->init == nullptr || 573 ( objDecl->init != nullptr && objDecl->init->maybeConstructed )) 574 && ! objDecl->storage.is_extern 575 && isConstructable( objDecl->type ); 576 } 577 578 bool isConstructable( const ast::Type * type ) { 579 return ! dynamic_cast< const ast::VarArgsType * >( type ) && ! dynamic_cast< const ast::ReferenceType * >( type ) 580 && ! dynamic_cast< const ast::FunctionType * >( type ) && ! Tuples::isTtype( type ); 581 } 582 513 583 struct CallFinder_old { 514 584 CallFinder_old( const std::list< std::string > & names ) : names( names ) {} … … 536 606 537 607 struct CallFinder_new final { 538 std::vector< ast::ptr< ast::Expr >> matches;608 std::vector< const ast::Expr * > matches; 539 609 const std::vector< std::string > names; 540 610 … … 558 628 } 559 629 560 std::vector< ast::ptr< ast::Expr >> collectCtorDtorCalls( const ast::Stmt * stmt ) {630 std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) { 561 631 ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } }; 562 632 maybe_accept( stmt, finder ); 563 return std::move( finder. pass.matches );633 return std::move( finder.core.matches ); 564 634 } 565 635 … … 696 766 template <typename Predicate> 697 767 bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) { 698 std::vector< ast::ptr< ast::Expr >> callExprs = collectCtorDtorCalls( stmt );768 std::vector< const ast::Expr * > callExprs = collectCtorDtorCalls( stmt ); 699 769 return std::all_of( callExprs.begin(), callExprs.end(), pred ); 700 770 } … … 939 1009 } 940 1010 1011 // looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards 1012 // following passes may accidentally resolve this expression if returned as untyped... 1013 ast::Expr * createBitwiseAssignment (const ast::Expr * dst, const ast::Expr * src) { 1014 static ast::ptr<ast::FunctionDecl> assign = nullptr; 1015 if (!assign) { 1016 auto td = new ast::TypeDecl({}, "T", {}, nullptr, ast::TypeDecl::Dtype, true); 1017 assign = new ast::FunctionDecl({}, "?=?", {}, 1018 { new ast::ObjectDecl({}, "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))), 1019 new ast::ObjectDecl({}, "_src", new ast::TypeInstType("T", td))}, 1020 { new ast::ObjectDecl({}, "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic); 1021 } 1022 if (dst->result.as<ast::ReferenceType>()) { 1023 for (int depth = dst->result->referenceDepth(); depth > 0; depth--) { 1024 dst = new ast::AddressExpr(dst); 1025 } 1026 } 1027 else { 1028 dst = new ast::CastExpr(dst, new ast::ReferenceType(dst->result, {})); 1029 } 1030 if (src->result.as<ast::ReferenceType>()) { 1031 for (int depth = src->result->referenceDepth(); depth > 0; depth--) { 1032 src = new ast::AddressExpr(src); 1033 } 1034 } 1035 return new ast::ApplicationExpr(dst->location, ast::VariableExpr::functionPointer(dst->location, assign), {dst, src}); 1036 } 1037 941 1038 struct ConstExprChecker : public WithShortCircuiting { 942 1039 // most expressions are not const expr … … 979 1076 }; 980 1077 1078 struct ConstExprChecker_new : public ast::WithShortCircuiting { 1079 // most expressions are not const expr 1080 void previsit( const ast::Expr * ) { result = false; visit_children = false; } 1081 1082 void previsit( const ast::AddressExpr *addressExpr ) { 1083 visit_children = false; 1084 const ast::Expr * arg = addressExpr->arg; 1085 1086 // address of a variable or member expression is constexpr 1087 if ( ! dynamic_cast< const ast::NameExpr * >( arg ) 1088 && ! dynamic_cast< const ast::VariableExpr * >( arg ) 1089 && ! dynamic_cast< const ast::MemberExpr * >( arg ) 1090 && ! dynamic_cast< const ast::UntypedMemberExpr * >( arg ) ) result = false; 1091 } 1092 1093 // these expressions may be const expr, depending on their children 1094 void previsit( const ast::SizeofExpr * ) {} 1095 void previsit( const ast::AlignofExpr * ) {} 1096 void previsit( const ast::UntypedOffsetofExpr * ) {} 1097 void previsit( const ast::OffsetofExpr * ) {} 1098 void previsit( const ast::OffsetPackExpr * ) {} 1099 void previsit( const ast::CommaExpr * ) {} 1100 void previsit( const ast::LogicalExpr * ) {} 1101 void previsit( const ast::ConditionalExpr * ) {} 1102 void previsit( const ast::CastExpr * ) {} 1103 void previsit( const ast::ConstantExpr * ) {} 1104 1105 void previsit( const ast::VariableExpr * varExpr ) { 1106 visit_children = false; 1107 1108 if ( auto inst = varExpr->result.as<ast::EnumInstType>() ) { 1109 long long int value; 1110 if ( inst->base->valueOf( varExpr->var, value ) ) { 1111 // enumerators are const expr 1112 return; 1113 } 1114 } 1115 result = false; 1116 } 1117 1118 bool result = true; 1119 }; 1120 981 1121 bool isConstExpr( Expression * expr ) { 982 1122 if ( expr ) { … … 998 1138 } 999 1139 1140 bool isConstExpr( const ast::Expr * expr ) { 1141 if ( expr ) { 1142 ast::Pass<ConstExprChecker_new> checker; 1143 expr->accept( checker ); 1144 return checker.core.result; 1145 } 1146 return true; 1147 } 1148 1149 bool isConstExpr( const ast::Init * init ) { 1150 if ( init ) { 1151 ast::Pass<ConstExprChecker_new> checker; 1152 init->accept( checker ); 1153 return checker.core.result; 1154 } // if 1155 // for all intents and purposes, no initializer means const expr 1156 return true; 1157 } 1158 1000 1159 bool isConstructor( const std::string & str ) { return str == "?{}"; } 1001 1160 bool isDestructor( const std::string & str ) { return str == "^?{}"; } … … 1026 1185 if ( ftype->params.size() != 2 ) return false; 1027 1186 1028 const ast::Type * t1 = getPointerBase( ftype->params.front() ->get_type());1187 const ast::Type * t1 = getPointerBase( ftype->params.front() ); 1029 1188 if ( ! t1 ) return false; 1030 const ast::Type * t2 = ftype->params.back() ->get_type();1189 const ast::Type * t2 = ftype->params.back(); 1031 1190 1032 1191 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} ); … … 1055 1214 return isCopyFunction( decl, "?{}" ); 1056 1215 } 1216 1217 void addDataSectonAttribute( ObjectDecl * objDecl ) { 1218 Type *strLitT = new PointerType( Type::Qualifiers( ), 1219 new BasicType( Type::Qualifiers( ), BasicType::Char ) ); 1220 std::list< Expression * > attr_params; 1221 attr_params.push_back( 1222 new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) ); 1223 objDecl->attributes.push_back(new Attribute("section", attr_params)); 1224 } 1225 1226 void addDataSectionAttribute( ast::ObjectDecl * objDecl ) { 1227 auto strLitT = new ast::PointerType(new ast::BasicType(ast::BasicType::Char)); 1228 objDecl->attributes.push_back(new ast::Attribute("section", {new ast::ConstantExpr(objDecl->location, strLitT, "\".data#\"", std::nullopt)})); 1229 } 1230 1057 1231 } -
src/InitTweak/InitTweak.h
rbdfc032 reef8dfb 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 55 60 bool isDesignated( Initializer * init ); 61 bool isDesignated( const ast::Init * init ); 56 62 57 63 /// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its 58 64 /// type, where the depth of its type is the number of nested ArrayTypes + 1 59 65 bool checkInitDepth( ObjectDecl * objDecl ); 66 bool checkInitDepth( const ast::ObjectDecl * objDecl ); 60 67 61 68 /// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr) … … 79 86 /// get all Ctor/Dtor call expressions from a Statement 80 87 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ); 81 std::vector< ast::ptr< ast::Expr >> collectCtorDtorCalls( const ast::Stmt * stmt );88 std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ); 82 89 83 90 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call … … 102 109 bool isConstExpr( Expression * expr ); 103 110 bool isConstExpr( Initializer * init ); 111 112 bool isConstExpr( const ast::Expr * expr ); 113 bool isConstExpr( const ast::Init * init ); 114 115 /// Modifies objDecl to have: 116 /// __attribute__((section (".data#"))) 117 /// which makes gcc put the declared variable in the data section, 118 /// which is helpful for global constants on newer gcc versions, 119 /// so that CFA's generated initialization won't segfault when writing it via a const cast. 120 /// The trailing # is an injected assembly comment, to suppress the "a" in 121 /// .section .data,"a" 122 /// .section .data#,"a" 123 /// to avoid assembler warning "ignoring changed section attributes for .data" 124 void addDataSectonAttribute( ObjectDecl * objDecl ); 125 126 void addDataSectionAttribute( ast::ObjectDecl * objDecl ); 104 127 105 128 class InitExpander_old { -
src/InitTweak/module.mk
rbdfc032 reef8dfb 15 15 ############################################################################### 16 16 17 SRC += InitTweak/GenInit.cc \ 17 SRC += \ 18 InitTweak/FixGlobalInit.cc \ 19 InitTweak/FixGlobalInit.h \ 18 20 InitTweak/FixInit.cc \ 19 InitTweak/FixGlobalInit.cc \ 20 InitTweak/InitTweak.cc 21 InitTweak/FixInit.h \ 22 InitTweak/GenInit.cc \ 23 InitTweak/GenInit.h \ 24 InitTweak/InitTweak.cc \ 25 InitTweak/InitTweak.h \ 26 InitTweak/FixInitNew.cpp 21 27 22 SRCDEMANGLE += InitTweak/GenInit.cc \ 23 InitTweak/InitTweak.cc 28 SRCDEMANGLE += \ 29 InitTweak/GenInit.cc \ 30 InitTweak/GenInit.h \ 31 InitTweak/InitTweak.cc \ 32 InitTweak/InitTweak.h 24 33
Note:
See TracChangeset
for help on using the changeset viewer.