Changeset 69bafd2 for src/AST/Pass.impl.hpp
- Timestamp:
- May 15, 2019, 3:57:26 PM (7 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 3648d98
- Parents:
- 9e1d485 (diff), be567e9 (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. - File:
-
- 1 edited
-
src/AST/Pass.impl.hpp (modified) (20 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Pass.impl.hpp
r9e1d485 r69bafd2 16 16 #pragma once 17 17 // IWYU pragma: private, include "AST/Pass.hpp" 18 19 #include <type_traits> 20 #include <unordered_map> 18 21 19 22 #define VISIT_START( node ) \ … … 26 29 __pass::previsit( pass, node, 0 ); 27 30 28 #define VISIT( code ) \31 #define VISIT( code... ) \ 29 32 /* if this node should visit its children */ \ 30 33 if ( __visit_children() ) { \ … … 35 38 #define VISIT_END( type, node ) \ 36 39 /* call the implementation of the postvisit of this pass */ \ 37 auto __return = __pass::postvisit < type * >( node); \40 auto __return = __pass::postvisit( pass, node, 0 ); \ 38 41 assertf(__return, "post visit should never return null"); \ 39 42 return __return; 40 43 41 44 #ifdef PEDANTIC_PASS_ASSERT 42 #define __pedantic_pass_assert (...) assert (__VAR_ARGS__)43 #define __pedantic_pass_assertf(...) assertf(__VA R_ARGS__)45 #define __pedantic_pass_assert(...) assert (__VA_ARGS__) 46 #define __pedantic_pass_assertf(...) assertf(__VA_ARGS__) 44 47 #else 45 #define __pedantic_pass_assert (...)48 #define __pedantic_pass_assert(...) 46 49 #define __pedantic_pass_assertf(...) 47 50 #endif … … 55 58 } 56 59 57 template<typename it_t, template <class> class container_t> 58 static inline void take_all( it_t it, container_t<ast::ptr<ast::Declaration>> * decls, bool * mutated = nullptr ) { 60 //------------------------------ 61 template<typename it_t, template <class...> class container_t> 62 static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) { 59 63 if(empty(decls)) return; 60 64 61 std::transform(decls->begin(), decls->end(), it, []( Declaration* decl) -> auto {65 std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto { 62 66 return new DeclStmt( decl ); 63 67 }); … … 66 70 } 67 71 68 template<typename it_t, template <class > class container_t>69 static inline void take_all( it_t it, container_t<ast::ptr<ast::St atement>> * decls, bool * mutated = nullptr ) {72 template<typename it_t, template <class...> class container_t> 73 static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * decls, bool * mutated = nullptr ) { 70 74 if(empty(decls)) return; 71 75 … … 75 79 } 76 80 81 //------------------------------ 82 /// Check if should be skipped, different for pointers and containers 77 83 template<typename node_t> 78 bool differs( const node_t * old_val, const node_t * new_val ) { 84 bool skip( const ast::ptr<node_t> & val) { 85 return !val; 86 } 87 88 template< template <class...> class container_t, typename node_t > 89 bool skip( const container_t<ast::ptr< node_t >> & val ) { 90 return val.empty(); 91 } 92 93 //------------------------------ 94 /// Get the value to visit, different for pointers and containers 95 template<typename node_t> 96 auto get( const ast::ptr<node_t> & val, int ) -> decltype(val.get()) { 97 return val.get(); 98 } 99 100 template<typename node_t> 101 const node_t & get( const node_t & val, long) { 102 return val; 103 } 104 105 106 //------------------------------ 107 /// Check if value was mutated, different for pointers and containers 108 template<typename lhs_t, typename rhs_t> 109 bool differs( const lhs_t * old_val, const rhs_t * new_val ) { 79 110 return old_val != new_val; 80 111 } 81 112 82 template< template <class > class container_t >83 bool differs( const container_t<ast::ptr< ast::Statement >> &, const container_t<ast::ptr< ast::Statement >> & new_val ) {113 template< template <class...> class container_t, typename node_t > 114 bool differs( const container_t<ast::ptr< node_t >> &, const container_t<ast::ptr< node_t >> & new_val ) { 84 115 return !new_val.empty(); 85 }86 }87 88 template<typename parent_t, typename child_t>89 template< typename pass_t >90 void Pass< pass_t >::maybe_accept(91 const parent_t * & parent,92 const typename parent_t::child_t * child93 ) {94 const auto & old_val = parent->*child;95 if(!old_val) return;96 97 auto new_val = call_accept(old_val);98 99 if( __pass::differs(old_val, new_val) ) {100 auto new_parent = mutate(parent);101 new_parent->*child = new_val;102 parent = new_parent;103 116 } 104 117 } … … 106 119 template< typename pass_t > 107 120 template< typename node_t > 108 auto Pass< pass_t >::call_accept( const node_t * node ) {121 auto Pass< pass_t >::call_accept( const node_t * node ) -> decltype( node->accept(*this) ) { 109 122 __pedantic_pass_assert( __visit_children() ); 110 123 __pedantic_pass_assert( expr ); 111 124 125 static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR"); 126 static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR"); 127 112 128 return node->accept( *this ); 113 129 } 114 130 115 131 template< typename pass_t > 116 ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) {132 const ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) { 117 133 __pedantic_pass_assert( __visit_children() ); 118 134 __pedantic_pass_assert( expr ); … … 127 143 128 144 template< typename pass_t > 129 Stmt * Pass< pass_t >::call_accept( constStmt * stmt ) {145 const ast::Stmt * Pass< pass_t >::call_accept( const ast::Stmt * stmt ) { 130 146 __pedantic_pass_assert( __visit_children() ); 131 147 __pedantic_pass_assert( stmt ); … … 141 157 142 158 // These may be modified by subnode but most be restored once we exit this statemnet. 143 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( pass, 0) ;);144 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before );145 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after );146 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > __old_stmts_before( decls_before );147 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after );159 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( pass, 0) ); 160 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > > __old_decls_before( stmts_before ); 161 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > > __old_decls_after ( stmts_after ); 162 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > > __old_stmts_before( decls_before ); 163 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > > __old_stmts_after ( decls_after ); 148 164 149 165 // Now is the time to actually visit the node 150 ast::Statement * nstmt = stmt->accept( *this );166 const ast::Stmt * nstmt = stmt->accept( *this ); 151 167 152 168 // If the pass doesn't want to add anything then we are done … … 161 177 162 178 // Create a new Compound Statement to hold the new decls/stmts 163 ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location );179 ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location ); 164 180 165 181 // Take all the declarations that go before … … 168 184 169 185 // Insert the original declaration 170 compound->kids. push_back( nstmt );186 compound->kids.emplace_back( nstmt ); 171 187 172 188 // Insert all the declarations that go before … … 178 194 179 195 template< typename pass_t > 180 template< template <class > class container_t >196 template< template <class...> class container_t > 181 197 container_t< ptr<Stmt> > Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 182 198 __pedantic_pass_assert( __visit_children() ); … … 196 212 197 213 // These may be modified by subnode but most be restored once we exit this statemnet. 198 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before );199 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after );200 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > __old_stmts_before( decls_before );201 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after );214 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > > __old_decls_before( stmts_before ); 215 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > > __old_decls_after ( stmts_after ); 216 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > > __old_stmts_before( decls_before ); 217 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > > __old_stmts_after ( decls_after ); 202 218 203 219 // update pass statitistics … … 211 227 try { 212 228 __pedantic_pass_assert( stmt ); 213 const ast::St atment * new_stmt = stmt->accept( visitor);229 const ast::Stmt * new_stmt = stmt->accept( *this ); 214 230 assert( new_stmt ); 215 231 if(new_stmt != stmt ) mutated = true; … … 240 256 if ( !errors.isEmpty() ) { throw errors; } 241 257 242 return mutated ? new_kids : {};258 return mutated ? new_kids : container_t< ptr<Stmt> >(); 243 259 } 244 260 245 261 template< typename pass_t > 246 template< template <class > class container_t, typename node_t >262 template< template <class...> class container_t, typename node_t > 247 263 container_t< ast::ptr<node_t> > Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 248 264 __pedantic_pass_assert( __visit_children() ); … … 259 275 try { 260 276 __pedantic_pass_assert( node ); 261 const node_t * new_ node= strict_dynamic_cast< const node_t * >( node->accept( *this ) );262 if(new_stmt != stmt) mutated = true;277 const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) ); 278 if(new_stmt != node ) mutated = true; 263 279 264 280 new_kids.emplace_back( new_stmt ); … … 271 287 if ( ! errors.isEmpty() ) { throw errors; } 272 288 273 return mutated ? new_kids : {}; 274 } 289 return mutated ? new_kids : container_t< ast::ptr<node_t> >(); 290 } 291 292 template< typename pass_t > 293 template<typename node_t, typename parent_t, typename child_t> 294 void Pass< pass_t >::maybe_accept( 295 const node_t * & parent, 296 child_t parent_t::*child 297 ) { 298 static_assert( std::is_base_of<parent_t, node_t>::value, "Error deductiing member object" ); 299 300 if(__pass::skip(parent->*child)) return; 301 const auto & old_val = __pass::get(parent->*child, 0); 302 303 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR"); 304 305 auto new_val = call_accept( old_val ); 306 307 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR"); 308 309 if( __pass::differs(old_val, new_val) ) { 310 auto new_parent = mutate(parent); 311 new_parent->*child = new_val; 312 parent = new_parent; 313 } 314 } 315 275 316 } 276 317 … … 284 325 285 326 template< typename pass_t > 286 inline void ast::accept All( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) {327 inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) { 287 328 // We are going to aggregate errors for all these statements 288 329 SemanticErrorException errors; … … 292 333 293 334 // get the stmts/decls that will need to be spliced in 294 auto decls_before = __pass::declsToAddBefore( pass, 0);295 auto decls_after = __pass::declsToAddAfter ( pass, 0);335 auto decls_before = __pass::declsToAddBefore( visitor.pass, 0); 336 auto decls_after = __pass::declsToAddAfter ( visitor.pass, 0); 296 337 297 338 // update pass statitistics … … 343 384 // ObjectDecl 344 385 template< typename pass_t > 345 ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {386 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) { 346 387 VISIT_START( node ); 347 388 348 389 VISIT( 349 390 { 350 indexer_guardguard { *this };351 maybe_accept( node, ObjectDecl::type );352 } 353 maybe_accept( node, ObjectDecl::init );354 maybe_accept( node, ObjectDecl::bitfieldWidth );355 maybe_accept( node, ObjectDecl::attributes );391 guard_indexer guard { *this }; 392 maybe_accept( node, &ast::ObjectDecl::type ); 393 } 394 maybe_accept( node, &ast::ObjectDecl::init ); 395 maybe_accept( node, &ast::ObjectDecl::bitfieldWidth ); 396 maybe_accept( node, &ast::ObjectDecl::attributes ); 356 397 ) 357 398 358 __pass::indexer:: AddId( pass, 0, node );399 __pass::indexer::addId( pass, 0, node ); 359 400 360 401 VISIT_END( DeclWithType, node ); 402 } 403 404 //-------------------------------------------------------------------------- 405 // SingleInit 406 template< typename pass_t > 407 const ast::Init * ast::Pass< pass_t >::visit( const ast::SingleInit * node ) { 408 VISIT_START( node ); 409 410 VISIT( 411 maybe_accept( node, &SingleInit::value ); 412 ) 413 414 VISIT_END( Init, node ); 415 } 416 417 //-------------------------------------------------------------------------- 418 // ListInit 419 template< typename pass_t > 420 const ast::Init * ast::Pass< pass_t >::visit( const ast::ListInit * node ) { 421 VISIT_START( node ); 422 423 VISIT( 424 maybe_accept( node, &ListInit::designations ); 425 maybe_accept( node, &ListInit::initializers ); 426 ) 427 428 VISIT_END( Init, node ); 429 } 430 431 //-------------------------------------------------------------------------- 432 // ConstructorInit 433 template< typename pass_t > 434 const ast::Init * ast::Pass< pass_t >::visit( const ast::ConstructorInit * node ) { 435 VISIT_START( node ); 436 437 VISIT( 438 maybe_accept( node, &ConstructorInit::ctor ); 439 maybe_accept( node, &ConstructorInit::dtor ); 440 maybe_accept( node, &ConstructorInit::init ); 441 ) 442 443 VISIT_END( Init, node ); 361 444 } 362 445 363 446 //-------------------------------------------------------------------------- 364 447 // Attribute 365 template< typename pass_t ype>366 ast::Attribute * ast::Pass< pass_type>::visit( const ast::Attribute * node ) {367 VISIT_START( node);448 template< typename pass_t > 449 const ast::Attribute * ast::Pass< pass_t >::visit( const ast::Attribute * node ) { 450 VISIT_START( node ); 368 451 369 452 VISIT( 370 maybe_accept( node, ast::Attribute::parameters );453 maybe_accept( node, &Attribute::parameters ); 371 454 ) 372 455 373 VISIT_END( ast::Attribute *, node );456 VISIT_END( Attribute *, node ); 374 457 } 375 458 376 459 //-------------------------------------------------------------------------- 377 460 // TypeSubstitution 378 template< typename pass_type > 379 TypeSubstitution * PassVisitor< pass_type >::mutate( const TypeSubstitution * node ) { 380 MUTATE_START( node ); 381 382 #error this is broken 383 384 for ( auto & p : node->typeEnv ) { 385 indexerScopedMutate( p.second, *this ); 386 } 387 for ( auto & p : node->varEnv ) { 388 indexerScopedMutate( p.second, *this ); 389 } 390 391 MUTATE_END( TypeSubstitution, node ); 461 template< typename pass_t > 462 const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) { 463 VISIT_START( node ); 464 465 VISIT( 466 { 467 bool mutated = false; 468 std::unordered_map< std::string, ast::ptr< ast::Type > > new_map; 469 for ( const auto & p : node->typeEnv ) { 470 guard_indexer guard { *this }; 471 auto new_node = p.second->accept( *this ); 472 if (new_node != p.second) mutated = false; 473 new_map.insert({ p.first, new_node }); 474 } 475 if (mutated) { 476 auto new_node = mutate( node ); 477 new_node->typeEnv.swap( new_map ); 478 node = new_node; 479 } 480 } 481 482 { 483 bool mutated = false; 484 std::unordered_map< std::string, ast::ptr< ast::Expr > > new_map; 485 for ( const auto & p : node->varEnv ) { 486 guard_indexer guard { *this }; 487 auto new_node = p.second->accept( *this ); 488 if (new_node != p.second) mutated = false; 489 new_map.insert({ p.first, new_node }); 490 } 491 if (mutated) { 492 auto new_node = mutate( node ); 493 new_node->varEnv.swap( new_map ); 494 node = new_node; 495 } 496 } 497 ) 498 499 VISIT_END( TypeSubstitution, node ); 392 500 } 393 501
Note:
See TracChangeset
for help on using the changeset viewer.