Changeset 04124c4 for src/AST/Pass.impl.hpp
- Timestamp:
- May 10, 2019, 2:47:32 PM (4 years ago)
- Branches:
- arm-eh, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 37e3af4
- Parents:
- 7f3f63c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Pass.impl.hpp
r7f3f63c r04124c4 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo 3 // 4 // The contents of this file are covered under the licence agreement in the 5 // file "LICENCE" distributed with Cforall. 6 // 7 // Pass.impl.hpp -- 8 // 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 15 1 16 #pragma once 2 // IWYU pragma: private, include " Pass.hpp"17 // IWYU pragma: private, include "AST/Pass.hpp" 3 18 4 19 #define VISIT_START( node ) \ 20 using namespace ast; \ 5 21 /* back-up the visit children */ \ 6 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children( m_pass, 0) ); \22 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \ 7 23 /* setup the scope for passes that want to run code at exit */ \ 8 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup ( m_pass, 0) ); \24 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup (pass, 0) ); \ 9 25 /* call the implementation of the previsit of this pass */ \ 10 __pass::previsit( m_pass, node, 0 );26 __pass::previsit( pass, node, 0 ); 11 27 12 28 #define VISIT( code ) \ … … 98 114 99 115 template< typename pass_t > 100 ast::Expr ession * Pass< pass_t >::call_accept( const ast::Expression* expr ) {116 ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) { 101 117 __pedantic_pass_assert( __visit_children() ); 102 118 __pedantic_pass_assert( expr ); 103 119 104 const ast::TypeSubstitution ** env_ptr = __pass::env( m_pass, 0);120 const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0); 105 121 if ( env_ptr && expr->env ) { 106 122 *env_ptr = expr->env; … … 111 127 112 128 template< typename pass_t > 113 ast::Statement * Pass< pass_t >::call_accept( const ast::Statement * stmt ) {129 Stmt * Pass< pass_t >::call_accept( const Stmt * stmt ) { 114 130 __pedantic_pass_assert( __visit_children() ); 115 131 __pedantic_pass_assert( stmt ); 116 117 // add a few useful symbols to the scope118 using __pass::empty;119 using decls_t = typename std::remove_pointer< decltype(__decls_before()) >::type;120 using stmts_t = typename std::remove_pointer< decltype(__stmts_before()) >::type;121 122 // get the stmts/decls that will need to be spliced in123 auto stmts_before = __pass::stmtsToAddBefore( m_pass, 0);124 auto stmts_after = __pass::stmtsToAddAfter ( m_pass, 0);125 auto decls_before = __pass::declsToAddBefore( m_pass, 0);126 auto decls_after = __pass::declsToAddAfter ( m_pass, 0);127 128 // These may be modified by subnode but most be restored once we exit this statemnet.129 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( m_pass, 0); );130 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before );131 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after );132 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > __old_stmts_before( decls_before );133 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after );134 135 // Now is the time to actually visit the node136 ast::Statement * nstmt = stmt->accept( *this );137 138 // If the pass doesn't want to add anything then we are done139 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {140 return nstmt;141 }142 143 // Make sure that it is either adding statements or declartions but not both144 // this is because otherwise the order would be awkward to predict145 assert(( empty( stmts_before ) && empty( stmts_after ))146 || ( empty( decls_before ) && empty( decls_after )) );147 148 // Create a new Compound Statement to hold the new decls/stmts149 ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location );150 151 // Take all the declarations that go before152 __pass::take_all( std::back_inserter( compound->kids ), decls_before );153 __pass::take_all( std::back_inserter( compound->kids ), stmts_before );154 155 // Insert the original declaration156 compound->kids.push_back( nstmt );157 158 // Insert all the declarations that go before159 __pass::take_all( std::back_inserter( compound->kids ), decls_after );160 __pass::take_all( std::back_inserter( compound->kids ), stmts_after );161 162 return compound;163 }164 165 template< typename pass_t >166 template< template <class> class container_t >167 container_t< ast::ptr<ast::Statement> > Pass< pass_t >::call_accept( const container_t< ast::ptr<ast::Statement> > & statements ) {168 __pedantic_pass_assert( __visit_children() );169 if( statements.empty() ) return {};170 171 // We are going to aggregate errors for all these statements172 SemanticErrorException errors;173 132 174 133 // add a few useful symbols to the scope … … 182 141 183 142 // 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); ); 184 144 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before ); 185 145 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after ); … … 187 147 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after ); 188 148 149 // Now is the time to actually visit the node 150 ast::Statement * nstmt = stmt->accept( *this ); 151 152 // If the pass doesn't want to add anything then we are done 153 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) { 154 return nstmt; 155 } 156 157 // Make sure that it is either adding statements or declartions but not both 158 // this is because otherwise the order would be awkward to predict 159 assert(( empty( stmts_before ) && empty( stmts_after )) 160 || ( empty( decls_before ) && empty( decls_after )) ); 161 162 // Create a new Compound Statement to hold the new decls/stmts 163 ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location ); 164 165 // Take all the declarations that go before 166 __pass::take_all( std::back_inserter( compound->kids ), decls_before ); 167 __pass::take_all( std::back_inserter( compound->kids ), stmts_before ); 168 169 // Insert the original declaration 170 compound->kids.push_back( nstmt ); 171 172 // Insert all the declarations that go before 173 __pass::take_all( std::back_inserter( compound->kids ), decls_after ); 174 __pass::take_all( std::back_inserter( compound->kids ), stmts_after ); 175 176 return compound; 177 } 178 179 template< typename pass_t > 180 template< template <class> class container_t > 181 container_t< ptr<Stmt> > Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 182 __pedantic_pass_assert( __visit_children() ); 183 if( statements.empty() ) return {}; 184 185 // We are going to aggregate errors for all these statements 186 SemanticErrorException errors; 187 188 // add a few useful symbols to the scope 189 using __pass::empty; 190 191 // get the stmts/decls that will need to be spliced in 192 auto stmts_before = __pass::stmtsToAddBefore( pass, 0); 193 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0); 194 auto decls_before = __pass::declsToAddBefore( pass, 0); 195 auto decls_after = __pass::declsToAddAfter ( pass, 0); 196 197 // 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 ); 202 189 203 // update pass statitistics 190 204 pass_visitor_stats.depth++; … … 193 207 194 208 bool mutated = false; 195 container_t< ast::ptr< ast::Statement >> new_kids;196 for( const ast::Statement * stmt : statements ) {209 container_t< ptr<Stmt> > new_kids; 210 for( const Stmt * stmt : statements ) { 197 211 try { 198 212 __pedantic_pass_assert( stmt ); … … 269 283 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 270 284 285 template< typename pass_t > 286 inline void ast::acceptAll( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) { 287 // We are going to aggregate errors for all these statements 288 SemanticErrorException errors; 289 290 // add a few useful symbols to the scope 291 using __pass::empty; 292 293 // 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); 296 297 // update pass statitistics 298 pass_visitor_stats.depth++; 299 pass_visitor_stats.max->push(pass_visitor_stats.depth); 300 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 301 302 for ( std::list< ast::ptr<ast::Decl> >::iterator i = decls.begin(); ; ++i ) { 303 // splice in new declarations after previous decl 304 if ( !empty( decls_after ) ) { decls.splice( i, *decls_after ); } 305 306 if ( i == decls.end() ) break; 307 308 try { 309 // run visitor on declaration 310 ast::ptr<ast::Decl> & node = *i; 311 assert( node ); 312 node = node->accept( visitor ); 313 } 314 catch( SemanticErrorException &e ) { 315 errors.append( e ); 316 } 317 318 // splice in new declarations before current decl 319 if ( !empty( decls_before ) ) { decls.splice( i, *decls_before ); } 320 } 321 pass_visitor_stats.depth--; 322 if ( !errors.isEmpty() ) { throw errors; } 323 } 324 271 325 // A NOTE ON THE ORDER OF TRAVERSAL 272 326 // … … 289 343 // ObjectDecl 290 344 template< typename pass_t > 291 ast::Decl arationWithType * Pass< pass_t >::mutate(ast::ObjectDecl * node ) {345 ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) { 292 346 VISIT_START( node ); 293 347 294 348 VISIT( 295 349 { 296 auto guard = make_indexer_guard();297 maybe_accept( node, ast::ObjectDecl::type );298 } 299 maybe_accept( node, ast::ObjectDecl::init );300 maybe_accept( node, ast::ObjectDecl::bitfieldWidth );301 maybe_accept( node, ast::ObjectDecl::attributes );350 indexer_guard guard { *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 ); 302 356 ) 303 357 304 __pass::indexer::AddId( m_pass, 0, node );305 306 VISIT_END( Decl arationWithType, node );358 __pass::indexer::AddId( pass, 0, node ); 359 360 VISIT_END( DeclWithType, node ); 307 361 } 308 362 … … 310 364 // Attribute 311 365 template< typename pass_type > 312 ast::Attribute * ast::Pass< pass_type >::visit( ast::ptr<ast::Attribute> &node ) {366 ast::Attribute * ast::Pass< pass_type >::visit( const ast::Attribute * node ) { 313 367 VISIT_START(node); 314 368 … … 323 377 // TypeSubstitution 324 378 template< typename pass_type > 325 TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {379 TypeSubstitution * PassVisitor< pass_type >::mutate( const TypeSubstitution * node ) { 326 380 MUTATE_START( node ); 327 381
Note: See TracChangeset
for help on using the changeset viewer.