- Timestamp:
- Apr 10, 2022, 2:53:18 PM (4 years ago)
- Branches:
- ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
- Children:
- d8e2a09
- Parents:
- 4559b34 (diff), 6256891 (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
- Files:
-
- 4 added
- 2 deleted
- 48 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
r4559b34 r92538ab 9 9 // Author : Thierry Delisle 10 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Feb 2 13:19:22202213 // Update Count : 4 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 15:01:00 2022 13 // Update Count : 42 14 14 // 15 15 … … 49 49 //================================================================================================ 50 50 namespace ast { 51 52 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not) 53 // allow us to use the same stratagy in the new ast. 54 // xxx - since convert back pass works, this concern seems to be unnecessary. 55 56 // these need to be accessed in new FixInit now 57 ast::ptr<ast::Type> sizeType = nullptr; 58 const ast::FunctionDecl * dereferenceOperator = nullptr; 59 const ast::StructDecl * dtorStruct = nullptr; 60 const ast::FunctionDecl * dtorStructDestroy = nullptr; 51 // These are the shared local information used by ConverterNewToOld and 52 // ConverterOldToNew to update the global information in the two versions. 53 54 static ast::ptr<ast::Type> sizeType = nullptr; 55 static const ast::FunctionDecl * dereferenceOperator = nullptr; 56 static const ast::StructDecl * dtorStruct = nullptr; 57 static const ast::FunctionDecl * dtorStructDestroy = nullptr; 61 58 62 59 } … … 357 354 } 358 355 356 void clausePostamble( Statement * stmt, const ast::StmtClause * node ) { 357 stmt->location = node->location; 358 this->node = stmt; 359 } 360 359 361 const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final { 360 362 if ( inCache( node ) ) return nullptr; … … 405 407 auto stmt = new SwitchStmt( 406 408 get<Expression>().accept1( node->cond ), 407 get<Statement>().acceptL( node-> stmts )409 get<Statement>().acceptL( node->cases ) 408 410 ); 409 411 return stmtPostamble( stmt, node ); 410 412 } 411 413 412 const ast:: Stmt * visit( const ast::CaseStmt* node ) override final {414 const ast::CaseClause * visit( const ast::CaseClause * node ) override final { 413 415 if ( inCache( node ) ) return nullptr; 414 416 auto stmt = new CaseStmt( … … 417 419 node->isDefault() 418 420 ); 419 return stmtPostamble( stmt, node ); 421 clausePostamble( stmt, node ); 422 return nullptr; 420 423 } 421 424 … … 513 516 } 514 517 515 const ast:: Stmt * visit( const ast::CatchStmt* node ) override final {518 const ast::CatchClause * visit( const ast::CatchClause * node ) override final { 516 519 if ( inCache( node ) ) return nullptr; 517 520 CatchStmt::Kind kind; … … 524 527 break; 525 528 default: 526 assertf(false, "Invalid ast:: CatchStmt::Kind: %d\n", node->kind);529 assertf(false, "Invalid ast::ExceptionKind: %d\n", node->kind); 527 530 } 528 531 auto stmt = new CatchStmt( … … 532 535 get<Statement>().accept1( node->body ) 533 536 ); 534 return stmtPostamble( stmt, node );535 } 536 537 const ast:: Stmt * visit( const ast::FinallyStmt* node ) override final {537 return clausePostamble( stmt, node ), nullptr; 538 } 539 540 const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final { 538 541 if ( inCache( node ) ) return nullptr; 539 542 auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) ); 540 return stmtPostamble( stmt, node );543 return clausePostamble( stmt, node ), nullptr; 541 544 } 542 545 … … 1894 1897 old->location, 1895 1898 GET_ACCEPT_1(condition, Expr), 1896 GET_ACCEPT_V(statements, Stmt),1899 GET_ACCEPT_V(statements, CaseClause), 1897 1900 GET_LABELS_V(old->labels) 1898 1901 ); … … 1902 1905 virtual void visit( const CaseStmt * old ) override final { 1903 1906 if ( inCache( old ) ) return; 1904 this->node = new ast::Case Stmt(1907 this->node = new ast::CaseClause( 1905 1908 old->location, 1906 1909 GET_ACCEPT_1(condition, Expr), 1907 GET_ACCEPT_V(stmts, Stmt), 1908 GET_LABELS_V(old->labels) 1909 ); 1910 GET_ACCEPT_V(stmts, Stmt) 1911 ); 1912 auto labels = GET_LABELS_V(old->labels); 1913 assertf(labels.empty(), "Labels found on CaseStmt."); 1910 1914 cache.emplace( old, this->node ); 1911 1915 } … … 2015 2019 old->location, 2016 2020 GET_ACCEPT_1(block, CompoundStmt), 2017 GET_ACCEPT_V(handlers, Catch Stmt),2018 GET_ACCEPT_1(finallyBlock, Finally Stmt),2021 GET_ACCEPT_V(handlers, CatchClause), 2022 GET_ACCEPT_1(finallyBlock, FinallyClause), 2019 2023 GET_LABELS_V(old->labels) 2020 2024 ); … … 2036 2040 } 2037 2041 2038 this->node = new ast::Catch Stmt(2042 this->node = new ast::CatchClause( 2039 2043 old->location, 2040 2044 kind, 2041 2045 GET_ACCEPT_1(decl, Decl), 2042 2046 GET_ACCEPT_1(cond, Expr), 2043 GET_ACCEPT_1(body, Stmt), 2044 GET_LABELS_V(old->labels) 2045 ); 2047 GET_ACCEPT_1(body, Stmt) 2048 ); 2049 auto labels = GET_LABELS_V(old->labels); 2050 assertf(labels.empty(), "Labels found on CatchStmt."); 2046 2051 cache.emplace( old, this->node ); 2047 2052 } … … 2049 2054 virtual void visit( const FinallyStmt * old ) override final { 2050 2055 if ( inCache( old ) ) return; 2051 this->node = new ast::FinallyStmt( 2052 old->location, 2053 GET_ACCEPT_1(block, CompoundStmt), 2054 GET_LABELS_V(old->labels) 2055 ); 2056 this->node = new ast::FinallyClause( 2057 old->location, 2058 GET_ACCEPT_1(block, CompoundStmt) 2059 ); 2060 auto labels = GET_LABELS_V(old->labels); 2061 assertf(labels.empty(), "Labels found on FinallyStmt."); 2056 2062 cache.emplace( old, this->node ); 2057 2063 } … … 2718 2724 2719 2725 for (auto & param : foralls) { 2720 ty->forall.emplace_back(new ast::TypeInstType(param ->name, param));2726 ty->forall.emplace_back(new ast::TypeInstType(param)); 2721 2727 for (auto asst : param->assertions) { 2722 2728 ty->assertions.emplace_back(new ast::VariableExpr({}, asst)); -
src/AST/Decl.cpp
r4559b34 r92538ab 39 39 if ( uniqueId ) return; // ensure only set once 40 40 uniqueId = ++lastUniqueId; 41 idMap[ uniqueId ] = this; 41 // The extra readonly pointer is causing some reference counting issues. 42 // idMap[ uniqueId ] = this; 42 43 } 43 44 44 45 readonly<Decl> Decl::fromId( UniqueId id ) { 46 // Right now this map is always empty, so don't use it. 47 assert( false ); 45 48 IdMapType::const_iterator i = idMap.find( id ); 46 49 if ( i != idMap.end() ) return i->second; … … 65 68 } 66 69 for (auto & tp : this->type_params) { 67 ftype->forall.emplace_back(new TypeInstType(tp ->name, tp));70 ftype->forall.emplace_back(new TypeInstType(tp)); 68 71 for (auto & ap: tp->assertions) { 69 72 ftype->assertions.emplace_back(new VariableExpr(loc, ap)); -
src/AST/Fwd.hpp
r4559b34 r92538ab 47 47 class ForStmt; 48 48 class SwitchStmt; 49 class Case Stmt;49 class CaseClause; 50 50 class BranchStmt; 51 51 class ReturnStmt; 52 52 class ThrowStmt; 53 53 class TryStmt; 54 class Catch Stmt;55 class Finally Stmt;54 class CatchClause; 55 class FinallyClause; 56 56 class SuspendStmt; 57 57 class WaitForStmt; … … 141 141 142 142 class TranslationUnit; 143 // TODO: Get from the TranslationUnit: 144 extern ptr<Type> sizeType; 145 extern const FunctionDecl * dereferenceOperator; 146 extern const StructDecl * dtorStruct; 147 extern const FunctionDecl * dtorStructDestroy; 143 class TranslationGlobal; 148 144 149 145 } -
src/AST/GenericSubstitution.cpp
r4559b34 r92538ab 45 45 visit_children = false; 46 46 const AggregateDecl * aggr = ty->aggr(); 47 sub = TypeSubstitution { aggr->params.begin(), aggr->params.end(), ty->params.begin() };47 sub = TypeSubstitution( aggr->params, ty->params ); 48 48 } 49 49 -
src/AST/Node.cpp
r4559b34 r92538ab 9 9 // Author : Thierry Delisle 10 10 // Created On : Thu May 16 14:16:00 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue Feb 1 09:09:39202213 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 25 10:30:00 2022 13 // Update Count : 4 14 14 // 15 15 … … 19 19 #include <csignal> // MEMORY DEBUG -- for raise 20 20 #include <iostream> 21 #include <utility> 21 22 22 23 #include "Attribute.hpp" … … 76 77 void ast::ptr_base<node_t, ref_t>::_check() const { 77 78 // if(node) assert(node->was_ever_strong == false || node->strong_count > 0); 79 } 80 81 template< typename node_t, enum ast::Node::ref_type ref_t > 82 void ast::ptr_base<node_t, ref_t>::swap( ptr_base & other ) noexcept { 83 std::swap( this->node, other.node ); 84 _trap( this->node ); 85 _trap( other.node ); 78 86 } 79 87 … … 152 160 template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::weak >; 153 161 template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::strong >; 154 template class ast::ptr_base< ast::Case Stmt, ast::Node::ref_type::weak >;155 template class ast::ptr_base< ast::Case Stmt, ast::Node::ref_type::strong >;162 template class ast::ptr_base< ast::CaseClause, ast::Node::ref_type::weak >; 163 template class ast::ptr_base< ast::CaseClause, ast::Node::ref_type::strong >; 156 164 template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::weak >; 157 165 template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::strong >; … … 162 170 template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::weak >; 163 171 template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::strong >; 164 template class ast::ptr_base< ast::Catch Stmt, ast::Node::ref_type::weak >;165 template class ast::ptr_base< ast::Catch Stmt, ast::Node::ref_type::strong >;166 template class ast::ptr_base< ast::Finally Stmt, ast::Node::ref_type::weak >;167 template class ast::ptr_base< ast::Finally Stmt, ast::Node::ref_type::strong >;172 template class ast::ptr_base< ast::CatchClause, ast::Node::ref_type::weak >; 173 template class ast::ptr_base< ast::CatchClause, ast::Node::ref_type::strong >; 174 template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::weak >; 175 template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::strong >; 168 176 template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >; 169 177 template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >; -
src/AST/Node.hpp
r4559b34 r92538ab 10 10 // Created On : Wed May 8 10:27:04 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jun 5 9:47:00 202013 // Update Count : 612 // Last Modified On : Fri Mar 25 10:33:00 2022 13 // Update Count : 7 14 14 // 15 15 … … 103 103 104 104 /// Mutate a node field (only clones if not equal to existing value) 105 template<typename node_t, typename parent_t, typename field_t, typename assn_t>106 const node_t * mutate_field( const node_t * node, field_t parent_t::* field, assn_t && val ) {105 template<typename node_t, typename super_t, typename field_t, typename assn_t> 106 const node_t * mutate_field( const node_t * node, field_t super_t::* field, assn_t && val ) { 107 107 // skip mutate if equivalent 108 108 if ( node->*field == val ) return node; … … 115 115 116 116 /// Mutate a single index of a node field (only clones if not equal to existing value) 117 template<typename node_t, typename parent_t, typename coll_t, typename ind_t, typename field_t>117 template<typename node_t, typename super_t, typename coll_t, typename ind_t, typename field_t> 118 118 const node_t * mutate_field_index( 119 const node_t * node, coll_t parent_t::* field, ind_t i, field_t && val119 const node_t * node, coll_t super_t::* field, ind_t i, field_t && val 120 120 ) { 121 121 // skip mutate if equivalent … … 129 129 130 130 /// Mutate an entire indexed collection by cloning to accepted value 131 template<typename node_t, typename parent_t, typename coll_t>132 const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {131 template<typename node_t, typename super_t, typename coll_t> 132 const node_t * mutate_each( const node_t * node, coll_t super_t::* field, Visitor & v ) { 133 133 for ( unsigned i = 0; i < (node->*field).size(); ++i ) { 134 134 node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) ); … … 230 230 } 231 231 232 /// Swaps the nodes contained within two pointers. 233 void swap( ptr_base & other ) noexcept; 234 232 235 const node_t * get() const { _check(); return node; } 233 236 const node_t * operator->() const { _check(); return node; } … … 292 295 template< typename node_t > 293 296 using readonly = ptr_base< node_t, Node::ref_type::weak >; 297 298 /// Non-member swap that an participate in overload resolution. 299 template< typename node_t, enum Node::ref_type ref_t > 300 void swap( ptr_base< node_t, ref_t > & l, ptr_base< node_t, ref_t > & r ) { 301 l.swap( r ); 302 } 303 294 304 } 295 305 -
src/AST/Pass.hpp
r4559b34 r92538ab 149 149 const ast::Stmt * visit( const ast::ForStmt * ) override final; 150 150 const ast::Stmt * visit( const ast::SwitchStmt * ) override final; 151 const ast:: Stmt * visit( const ast::CaseStmt* ) override final;151 const ast::CaseClause * visit( const ast::CaseClause * ) override final; 152 152 const ast::Stmt * visit( const ast::BranchStmt * ) override final; 153 153 const ast::Stmt * visit( const ast::ReturnStmt * ) override final; 154 154 const ast::Stmt * visit( const ast::ThrowStmt * ) override final; 155 155 const ast::Stmt * visit( const ast::TryStmt * ) override final; 156 const ast:: Stmt * visit( const ast::CatchStmt* ) override final;157 const ast:: Stmt * visit( const ast::FinallyStmt* ) override final;156 const ast::CatchClause * visit( const ast::CatchClause * ) override final; 157 const ast::FinallyClause * visit( const ast::FinallyClause * ) override final; 158 158 const ast::Stmt * visit( const ast::SuspendStmt * ) override final; 159 159 const ast::Stmt * visit( const ast::WaitForStmt * ) override final; -
src/AST/Pass.impl.hpp
r4559b34 r92538ab 354 354 // Take all the elements that are different in 'values' 355 355 // and swap them into 'container' 356 if( values[i] != nullptr ) s td::swap(container[i], values[i]);356 if( values[i] != nullptr ) swap(container[i], values[i]); 357 357 } 358 358 … … 399 399 400 400 template< typename core_t > 401 template<typename node_t, typename parent_t, typename child_t>401 template<typename node_t, typename super_t, typename field_t> 402 402 void ast::Pass< core_t >::maybe_accept( 403 403 const node_t * & parent, 404 child_t parent_t::*child404 field_t super_t::*field 405 405 ) { 406 static_assert( std::is_base_of< parent_t, node_t>::value, "Error deducing member object" );407 408 if(__pass::skip(parent->* child)) return;409 const auto & old_val = __pass::get(parent->* child, 0);406 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" ); 407 408 if(__pass::skip(parent->*field)) return; 409 const auto & old_val = __pass::get(parent->*field, 0); 410 410 411 411 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR"); … … 417 417 if( new_val.differs ) { 418 418 auto new_parent = __pass::mutate<core_t>(parent); 419 new_val.apply(new_parent, child);419 new_val.apply(new_parent, field); 420 420 parent = new_parent; 421 421 } … … 423 423 424 424 template< typename core_t > 425 template<typename node_t, typename parent_t, typename child_t>425 template<typename node_t, typename super_t, typename field_t> 426 426 void ast::Pass< core_t >::maybe_accept_as_compound( 427 427 const node_t * & parent, 428 child_t parent_t::*child428 field_t super_t::*child 429 429 ) { 430 static_assert( std::is_base_of< parent_t, node_t>::value, "Error deducing member object" );430 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" ); 431 431 432 432 if(__pass::skip(parent->*child)) return; … … 893 893 if ( __visit_children() ) { 894 894 maybe_accept( node, &SwitchStmt::cond ); 895 maybe_accept( node, &SwitchStmt:: stmts );895 maybe_accept( node, &SwitchStmt::cases ); 896 896 } 897 897 … … 900 900 901 901 //-------------------------------------------------------------------------- 902 // Case Stmt903 template< typename core_t > 904 const ast:: Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt* node ) {905 VISIT_START( node ); 906 907 if ( __visit_children() ) { 908 maybe_accept( node, &Case Stmt::cond );909 maybe_accept( node, &Case Stmt::stmts );910 } 911 912 VISIT_END( Stmt, node );902 // CaseClause 903 template< typename core_t > 904 const ast::CaseClause * ast::Pass< core_t >::visit( const ast::CaseClause * node ) { 905 VISIT_START( node ); 906 907 if ( __visit_children() ) { 908 maybe_accept( node, &CaseClause::cond ); 909 maybe_accept( node, &CaseClause::stmts ); 910 } 911 912 VISIT_END( CaseClause, node ); 913 913 } 914 914 … … 964 964 965 965 //-------------------------------------------------------------------------- 966 // Catch Stmt967 template< typename core_t > 968 const ast:: Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt* node ) {966 // CatchClause 967 template< typename core_t > 968 const ast::CatchClause * ast::Pass< core_t >::visit( const ast::CatchClause * node ) { 969 969 VISIT_START( node ); 970 970 … … 972 972 // catch statements introduce a level of scope (for the caught exception) 973 973 guard_symtab guard { *this }; 974 maybe_accept( node, &Catch Stmt::decl );975 maybe_accept( node, &Catch Stmt::cond );976 maybe_accept_as_compound( node, &Catch Stmt::body );977 } 978 979 VISIT_END( Stmt, node );980 } 981 982 //-------------------------------------------------------------------------- 983 // Finally Stmt984 template< typename core_t > 985 const ast:: Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt* node ) {986 VISIT_START( node ); 987 988 if ( __visit_children() ) { 989 maybe_accept( node, &Finally Stmt::body );990 } 991 992 VISIT_END( Stmt, node );974 maybe_accept( node, &CatchClause::decl ); 975 maybe_accept( node, &CatchClause::cond ); 976 maybe_accept_as_compound( node, &CatchClause::body ); 977 } 978 979 VISIT_END( CatchClause, node ); 980 } 981 982 //-------------------------------------------------------------------------- 983 // FinallyClause 984 template< typename core_t > 985 const ast::FinallyClause * ast::Pass< core_t >::visit( const ast::FinallyClause * node ) { 986 VISIT_START( node ); 987 988 if ( __visit_children() ) { 989 maybe_accept( node, &FinallyClause::body ); 990 } 991 992 VISIT_END( FinallyClause, node ); 993 993 } 994 994 … … 1054 1054 auto n = __pass::mutate<core_t>(node); 1055 1055 for(size_t i = 0; i < new_clauses.size(); i++) { 1056 if(new_clauses.at(i).target.func != nullptr) s td::swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);1056 if(new_clauses.at(i).target.func != nullptr) swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func); 1057 1057 1058 1058 for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) { 1059 if(new_clauses.at(i).target.args.at(j) != nullptr) s td::swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));1059 if(new_clauses.at(i).target.args.at(j) != nullptr) swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j)); 1060 1060 } 1061 1061 1062 if(new_clauses.at(i).stmt != nullptr) s td::swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);1063 if(new_clauses.at(i).cond != nullptr) s td::swap(n->clauses.at(i).cond, new_clauses.at(i).cond);1062 if(new_clauses.at(i).stmt != nullptr) swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt); 1063 if(new_clauses.at(i).cond != nullptr) swap(n->clauses.at(i).cond, new_clauses.at(i).cond); 1064 1064 } 1065 1065 node = n; … … 2151 2151 2152 2152 if ( __visit_children() ) { 2153 { 2154 bool mutated = false; 2155 std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map; 2156 for ( const auto & p : node->typeEnv ) { 2157 guard_symtab guard { *this }; 2158 auto new_node = p.second->accept( *this ); 2159 if (new_node != p.second) mutated = true; 2160 new_map.insert({ p.first, new_node }); 2161 } 2162 if (mutated) { 2163 auto new_node = __pass::mutate<core_t>( node ); 2164 new_node->typeEnv.swap( new_map ); 2165 node = new_node; 2166 } 2153 bool mutated = false; 2154 std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map; 2155 for ( const auto & p : node->typeEnv ) { 2156 guard_symtab guard { *this }; 2157 auto new_node = p.second->accept( *this ); 2158 if (new_node != p.second) mutated = true; 2159 new_map.insert({ p.first, new_node }); 2160 } 2161 if (mutated) { 2162 auto new_node = __pass::mutate<core_t>( node ); 2163 new_node->typeEnv.swap( new_map ); 2164 node = new_node; 2167 2165 } 2168 2166 } -
src/AST/Print.cpp
r4559b34 r92538ab 597 597 598 598 ++indent; 599 for ( const ast:: Stmt * stmt : node->stmts ) {599 for ( const ast::CaseClause * stmt : node->cases ) { 600 600 stmt->accept( *this ); 601 601 } … … 605 605 } 606 606 607 virtual const ast:: Stmt * visit( const ast::CaseStmt* node ) override final {607 virtual const ast::CaseClause * visit( const ast::CaseClause * node ) override final { 608 608 if ( node->isDefault() ) { 609 609 os << indent << "Default "; … … 687 687 688 688 os << indent-1 << "... and handlers:" << endl; 689 for ( const ast::Catch Stmt* stmt : node->handlers ) {689 for ( const ast::CatchClause * stmt : node->handlers ) { 690 690 os << indent; 691 691 stmt->accept( *this ); … … 701 701 } 702 702 703 virtual const ast:: Stmt * visit( const ast::CatchStmt* node ) override final {703 virtual const ast::CatchClause * visit( const ast::CatchClause * node ) override final { 704 704 os << "Catch "; 705 705 switch ( node->kind ) { … … 726 726 } 727 727 728 virtual const ast:: Stmt * visit( const ast::FinallyStmt* node ) override final {728 virtual const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final { 729 729 os << "Finally Statement" << endl; 730 730 os << indent << "... with block:" << endl; -
src/AST/Stmt.hpp
r4559b34 r92538ab 9 9 // Author : Aaron B. Moss 10 10 // Created On : Wed May 8 13:00:00 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Feb 2 20:06:41202213 // Update Count : 3 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Mar 28 9:50:00 2022 13 // Update Count : 35 14 14 // 15 15 … … 47 47 private: 48 48 Stmt * clone() const override = 0; 49 MUTATE_FRIEND 50 }; 51 52 // Base statement component node (only serves to group them). 53 class StmtClause : public ParseNode { 54 public: 55 // This is for non-statements that still belong with the statements, 56 // but are not statements, usually some sort of clause. Often these can 57 // (and should) be folded into the approprate parent node, but if they 58 // cannot be, they are sub-types of this type, for organization. 59 60 StmtClause( const CodeLocation & loc ) 61 : ParseNode(loc) {} 62 63 private: 64 StmtClause * clone() const override = 0; 49 65 MUTATE_FRIEND 50 66 }; … … 158 174 public: 159 175 ptr<Expr> cond; 176 std::vector<ptr<CaseClause>> cases; 177 178 SwitchStmt( const CodeLocation & loc, const Expr * cond, 179 const std::vector<ptr<CaseClause>> && cases, 180 const std::vector<Label> && labels = {} ) 181 : Stmt(loc, std::move(labels)), cond(cond), cases(std::move(cases)) {} 182 183 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } 184 private: 185 SwitchStmt * clone() const override { return new SwitchStmt{ *this }; } 186 MUTATE_FRIEND 187 }; 188 189 // Case label: case ...: or default: 190 class CaseClause final : public StmtClause { 191 public: 192 // Null for the default label. 193 ptr<Expr> cond; 160 194 std::vector<ptr<Stmt>> stmts; 161 195 162 SwitchStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts, 163 const std::vector<Label> && labels = {} ) 164 : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {} 165 166 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } 167 private: 168 SwitchStmt * clone() const override { return new SwitchStmt{ *this }; } 169 MUTATE_FRIEND 170 }; 171 172 // Case label: case ...: or default: 173 class CaseStmt final : public Stmt { 174 public: 175 // Null for the default label. 176 ptr<Expr> cond; 177 std::vector<ptr<Stmt>> stmts; 178 179 CaseStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts, 180 const std::vector<Label> && labels = {} ) 181 : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {} 196 CaseClause( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts ) 197 : StmtClause(loc), cond(cond), stmts(std::move(stmts)) {} 182 198 183 199 bool isDefault() const { return !cond; } 184 200 185 const Stmt* accept( Visitor & v ) const override { return v.visit( this ); }186 private: 187 Case Stmt * clone() const override { return new CaseStmt{ *this }; }201 const CaseClause * accept( Visitor & v ) const override { return v.visit( this ); } 202 private: 203 CaseClause * clone() const override { return new CaseClause{ *this }; } 188 204 MUTATE_FRIEND 189 205 }; … … 298 314 public: 299 315 ptr<CompoundStmt> body; 300 std::vector<ptr<Catch Stmt>> handlers;301 ptr<Finally Stmt> finally;316 std::vector<ptr<CatchClause>> handlers; 317 ptr<FinallyClause> finally; 302 318 303 319 TryStmt( const CodeLocation & loc, const CompoundStmt * body, 304 const std::vector<ptr<Catch Stmt>> && handlers, const FinallyStmt* finally,320 const std::vector<ptr<CatchClause>> && handlers, const FinallyClause * finally, 305 321 const std::vector<Label> && labels = {} ) 306 322 : Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {} … … 313 329 314 330 // Catch clause of try statement 315 class Catch Stmt final : public Stmt{331 class CatchClause final : public StmtClause { 316 332 public: 317 333 ptr<Decl> decl; … … 320 336 ExceptionKind kind; 321 337 322 Catch Stmt( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,323 const Stmt * body , const std::vector<Label> && labels = {})324 : Stmt (loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}325 326 const Stmt* accept( Visitor & v ) const override { return v.visit( this ); }327 private: 328 Catch Stmt * clone() const override { return new CatchStmt{ *this }; }338 CatchClause( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond, 339 const Stmt * body ) 340 : StmtClause(loc), decl(decl), cond(cond), body(body), kind(kind) {} 341 342 const CatchClause * accept( Visitor & v ) const override { return v.visit( this ); } 343 private: 344 CatchClause * clone() const override { return new CatchClause{ *this }; } 329 345 MUTATE_FRIEND 330 346 }; 331 347 332 348 // Finally clause of try statement 333 class Finally Stmt final : public Stmt{349 class FinallyClause final : public StmtClause { 334 350 public: 335 351 ptr<CompoundStmt> body; 336 352 337 FinallyStmt( const CodeLocation & loc, const CompoundStmt * body, 338 std::vector<Label> && labels = {} ) 339 : Stmt(loc, std::move(labels)), body(body) {} 340 341 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } 342 private: 343 FinallyStmt * clone() const override { return new FinallyStmt{ *this }; } 353 FinallyClause( const CodeLocation & loc, const CompoundStmt * body ) 354 : StmtClause(loc), body(body) {} 355 356 const FinallyClause * accept( Visitor & v ) const override { return v.visit( this ); } 357 private: 358 FinallyClause * clone() const override { return new FinallyClause{ *this }; } 344 359 MUTATE_FRIEND 345 360 }; -
src/AST/TranslationUnit.hpp
r4559b34 r92538ab 10 10 // Created On : Tue Jun 11 15:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Jun 11 15:42:00 201913 // Update Count : 012 // Last Modified On : Tue Mar 11 11:19:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 23 23 namespace ast { 24 24 25 class TranslationGlobal { 26 public: 27 std::map< UniqueId, Decl * > idMap; 28 29 ptr<Type> sizeType; 30 const FunctionDecl * dereference; 31 const StructDecl * dtorStruct; 32 const FunctionDecl * dtorDestroy; 33 }; 34 25 35 class TranslationUnit { 26 36 public: 27 37 std::list< ptr< Decl > > decls; 28 29 struct Global { 30 std::map< UniqueId, Decl * > idMap; 31 32 ptr<Type> sizeType; 33 const FunctionDecl * dereference; 34 const StructDecl * dtorStruct; 35 const FunctionDecl * dtorDestroy; 36 } global; 38 TranslationGlobal global; 37 39 }; 38 40 -
src/AST/Type.cpp
r4559b34 r92538ab 147 147 // --- TypeInstType 148 148 149 TypeInstType::TypeInstType( const TypeDecl * b, 150 CV::Qualifiers q, std::vector<ptr<Attribute>> && as ) 151 : BaseInstType( b->name, q, move(as) ), base( b ), kind( b->kind ) {} 152 149 153 void TypeInstType::set_base( const TypeDecl * b ) { 150 154 base = b; -
src/AST/Type.hpp
r4559b34 r92538ab 421 421 std::vector<ptr<Attribute>> && as = {} ) 422 422 : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {} 423 424 TypeInstType( const TypeDecl * b, 425 CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ); 426 423 427 TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {}, 424 428 std::vector<ptr<Attribute>> && as = {} ) -
src/AST/TypeSubstitution.hpp
r4559b34 r92538ab 37 37 public: 38 38 TypeSubstitution(); 39 template< typename FormalContainer, typename ActualContainer > 40 TypeSubstitution( FormalContainer formals, ActualContainer actuals ); 39 41 template< typename FormalIterator, typename ActualIterator > 40 42 TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ); … … 76 78 bool empty() const; 77 79 80 template< typename FormalContainer, typename ActualContainer > 81 void addAll( FormalContainer formals, ActualContainer actuals ); 78 82 template< typename FormalIterator, typename ActualIterator > 79 void add ( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );83 void addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ); 80 84 81 85 /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr … … 112 116 }; 113 117 118 template< typename FormalContainer, typename ActualContainer > 119 TypeSubstitution::TypeSubstitution( FormalContainer formals, ActualContainer actuals ) { 120 assert( formals.size() == actuals.size() ); 121 addAll( formals.begin(), formals.end(), actuals.begin() ); 122 } 123 124 template< typename FormalIterator, typename ActualIterator > 125 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) { 126 addAll( formalBegin, formalEnd, actualBegin ); 127 } 128 129 template< typename FormalContainer, typename ActualContainer > 130 void TypeSubstitution::addAll( FormalContainer formals, ActualContainer actuals ) { 131 assert( formals.size() == actuals.size() ); 132 addAll( formals.begin(), formals.end(), actuals.begin() ); 133 } 134 114 135 // this is the only place where type parameters outside a function formal may be substituted. 115 136 template< typename FormalIterator, typename ActualIterator > 116 void TypeSubstitution::add ( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {137 void TypeSubstitution::addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) { 117 138 // FormalIterator points to a TypeDecl 118 139 // ActualIterator points to a Type … … 129 150 } // if 130 151 } else { 131 152 // Is this an error? 132 153 } // if 133 154 } // for 134 155 } 135 136 137 138 template< typename FormalIterator, typename ActualIterator >139 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {140 add( formalBegin, formalEnd, actualBegin );141 }142 143 156 144 157 } // namespace ast -
src/AST/Visitor.hpp
r4559b34 r92538ab 41 41 virtual const ast::Stmt * visit( const ast::ForStmt * ) = 0; 42 42 virtual const ast::Stmt * visit( const ast::SwitchStmt * ) = 0; 43 virtual const ast:: Stmt * visit( const ast::CaseStmt* ) = 0;43 virtual const ast::CaseClause * visit( const ast::CaseClause * ) = 0; 44 44 virtual const ast::Stmt * visit( const ast::BranchStmt * ) = 0; 45 45 virtual const ast::Stmt * visit( const ast::ReturnStmt * ) = 0; 46 46 virtual const ast::Stmt * visit( const ast::ThrowStmt * ) = 0; 47 47 virtual const ast::Stmt * visit( const ast::TryStmt * ) = 0; 48 virtual const ast:: Stmt * visit( const ast::CatchStmt* ) = 0;49 virtual const ast:: Stmt * visit( const ast::FinallyStmt* ) = 0;48 virtual const ast::CatchClause * visit( const ast::CatchClause * ) = 0; 49 virtual const ast::FinallyClause * visit( const ast::FinallyClause * ) = 0; 50 50 virtual const ast::Stmt * visit( const ast::SuspendStmt * ) = 0; 51 51 virtual const ast::Stmt * visit( const ast::WaitForStmt * ) = 0; -
src/AST/module.mk
r4559b34 r92538ab 16 16 17 17 SRC_AST = \ 18 AST/AssertAcyclic.cpp \19 AST/AssertAcyclic.hpp \20 18 AST/Attribute.cpp \ 21 19 AST/Attribute.hpp \ … … 64 62 AST/TypeSubstitution.cpp \ 65 63 AST/TypeSubstitution.hpp \ 64 AST/Util.cpp \ 65 AST/Util.hpp \ 66 66 AST/Visitor.hpp 67 67 -
src/Common/CodeLocationTools.cpp
r4559b34 r92538ab 9 9 // Author : Andrew Beach 10 10 // Created On : Fri Dec 4 15:42:00 2020 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue Feb 1 09:14:39202213 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Mar 14 15:14:00 2022 13 // Update Count : 4 14 14 // 15 15 … … 112 112 macro(ForStmt, Stmt) \ 113 113 macro(SwitchStmt, Stmt) \ 114 macro(Case Stmt, Stmt) \114 macro(CaseClause, CaseClause) \ 115 115 macro(BranchStmt, Stmt) \ 116 116 macro(ReturnStmt, Stmt) \ 117 117 macro(ThrowStmt, Stmt) \ 118 118 macro(TryStmt, Stmt) \ 119 macro(Catch Stmt, Stmt) \120 macro(Finally Stmt, Stmt) \119 macro(CatchClause, CatchClause) \ 120 macro(FinallyClause, FinallyClause) \ 121 121 macro(SuspendStmt, Stmt) \ 122 122 macro(WaitForStmt, Stmt) \ … … 239 239 }; 240 240 241 class LocalFillCore : public ast::WithGuards { 242 CodeLocation const * parent; 243 public: 244 LocalFillCore( CodeLocation const & location ) : parent( &location ) { 245 assert( location.isSet() ); 246 } 247 248 template<typename node_t> 249 auto previsit( node_t const * node ) 250 -> typename std::enable_if<has_code_location<node_t>::value, node_t const *>::type { 251 if ( node->location.isSet() ) { 252 GuardValue( parent ) = &node->location; 253 return node; 254 } else { 255 node_t * mut = ast::mutate( node ); 256 mut->location = *parent; 257 return mut; 258 } 259 } 260 }; 261 241 262 } // namespace 242 263 … … 278 299 ast::Pass<FillCore>::run( unit ); 279 300 } 301 302 ast::Node const * localFillCodeLocations( 303 CodeLocation const & location , ast::Node const * node ) { 304 ast::Pass<LocalFillCore> visitor( location ); 305 return node->accept( visitor ); 306 } -
src/Common/CodeLocationTools.hpp
r4559b34 r92538ab 10 10 // Created On : Fri Dec 4 15:35:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Dec 9 9:53:00 202013 // Update Count : 112 // Last Modified On : Mon Mar 14 15:14:00 2022 13 // Update Count : 2 14 14 // 15 15 16 16 #pragma once 17 17 18 struct CodeLocation; 18 19 namespace ast { 20 class Node; 19 21 class TranslationUnit; 20 22 } … … 28 30 // Assign a nearby code-location to any unset code locations in the forest. 29 31 void forceFillCodeLocations( ast::TranslationUnit & unit ); 32 33 // Fill in code-locations with a parent code location, 34 // using the provided CodeLocation as the base. 35 ast::Node const * 36 localFillCodeLocations( CodeLocation const &, ast::Node const * ); -
src/Common/Examine.cc
r4559b34 r92538ab 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Examine. h --7 // Examine.cc -- Helpers for examining AST code. 8 8 // 9 9 // Author : Andrew Beach 10 10 // Created On : Wed Sept 2 14:02 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Sep 8 12:15 202013 // Update Count : 012 // Last Modified On : Fri Dec 10 10:27 2021 13 // Update Count : 1 14 14 // 15 15 16 16 #include "Common/Examine.h" 17 17 18 #include "AST/Type.hpp" 18 19 #include "CodeGen/OperatorTable.h" 20 #include "InitTweak/InitTweak.h" 19 21 20 22 DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ) { … … 36 38 37 39 namespace { 40 41 // getTypeofThis but does some extra checks used in this module. 42 const ast::Type * getTypeofThisSolo( const ast::FunctionDecl * func ) { 43 if ( 1 != func->params.size() ) { 44 return nullptr; 45 } 46 auto ref = func->type->params.front().as<ast::ReferenceType>(); 47 return (ref) ? ref->base : nullptr; 48 } 49 50 } 51 52 const ast::DeclWithType * isMainFor( 53 const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind ) { 54 if ( "main" != func->name ) return nullptr; 55 if ( 1 != func->params.size() ) return nullptr; 56 57 auto param = func->params.front(); 58 59 auto type = dynamic_cast<const ast::ReferenceType *>( param->get_type() ); 60 if ( !type ) return nullptr; 61 62 auto obj = type->base.as<ast::StructInstType>(); 63 if ( !obj ) return nullptr; 64 65 if ( kind != obj->base->kind ) return nullptr; 66 67 return param; 68 } 69 70 namespace { 38 71 Type * getDestructorParam( FunctionDecl * func ) { 39 72 if ( !CodeGen::isDestructor( func->name ) ) return nullptr; … … 48 81 return nullptr; 49 82 } 83 84 const ast::Type * getDestructorParam( const ast::FunctionDecl * func ) { 85 if ( !CodeGen::isDestructor( func->name ) ) return nullptr; 86 //return InitTweak::getParamThis( func )->type; 87 return getTypeofThisSolo( func ); 88 } 89 50 90 } 51 91 … … 57 97 return false; 58 98 } 99 100 bool isDestructorFor( 101 const ast::FunctionDecl * func, const ast::StructDecl * type_decl ) { 102 if ( const ast::Type * type = getDestructorParam( func ) ) { 103 auto stype = dynamic_cast<const ast::StructInstType *>( type ); 104 return stype && stype->base.get() == type_decl; 105 } 106 return false; 107 } -
src/Common/Examine.h
r4559b34 r92538ab 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Examine.h -- 7 // Examine.h -- Helpers for examining AST code. 8 8 // 9 9 // Author : Andrew Beach 10 10 // Created On : Wed Sept 2 13:57 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Sep 8 12:08 202013 // Update Count : 012 // Last Modified On : Fri Dec 10 10:28 2021 13 // Update Count : 1 14 14 // 15 15 16 #include "AST/Decl.hpp" 16 17 #include "SynTree/Declaration.h" 17 18 18 19 /// Check if this is a main function for a type of an aggregate kind. 19 20 DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ); 21 const ast::DeclWithType * isMainFor( 22 const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind ); 20 23 // Returns a pointer to the parameter if true, nullptr otherwise. 21 24 22 25 /// Check if this function is a destructor for the given structure. 23 26 bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl ); 27 bool isDestructorFor( 28 const ast::FunctionDecl * func, const ast::StructDecl * type ); -
src/Concurrency/Keywords.cc
r4559b34 r92538ab 422 422 ; 423 423 else if ( auto param = isMainFor( decl, cast_target ) ) { 424 // This should never trigger. 425 assert( vtable_decl ); 424 if ( !vtable_decl ) { 425 SemanticError( decl, context_error ); 426 } 426 427 // Should be safe because of isMainFor. 427 428 StructInstType * struct_type = static_cast<StructInstType *>( … … 1203 1204 //new TypeofType( noQualifiers, args.front()->clone() ) 1204 1205 new TypeofType( noQualifiers, new UntypedExpr( 1205 new NameExpr( "__get_ type" ),1206 new NameExpr( "__get_mutexstmt_lock_type" ), 1206 1207 { args.front()->clone() } 1207 1208 ) … … 1215 1216 map_range < std::list<Initializer*> > ( args, [](Expression * var ){ 1216 1217 return new SingleInit( new UntypedExpr( 1217 new NameExpr( "__get_ ptr" ),1218 new NameExpr( "__get_mutexstmt_lock_ptr" ), 1218 1219 { var } 1219 1220 ) ); … … 1226 1227 TypeExpr * lock_type_expr = new TypeExpr( 1227 1228 new TypeofType( noQualifiers, new UntypedExpr( 1228 new NameExpr( "__get_ type" ),1229 new NameExpr( "__get_mutexstmt_lock_type" ), 1229 1230 { args.front()->clone() } 1230 1231 ) -
src/Concurrency/KeywordsNew.cpp
r4559b34 r92538ab 10 10 // Created On : Tue Nov 16 9:53:00 2021 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Dec 1 11:24:00 202113 // Update Count : 112 // Last Modified On : Fri Mar 11 10:40:00 2022 13 // Update Count : 2 14 14 // 15 16 #include <iostream> 15 17 16 18 #include "Concurrency/Keywords.h" … … 18 20 #include "AST/Copy.hpp" 19 21 #include "AST/Decl.hpp" 22 #include "AST/Expr.hpp" 20 23 #include "AST/Pass.hpp" 21 24 #include "AST/Stmt.hpp" 25 #include "AST/DeclReplacer.hpp" 22 26 #include "AST/TranslationUnit.hpp" 23 27 #include "CodeGen/OperatorTable.h" 28 #include "Common/Examine.h" 24 29 #include "Common/utility.h" 30 #include "Common/UniqueName.h" 31 #include "ControlStruct/LabelGeneratorNew.hpp" 25 32 #include "InitTweak/InitTweak.h" 33 #include "Virtual/Tables.h" 26 34 27 35 namespace Concurrency { … … 29 37 namespace { 30 38 31 inline static bool isThread( const ast::DeclWithType * decl ) { 39 // -------------------------------------------------------------------------- 40 // Loose Helper Functions: 41 42 /// Detect threads constructed with the keyword thread. 43 bool isThread( const ast::DeclWithType * decl ) { 32 44 auto baseType = decl->get_type()->stripDeclarator(); 33 45 auto instType = dynamic_cast<const ast::StructInstType *>( baseType ); … … 36 48 } 37 49 50 /// Get the virtual type id if given a type name. 51 std::string typeIdType( std::string const & exception_name ) { 52 return exception_name.empty() ? std::string() 53 : Virtual::typeIdType( exception_name ); 54 } 55 56 /// Get the vtable type name if given a type name. 57 std::string vtableTypeName( std::string const & exception_name ) { 58 return exception_name.empty() ? std::string() 59 : Virtual::vtableTypeName( exception_name ); 60 } 61 62 static ast::Type * mutate_under_references( ast::ptr<ast::Type>& type ) { 63 ast::Type * mutType = type.get_and_mutate(); 64 for ( ast::ReferenceType * mutRef 65 ; (mutRef = dynamic_cast<ast::ReferenceType *>( mutType )) 66 ; mutType = mutRef->base.get_and_mutate() ); 67 return mutType; 68 } 69 70 // Describe that it adds the generic parameters and the uses of the generic 71 // parameters on the function and first "this" argument. 72 ast::FunctionDecl * fixupGenerics( 73 const ast::FunctionDecl * func, const ast::StructDecl * decl ) { 74 const CodeLocation & location = decl->location; 75 // We have to update both the declaration 76 auto mutFunc = ast::mutate( func ); 77 auto mutType = mutFunc->type.get_and_mutate(); 78 79 if ( decl->params.empty() ) { 80 return mutFunc; 81 } 82 83 assert( 0 != mutFunc->params.size() ); 84 assert( 0 != mutType->params.size() ); 85 86 // Add the "forall" clause information. 87 for ( const ast::ptr<ast::TypeDecl> & typeParam : decl->params ) { 88 auto typeDecl = ast::deepCopy( typeParam ); 89 mutFunc->type_params.push_back( typeDecl ); 90 mutType->forall.push_back( new ast::TypeInstType( typeDecl ) ); 91 for ( auto & assertion : typeDecl->assertions ) { 92 mutFunc->assertions.push_back( assertion ); 93 mutType->assertions.emplace_back( 94 new ast::VariableExpr( location, assertion ) ); 95 } 96 typeDecl->assertions.clear(); 97 } 98 99 // Even chain_mutate is not powerful enough for this: 100 ast::ptr<ast::Type>& paramType = strict_dynamic_cast<ast::ObjectDecl *>( 101 mutFunc->params[0].get_and_mutate() )->type; 102 auto paramTypeInst = strict_dynamic_cast<ast::StructInstType *>( 103 mutate_under_references( paramType ) ); 104 auto typeParamInst = strict_dynamic_cast<ast::StructInstType *>( 105 mutate_under_references( mutType->params[0] ) ); 106 107 for ( const ast::ptr<ast::TypeDecl> & typeDecl : mutFunc->type_params ) { 108 paramTypeInst->params.push_back( 109 new ast::TypeExpr( location, new ast::TypeInstType( typeDecl ) ) ); 110 typeParamInst->params.push_back( 111 new ast::TypeExpr( location, new ast::TypeInstType( typeDecl ) ) ); 112 } 113 114 return mutFunc; 115 } 116 38 117 // -------------------------------------------------------------------------- 39 struct MutexKeyword final { 118 struct ConcurrentSueKeyword : public ast::WithDeclsToAdd<> { 119 ConcurrentSueKeyword( 120 std::string&& type_name, std::string&& field_name, 121 std::string&& getter_name, std::string&& context_error, 122 std::string&& exception_name, 123 bool needs_main, ast::AggregateDecl::Aggregate cast_target 124 ) : 125 type_name( type_name ), field_name( field_name ), 126 getter_name( getter_name ), context_error( context_error ), 127 exception_name( exception_name ), 128 typeid_name( typeIdType( exception_name ) ), 129 vtable_name( vtableTypeName( exception_name ) ), 130 needs_main( needs_main ), cast_target( cast_target ) 131 {} 132 133 virtual ~ConcurrentSueKeyword() {} 134 135 const ast::Decl * postvisit( const ast::StructDecl * decl ); 136 const ast::DeclWithType * postvisit( const ast::FunctionDecl * decl ); 137 const ast::Expr * postvisit( const ast::KeywordCastExpr * expr ); 138 139 struct StructAndField { 140 const ast::StructDecl * decl; 141 const ast::ObjectDecl * field; 142 }; 143 144 const ast::StructDecl * handleStruct( const ast::StructDecl * ); 145 void handleMain( const ast::FunctionDecl *, const ast::StructInstType * ); 146 void addTypeId( const ast::StructDecl * ); 147 void addVtableForward( const ast::StructDecl * ); 148 const ast::FunctionDecl * forwardDeclare( const ast::StructDecl * ); 149 StructAndField addField( const ast::StructDecl * ); 150 void addGetRoutines( const ast::ObjectDecl *, const ast::FunctionDecl * ); 151 void addLockUnlockRoutines( const ast::StructDecl * ); 152 153 private: 154 const std::string type_name; 155 const std::string field_name; 156 const std::string getter_name; 157 const std::string context_error; 158 const std::string exception_name; 159 const std::string typeid_name; 160 const std::string vtable_name; 161 const bool needs_main; 162 const ast::AggregateDecl::Aggregate cast_target; 163 164 const ast::StructDecl * type_decl = nullptr; 165 const ast::FunctionDecl * dtor_decl = nullptr; 166 const ast::StructDecl * except_decl = nullptr; 167 const ast::StructDecl * typeid_decl = nullptr; 168 const ast::StructDecl * vtable_decl = nullptr; 169 170 }; 171 172 // Handles thread type declarations: 173 // 174 // thread Mythread { struct MyThread { 175 // int data; int data; 176 // a_struct_t more_data; a_struct_t more_data; 177 // => thread$ __thrd_d; 178 // }; }; 179 // static inline thread$ * get_thread( MyThread * this ) { return &this->__thrd_d; } 180 // 181 struct ThreadKeyword final : public ConcurrentSueKeyword { 182 ThreadKeyword() : ConcurrentSueKeyword( 183 "thread$", 184 "__thrd", 185 "get_thread", 186 "thread keyword requires threads to be in scope, add #include <thread.hfa>\n", 187 "ThreadCancelled", 188 true, 189 ast::AggregateDecl::Thread ) 190 {} 191 192 virtual ~ThreadKeyword() {} 193 }; 194 195 // Handles coroutine type declarations: 196 // 197 // coroutine MyCoroutine { struct MyCoroutine { 198 // int data; int data; 199 // a_struct_t more_data; a_struct_t more_data; 200 // => coroutine$ __cor_d; 201 // }; }; 202 // static inline coroutine$ * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; } 203 // 204 struct CoroutineKeyword final : public ConcurrentSueKeyword { 205 CoroutineKeyword() : ConcurrentSueKeyword( 206 "coroutine$", 207 "__cor", 208 "get_coroutine", 209 "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n", 210 "CoroutineCancelled", 211 true, 212 ast::AggregateDecl::Coroutine ) 213 {} 214 215 virtual ~CoroutineKeyword() {} 216 }; 217 218 // Handles monitor type declarations: 219 // 220 // monitor MyMonitor { struct MyMonitor { 221 // int data; int data; 222 // a_struct_t more_data; a_struct_t more_data; 223 // => monitor$ __mon_d; 224 // }; }; 225 // static inline monitor$ * get_coroutine( MyMonitor * this ) { 226 // return &this->__cor_d; 227 // } 228 // void lock(MyMonitor & this) { 229 // lock(get_monitor(this)); 230 // } 231 // void unlock(MyMonitor & this) { 232 // unlock(get_monitor(this)); 233 // } 234 // 235 struct MonitorKeyword final : public ConcurrentSueKeyword { 236 MonitorKeyword() : ConcurrentSueKeyword( 237 "monitor$", 238 "__mon", 239 "get_monitor", 240 "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n", 241 "", 242 false, 243 ast::AggregateDecl::Monitor ) 244 {} 245 246 virtual ~MonitorKeyword() {} 247 }; 248 249 // Handles generator type declarations: 250 // 251 // generator MyGenerator { struct MyGenerator { 252 // int data; int data; 253 // a_struct_t more_data; a_struct_t more_data; 254 // => int __generator_state; 255 // }; }; 256 // 257 struct GeneratorKeyword final : public ConcurrentSueKeyword { 258 GeneratorKeyword() : ConcurrentSueKeyword( 259 "generator$", 260 "__generator_state", 261 "get_generator", 262 "Unable to find builtin type generator$\n", 263 "", 264 true, 265 ast::AggregateDecl::Generator ) 266 {} 267 268 virtual ~GeneratorKeyword() {} 269 }; 270 271 const ast::Decl * ConcurrentSueKeyword::postvisit( 272 const ast::StructDecl * decl ) { 273 if ( !decl->body ) { 274 return decl; 275 } else if ( cast_target == decl->kind ) { 276 return handleStruct( decl ); 277 } else if ( type_name == decl->name ) { 278 assert( !type_decl ); 279 type_decl = decl; 280 } else if ( exception_name == decl->name ) { 281 assert( !except_decl ); 282 except_decl = decl; 283 } else if ( typeid_name == decl->name ) { 284 assert( !typeid_decl ); 285 typeid_decl = decl; 286 } else if ( vtable_name == decl->name ) { 287 assert( !vtable_decl ); 288 vtable_decl = decl; 289 } 290 return decl; 291 } 292 293 // Try to get the full definition, but raise an error on conflicts. 294 const ast::FunctionDecl * getDefinition( 295 const ast::FunctionDecl * old_decl, 296 const ast::FunctionDecl * new_decl ) { 297 if ( !new_decl->stmts ) { 298 return old_decl; 299 } else if ( !old_decl->stmts ) { 300 return new_decl; 301 } else { 302 assert( !old_decl->stmts || !new_decl->stmts ); 303 return nullptr; 304 } 305 } 306 307 const ast::DeclWithType * ConcurrentSueKeyword::postvisit( 308 const ast::FunctionDecl * decl ) { 309 if ( type_decl && isDestructorFor( decl, type_decl ) ) { 310 // Check for forward declarations, try to get the full definition. 311 dtor_decl = (dtor_decl) ? getDefinition( dtor_decl, decl ) : decl; 312 } else if ( !vtable_name.empty() && decl->has_body() ) { 313 if (const ast::DeclWithType * param = isMainFor( decl, cast_target )) { 314 if ( !vtable_decl ) { 315 SemanticError( decl, context_error ); 316 } 317 // Should be safe because of isMainFor. 318 const ast::StructInstType * struct_type = 319 static_cast<const ast::StructInstType *>( 320 static_cast<const ast::ReferenceType *>( 321 param->get_type() )->base.get() ); 322 323 handleMain( decl, struct_type ); 324 } 325 } 326 return decl; 327 } 328 329 const ast::Expr * ConcurrentSueKeyword::postvisit( 330 const ast::KeywordCastExpr * expr ) { 331 if ( cast_target == expr->target ) { 332 // Convert `(thread &)ex` to `(thread$ &)*get_thread(ex)`, etc. 333 if ( !type_decl || !dtor_decl ) { 334 SemanticError( expr, context_error ); 335 } 336 assert( nullptr == expr->result ); 337 auto cast = ast::mutate( expr ); 338 cast->result = new ast::ReferenceType( new ast::StructInstType( type_decl ) ); 339 cast->concrete_target.field = field_name; 340 cast->concrete_target.getter = getter_name; 341 return cast; 342 } 343 return expr; 344 } 345 346 const ast::StructDecl * ConcurrentSueKeyword::handleStruct( 347 const ast::StructDecl * decl ) { 348 assert( decl->body ); 349 350 if ( !type_decl || !dtor_decl ) { 351 SemanticError( decl, context_error ); 352 } 353 354 if ( !exception_name.empty() ) { 355 if( !typeid_decl || !vtable_decl ) { 356 SemanticError( decl, context_error ); 357 } 358 addTypeId( decl ); 359 addVtableForward( decl ); 360 } 361 362 const ast::FunctionDecl * func = forwardDeclare( decl ); 363 StructAndField addFieldRet = addField( decl ); 364 decl = addFieldRet.decl; 365 const ast::ObjectDecl * field = addFieldRet.field; 366 367 addGetRoutines( field, func ); 368 // Add routines to monitors for use by mutex stmt. 369 if ( ast::AggregateDecl::Monitor == cast_target ) { 370 addLockUnlockRoutines( decl ); 371 } 372 373 return decl; 374 } 375 376 void ConcurrentSueKeyword::handleMain( 377 const ast::FunctionDecl * decl, const ast::StructInstType * type ) { 378 assert( vtable_decl ); 379 assert( except_decl ); 380 381 const CodeLocation & location = decl->location; 382 383 std::vector<ast::ptr<ast::Expr>> poly_args = { 384 new ast::TypeExpr( location, type ), 385 }; 386 ast::ObjectDecl * vtable_object = Virtual::makeVtableInstance( 387 location, 388 "_default_vtable_object_declaration", 389 new ast::StructInstType( vtable_decl, copy( poly_args ) ), 390 type, 391 nullptr 392 ); 393 declsToAddAfter.push_back( vtable_object ); 394 declsToAddAfter.push_back( 395 new ast::ObjectDecl( 396 location, 397 Virtual::concurrentDefaultVTableName(), 398 new ast::ReferenceType( vtable_object->type, ast::CV::Const ), 399 new ast::SingleInit( location, 400 new ast::VariableExpr( location, vtable_object ) ), 401 ast::Storage::Classes(), 402 ast::Linkage::Cforall 403 ) 404 ); 405 declsToAddAfter.push_back( Virtual::makeGetExceptionFunction( 406 location, 407 vtable_object, 408 new ast::StructInstType( except_decl, copy( poly_args ) ) 409 ) ); 410 } 411 412 void ConcurrentSueKeyword::addTypeId( const ast::StructDecl * decl ) { 413 assert( typeid_decl ); 414 const CodeLocation & location = decl->location; 415 416 ast::StructInstType * typeid_type = 417 new ast::StructInstType( typeid_decl, ast::CV::Const ); 418 typeid_type->params.push_back( 419 new ast::TypeExpr( location, new ast::StructInstType( decl ) ) ); 420 declsToAddBefore.push_back( 421 Virtual::makeTypeIdInstance( location, typeid_type ) ); 422 // If the typeid_type is going to be kept, the other reference will have 423 // been made by now, but we also get to avoid extra mutates. 424 ast::ptr<ast::StructInstType> typeid_cleanup = typeid_type; 425 } 426 427 void ConcurrentSueKeyword::addVtableForward( const ast::StructDecl * decl ) { 428 assert( vtable_decl ); 429 const CodeLocation& location = decl->location; 430 431 std::vector<ast::ptr<ast::Expr>> poly_args = { 432 new ast::TypeExpr( location, new ast::StructInstType( decl ) ), 433 }; 434 declsToAddBefore.push_back( Virtual::makeGetExceptionForward( 435 location, 436 new ast::StructInstType( vtable_decl, copy( poly_args ) ), 437 new ast::StructInstType( except_decl, copy( poly_args ) ) 438 ) ); 439 ast::ObjectDecl * vtable_object = Virtual::makeVtableForward( 440 location, 441 "_default_vtable_object_declaration", 442 new ast::StructInstType( vtable_decl, std::move( poly_args ) ) 443 ); 444 declsToAddBefore.push_back( vtable_object ); 445 declsToAddBefore.push_back( 446 new ast::ObjectDecl( 447 location, 448 Virtual::concurrentDefaultVTableName(), 449 new ast::ReferenceType( vtable_object->type, ast::CV::Const ), 450 nullptr, 451 ast::Storage::Extern, 452 ast::Linkage::Cforall 453 ) 454 ); 455 } 456 457 const ast::FunctionDecl * ConcurrentSueKeyword::forwardDeclare( 458 const ast::StructDecl * decl ) { 459 const CodeLocation & location = decl->location; 460 461 ast::StructDecl * forward = ast::deepCopy( decl ); 462 { 463 // If removing members makes ref-count go to zero, do not free. 464 ast::ptr<ast::StructDecl> forward_ptr = forward; 465 forward->body = false; 466 forward->members.clear(); 467 forward_ptr.release(); 468 } 469 470 ast::ObjectDecl * this_decl = new ast::ObjectDecl( 471 location, 472 "this", 473 new ast::ReferenceType( new ast::StructInstType( decl ) ), 474 nullptr, 475 ast::Storage::Classes(), 476 ast::Linkage::Cforall 477 ); 478 479 ast::ObjectDecl * ret_decl = new ast::ObjectDecl( 480 location, 481 "ret", 482 new ast::PointerType( new ast::StructInstType( type_decl ) ), 483 nullptr, 484 ast::Storage::Classes(), 485 ast::Linkage::Cforall 486 ); 487 488 ast::FunctionDecl * get_decl = new ast::FunctionDecl( 489 location, 490 getter_name, 491 {}, // forall 492 { this_decl }, // params 493 { ret_decl }, // returns 494 nullptr, // stmts 495 ast::Storage::Static, 496 ast::Linkage::Cforall, 497 { new ast::Attribute( "const" ) }, 498 ast::Function::Inline 499 ); 500 get_decl = fixupGenerics( get_decl, decl ); 501 502 ast::FunctionDecl * main_decl = nullptr; 503 if ( needs_main ) { 504 // `this_decl` is copied here because the original was used above. 505 main_decl = new ast::FunctionDecl( 506 location, 507 "main", 508 {}, 509 { ast::deepCopy( this_decl ) }, 510 {}, 511 nullptr, 512 ast::Storage::Classes(), 513 ast::Linkage::Cforall 514 ); 515 main_decl = fixupGenerics( main_decl, decl ); 516 } 517 518 declsToAddBefore.push_back( forward ); 519 if ( needs_main ) declsToAddBefore.push_back( main_decl ); 520 declsToAddBefore.push_back( get_decl ); 521 522 return get_decl; 523 } 524 525 ConcurrentSueKeyword::StructAndField ConcurrentSueKeyword::addField( 526 const ast::StructDecl * decl ) { 527 const CodeLocation & location = decl->location; 528 529 ast::ObjectDecl * field = new ast::ObjectDecl( 530 location, 531 field_name, 532 new ast::StructInstType( type_decl ), 533 nullptr, 534 ast::Storage::Classes(), 535 ast::Linkage::Cforall 536 ); 537 538 auto mutDecl = ast::mutate( decl ); 539 mutDecl->members.push_back( field ); 540 541 return {mutDecl, field}; 542 } 543 544 void ConcurrentSueKeyword::addGetRoutines( 545 const ast::ObjectDecl * field, const ast::FunctionDecl * forward ) { 546 // Say it is generated at the "same" places as the forward declaration. 547 const CodeLocation & location = forward->location; 548 549 const ast::DeclWithType * param = forward->params.front(); 550 ast::Stmt * stmt = new ast::ReturnStmt( location, 551 new ast::AddressExpr( location, 552 new ast::MemberExpr( location, 553 field, 554 new ast::CastExpr( location, 555 new ast::VariableExpr( location, param ), 556 ast::deepCopy( param->get_type()->stripReferences() ), 557 ast::ExplicitCast 558 ) 559 ) 560 ) 561 ); 562 563 ast::FunctionDecl * decl = ast::deepCopy( forward ); 564 decl->stmts = new ast::CompoundStmt( location, { stmt } ); 565 declsToAddAfter.push_back( decl ); 566 } 567 568 void ConcurrentSueKeyword::addLockUnlockRoutines( 569 const ast::StructDecl * decl ) { 570 // This should only be used on monitors. 571 assert( ast::AggregateDecl::Monitor == cast_target ); 572 573 const CodeLocation & location = decl->location; 574 575 // The parameter for both routines. 576 ast::ObjectDecl * this_decl = new ast::ObjectDecl( 577 location, 578 "this", 579 new ast::ReferenceType( new ast::StructInstType( decl ) ), 580 nullptr, 581 ast::Storage::Classes(), 582 ast::Linkage::Cforall 583 ); 584 585 ast::FunctionDecl * lock_decl = new ast::FunctionDecl( 586 location, 587 "lock", 588 { /* forall */ }, 589 { 590 // Copy the declaration of this. 591 ast::deepCopy( this_decl ), 592 }, 593 { /* returns */ }, 594 nullptr, 595 ast::Storage::Static, 596 ast::Linkage::Cforall, 597 { /* attributes */ }, 598 ast::Function::Inline 599 ); 600 lock_decl = fixupGenerics( lock_decl, decl ); 601 602 lock_decl->stmts = new ast::CompoundStmt( location, { 603 new ast::ExprStmt( location, 604 new ast::UntypedExpr( location, 605 new ast::NameExpr( location, "lock" ), 606 { 607 new ast::UntypedExpr( location, 608 new ast::NameExpr( location, "get_monitor" ), 609 { new ast::VariableExpr( location, 610 InitTweak::getParamThis( lock_decl ) ) } 611 ) 612 } 613 ) 614 ) 615 } ); 616 617 ast::FunctionDecl * unlock_decl = new ast::FunctionDecl( 618 location, 619 "unlock", 620 { /* forall */ }, 621 { 622 // Last use, consume the declaration of this. 623 this_decl, 624 }, 625 { /* returns */ }, 626 nullptr, 627 ast::Storage::Static, 628 ast::Linkage::Cforall, 629 { /* attributes */ }, 630 ast::Function::Inline 631 ); 632 unlock_decl = fixupGenerics( unlock_decl, decl ); 633 634 unlock_decl->stmts = new ast::CompoundStmt( location, { 635 new ast::ExprStmt( location, 636 new ast::UntypedExpr( location, 637 new ast::NameExpr( location, "unlock" ), 638 { 639 new ast::UntypedExpr( location, 640 new ast::NameExpr( location, "get_monitor" ), 641 { new ast::VariableExpr( location, 642 InitTweak::getParamThis( unlock_decl ) ) } 643 ) 644 } 645 ) 646 ) 647 } ); 648 649 declsToAddAfter.push_back( lock_decl ); 650 declsToAddAfter.push_back( unlock_decl ); 651 } 652 653 654 // -------------------------------------------------------------------------- 655 struct SuspendKeyword final : 656 public ast::WithStmtsToAdd<>, public ast::WithGuards { 657 SuspendKeyword() = default; 658 virtual ~SuspendKeyword() = default; 659 660 void previsit( const ast::FunctionDecl * ); 661 const ast::DeclWithType * postvisit( const ast::FunctionDecl * ); 662 const ast::Stmt * postvisit( const ast::SuspendStmt * ); 663 664 private: 665 bool is_real_suspend( const ast::FunctionDecl * ); 666 667 const ast::Stmt * make_generator_suspend( const ast::SuspendStmt * ); 668 const ast::Stmt * make_coroutine_suspend( const ast::SuspendStmt * ); 669 670 struct LabelPair { 671 ast::Label obj; 672 int idx; 673 }; 674 675 LabelPair make_label(const ast::Stmt * stmt ) { 676 labels.push_back( ControlStruct::newLabel( "generator", stmt ) ); 677 return { labels.back(), int(labels.size()) }; 678 } 679 680 const ast::DeclWithType * in_generator = nullptr; 681 const ast::FunctionDecl * decl_suspend = nullptr; 682 std::vector<ast::Label> labels; 683 }; 684 685 void SuspendKeyword::previsit( const ast::FunctionDecl * decl ) { 686 GuardValue( in_generator ); in_generator = nullptr; 687 688 // If it is the real suspend, grab it if we don't have one already. 689 if ( is_real_suspend( decl ) ) { 690 decl_suspend = decl_suspend ? decl_suspend : decl; 691 return; 692 } 693 694 // Otherwise check if this is a generator main and, if so, handle it. 695 auto param = isMainFor( decl, ast::AggregateDecl::Generator ); 696 if ( !param ) return; 697 698 if ( 0 != decl->returns.size() ) { 699 SemanticError( decl->location, "Generator main must return void" ); 700 } 701 702 in_generator = param; 703 GuardValue( labels ); labels.clear(); 704 } 705 706 const ast::DeclWithType * SuspendKeyword::postvisit( 707 const ast::FunctionDecl * decl ) { 708 // Only modify a full definition of a generator with states. 709 if ( !decl->stmts || !in_generator || labels.empty() ) return decl; 710 711 const CodeLocation & location = decl->location; 712 713 // Create a new function body: 714 // static void * __generator_labels[] = {&&s0, &&s1, ...}; 715 // void * __generator_label = __generator_labels[GEN.__generator_state]; 716 // goto * __generator_label; 717 // s0: ; 718 // OLD_BODY 719 720 // This is the null statement inserted right before the body. 721 ast::NullStmt * noop = new ast::NullStmt( location ); 722 noop->labels.push_back( ControlStruct::newLabel( "generator", noop ) ); 723 const ast::Label & first_label = noop->labels.back(); 724 725 // Add each label to the init, starting with the first label. 726 std::vector<ast::ptr<ast::Init>> inits = { 727 new ast::SingleInit( location, 728 new ast::LabelAddressExpr( location, copy( first_label ) ) ) }; 729 // Then go through all the stored labels, and clear the store. 730 for ( auto && label : labels ) { 731 inits.push_back( new ast::SingleInit( label.location, 732 new ast::LabelAddressExpr( label.location, std::move( label ) 733 ) ) ); 734 } 735 labels.clear(); 736 // Then construct the initializer itself. 737 auto init = new ast::ListInit( location, std::move( inits ) ); 738 739 ast::ObjectDecl * generatorLabels = new ast::ObjectDecl( 740 location, 741 "__generator_labels", 742 new ast::ArrayType( 743 new ast::PointerType( new ast::VoidType() ), 744 nullptr, 745 ast::FixedLen, 746 ast::DynamicDim 747 ), 748 init, 749 ast::Storage::Classes(), 750 ast::Linkage::AutoGen 751 ); 752 753 ast::ObjectDecl * generatorLabel = new ast::ObjectDecl( 754 location, 755 "__generator_label", 756 new ast::PointerType( new ast::VoidType() ), 757 new ast::SingleInit( location, 758 new ast::UntypedExpr( location, 759 new ast::NameExpr( location, "?[?]" ), 760 { 761 // TODO: Could be a variable expr. 762 new ast::NameExpr( location, "__generator_labels" ), 763 new ast::UntypedMemberExpr( location, 764 new ast::NameExpr( location, "__generator_state" ), 765 new ast::VariableExpr( location, in_generator ) 766 ) 767 } 768 ) 769 ), 770 ast::Storage::Classes(), 771 ast::Linkage::AutoGen 772 ); 773 774 ast::BranchStmt * theGoTo = new ast::BranchStmt( 775 location, new ast::VariableExpr( location, generatorLabel ) 776 ); 777 778 // The noop goes here in order. 779 780 ast::CompoundStmt * body = new ast::CompoundStmt( location, { 781 { new ast::DeclStmt( location, generatorLabels ) }, 782 { new ast::DeclStmt( location, generatorLabel ) }, 783 { theGoTo }, 784 { noop }, 785 { decl->stmts }, 786 } ); 787 788 auto mutDecl = ast::mutate( decl ); 789 mutDecl->stmts = body; 790 return mutDecl; 791 } 792 793 const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) { 794 switch ( stmt->type ) { 795 case ast::SuspendStmt::None: 796 // Use the context to determain the implicit target. 797 if ( in_generator ) { 798 return make_generator_suspend( stmt ); 799 } else { 800 return make_coroutine_suspend( stmt ); 801 } 802 case ast::SuspendStmt::Coroutine: 803 return make_coroutine_suspend( stmt ); 804 case ast::SuspendStmt::Generator: 805 // Generator suspends must be directly in a generator. 806 if ( !in_generator ) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type." ); 807 return make_generator_suspend( stmt ); 808 } 809 assert( false ); 810 return stmt; 811 } 812 813 /// Find the real/official suspend declaration. 814 bool SuspendKeyword::is_real_suspend( const ast::FunctionDecl * decl ) { 815 return ( !decl->linkage.is_mangled 816 && 0 == decl->params.size() 817 && 0 == decl->returns.size() 818 && "__cfactx_suspend" == decl->name ); 819 } 820 821 const ast::Stmt * SuspendKeyword::make_generator_suspend( 822 const ast::SuspendStmt * stmt ) { 823 assert( in_generator ); 824 // Target code is: 825 // GEN.__generator_state = X; 826 // THEN 827 // return; 828 // __gen_X:; 829 830 const CodeLocation & location = stmt->location; 831 832 LabelPair label = make_label( stmt ); 833 834 // This is the context saving statement. 835 stmtsToAddBefore.push_back( new ast::ExprStmt( location, 836 new ast::UntypedExpr( location, 837 new ast::NameExpr( location, "?=?" ), 838 { 839 new ast::UntypedMemberExpr( location, 840 new ast::NameExpr( location, "__generator_state" ), 841 new ast::VariableExpr( location, in_generator ) 842 ), 843 ast::ConstantExpr::from_int( location, label.idx ), 844 } 845 ) 846 ) ); 847 848 // The THEN component is conditional (return is not). 849 if ( stmt->then ) { 850 stmtsToAddBefore.push_back( stmt->then.get() ); 851 } 852 stmtsToAddBefore.push_back( new ast::ReturnStmt( location, nullptr ) ); 853 854 // The null statement replaces the old suspend statement. 855 return new ast::NullStmt( location, { label.obj } ); 856 } 857 858 const ast::Stmt * SuspendKeyword::make_coroutine_suspend( 859 const ast::SuspendStmt * stmt ) { 860 // The only thing we need from the old statement is the location. 861 const CodeLocation & location = stmt->location; 862 863 if ( !decl_suspend ) { 864 SemanticError( location, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n" ); 865 } 866 if ( stmt->then ) { 867 SemanticError( location, "Compound statement following coroutines is not implemented." ); 868 } 869 870 return new ast::ExprStmt( location, 871 new ast::UntypedExpr( location, 872 ast::VariableExpr::functionPointer( location, decl_suspend ) ) 873 ); 874 } 875 876 // -------------------------------------------------------------------------- 877 struct MutexKeyword final : public ast::WithDeclsToAdd<> { 40 878 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl ); 41 879 void postvisit( const ast::StructDecl * decl ); … … 50 888 ast::CompoundStmt * addStatements( const ast::CompoundStmt * body, const std::vector<ast::ptr<ast::Expr>> & args ); 51 889 ast::CompoundStmt * addThreadDtorStatements( const ast::FunctionDecl* func, const ast::CompoundStmt * body, const std::vector<const ast::DeclWithType *> & args ); 52 890 ast::ExprStmt * genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param); 891 ast::IfStmt * genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam ); 53 892 private: 54 893 const ast::StructDecl * monitor_decl = nullptr; … … 59 898 60 899 static ast::ptr<ast::Type> generic_func; 900 901 UniqueName mutex_func_namer = UniqueName("__lock_unlock_curr"); 61 902 }; 62 903 … … 160 1001 161 1002 const ast::Stmt * MutexKeyword::postvisit( const ast::MutexStmt * stmt ) { 1003 if ( !lock_guard_decl ) { 1004 SemanticError( stmt->location, "mutex stmt requires a header, add #include <mutex_stmt.hfa>\n" ); 1005 } 162 1006 ast::CompoundStmt * body = 163 1007 new ast::CompoundStmt( stmt->location, { stmt->stmt } ); 164 addStatements( body, stmt->mutexObjs );165 return body;1008 1009 return addStatements( body, stmt->mutexObjs );; 166 1010 } 167 1011 … … 251 1095 { 252 1096 new ast::SingleInit( location, 253 new ast::AddressExpr( 1097 new ast::AddressExpr( location, 254 1098 new ast::VariableExpr( location, monitor ) ) ), 255 1099 new ast::SingleInit( location, … … 358 1202 } 359 1203 1204 // generates a cast to the void ptr to the appropriate lock type and dereferences it before calling lock or unlock on it 1205 // used to undo the type erasure done by storing all the lock pointers as void 1206 ast::ExprStmt * MutexKeyword::genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param ) { 1207 return new ast::ExprStmt( location, 1208 new ast::UntypedExpr( location, 1209 new ast::NameExpr( location, fnName ), { 1210 ast::UntypedExpr::createDeref( 1211 location, 1212 new ast::CastExpr( location, 1213 param, 1214 new ast::PointerType( new ast::TypeofType( new ast::UntypedExpr( 1215 expr->location, 1216 new ast::NameExpr( expr->location, "__get_mutexstmt_lock_type" ), 1217 { expr } 1218 ) ) ), 1219 ast::GeneratedFlag::ExplicitCast 1220 ) 1221 ) 1222 } 1223 ) 1224 ); 1225 } 1226 1227 ast::IfStmt * MutexKeyword::genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam ) { 1228 ast::IfStmt * outerLockIf = nullptr; 1229 ast::IfStmt * lastLockIf = nullptr; 1230 1231 //adds an if/elif clause for each lock to assign type from void ptr based on ptr address 1232 for ( long unsigned int i = 0; i < args.size(); i++ ) { 1233 1234 ast::UntypedExpr * ifCond = new ast::UntypedExpr( location, 1235 new ast::NameExpr( location, "?==?" ), { 1236 ast::deepCopy( thisParam ), 1237 new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() )) 1238 } 1239 ); 1240 1241 ast::IfStmt * currLockIf = new ast::IfStmt( 1242 location, 1243 ifCond, 1244 genVirtLockUnlockExpr( fnName, args.at(i), location, ast::deepCopy( thisParam ) ) 1245 ); 1246 1247 if ( i == 0 ) { 1248 outerLockIf = currLockIf; 1249 } else { 1250 // add ifstmt to else of previous stmt 1251 lastLockIf->else_ = currLockIf; 1252 } 1253 1254 lastLockIf = currLockIf; 1255 } 1256 return outerLockIf; 1257 } 1258 360 1259 ast::CompoundStmt * MutexKeyword::addStatements( 361 1260 const ast::CompoundStmt * body, 362 1261 const std::vector<ast::ptr<ast::Expr>> & args ) { 363 ast::CompoundStmt * mutBody = ast::mutate( body );364 1262 365 1263 // Code is generated near the beginning of the compound statement. 366 const CodeLocation & location = mutBody->location; 1264 const CodeLocation & location = body->location; 1265 1266 // final body to return 1267 ast::CompoundStmt * newBody = new ast::CompoundStmt( location ); 1268 1269 // std::string lockFnName = mutex_func_namer.newName(); 1270 // std::string unlockFnName = mutex_func_namer.newName(); 367 1271 368 1272 // Make pointer to the monitors. … … 372 1276 new ast::ArrayType( 373 1277 new ast::PointerType( 374 new ast::TypeofType( 375 new ast::UntypedExpr( 376 location, 377 new ast::NameExpr( location, "__get_type" ), 378 { args.front() } 379 ) 380 ) 1278 new ast::VoidType() 381 1279 ), 382 1280 ast::ConstantExpr::from_ulong( location, args.size() ), … … 392 1290 new ast::UntypedExpr( 393 1291 expr->location, 394 new ast::NameExpr( expr->location, "__get_ ptr" ),1292 new ast::NameExpr( expr->location, "__get_mutexstmt_lock_ptr" ), 395 1293 { expr } 396 1294 ) … … 405 1303 ast::StructInstType * lock_guard_struct = 406 1304 new ast::StructInstType( lock_guard_decl ); 407 ast::TypeExpr * lock_type_expr = new ast::TypeExpr( 408 location, 409 new ast::TypeofType( 410 new ast::UntypedExpr( 411 location, 412 new ast::NameExpr( location, "__get_type" ), 413 { args.front() } 414 ) 415 ) 416 ); 417 418 lock_guard_struct->params.push_back( lock_type_expr ); 419 420 // In reverse order: 1305 1306 // use try stmts to lock and finally to unlock 1307 ast::TryStmt * outerTry = nullptr; 1308 ast::TryStmt * currentTry; 1309 ast::CompoundStmt * lastBody = nullptr; 1310 1311 // adds a nested try stmt for each lock we are locking 1312 for ( long unsigned int i = 0; i < args.size(); i++ ) { 1313 ast::UntypedExpr * innerAccess = new ast::UntypedExpr( 1314 location, 1315 new ast::NameExpr( location,"?[?]" ), { 1316 new ast::NameExpr( location, "__monitors" ), 1317 ast::ConstantExpr::from_int( location, i ) 1318 } 1319 ); 1320 1321 // make the try body 1322 ast::CompoundStmt * currTryBody = new ast::CompoundStmt( location ); 1323 ast::IfStmt * lockCall = genTypeDiscrimLockUnlock( "lock", args, location, innerAccess ); 1324 currTryBody->push_back( lockCall ); 1325 1326 // make the finally stmt 1327 ast::CompoundStmt * currFinallyBody = new ast::CompoundStmt( location ); 1328 ast::IfStmt * unlockCall = genTypeDiscrimLockUnlock( "unlock", args, location, innerAccess ); 1329 currFinallyBody->push_back( unlockCall ); 1330 1331 // construct the current try 1332 currentTry = new ast::TryStmt( 1333 location, 1334 currTryBody, 1335 {}, 1336 new ast::FinallyClause( location, currFinallyBody ) 1337 ); 1338 if ( i == 0 ) outerTry = currentTry; 1339 else { 1340 // pushback try into the body of the outer try 1341 lastBody->push_back( currentTry ); 1342 } 1343 lastBody = currTryBody; 1344 } 1345 1346 // push body into innermost try body 1347 if ( lastBody != nullptr ) { 1348 lastBody->push_back( body ); 1349 newBody->push_front( outerTry ); 1350 } 1351 421 1352 // monitor_guard_t __guard = { __monitors, # }; 422 mutBody->push_front(1353 newBody->push_front( 423 1354 new ast::DeclStmt( 424 1355 location, … … 447 1378 448 1379 // monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) }; 449 mutBody->push_front( new ast::DeclStmt( location, monitors ) ); 450 451 return mutBody; 1380 newBody->push_front( new ast::DeclStmt( location, monitors ) ); 1381 1382 // // The parameter for both __lock_curr/__unlock_curr routines. 1383 // ast::ObjectDecl * this_decl = new ast::ObjectDecl( 1384 // location, 1385 // "this", 1386 // new ast::PointerType( new ast::VoidType() ), 1387 // nullptr, 1388 // {}, 1389 // ast::Linkage::Cforall 1390 // ); 1391 1392 // ast::FunctionDecl * lock_decl = new ast::FunctionDecl( 1393 // location, 1394 // lockFnName, 1395 // { /* forall */ }, 1396 // { 1397 // // Copy the declaration of this. 1398 // this_decl, 1399 // }, 1400 // { /* returns */ }, 1401 // nullptr, 1402 // 0, 1403 // ast::Linkage::Cforall, 1404 // { /* attributes */ }, 1405 // ast::Function::Inline 1406 // ); 1407 1408 // ast::FunctionDecl * unlock_decl = new ast::FunctionDecl( 1409 // location, 1410 // unlockFnName, 1411 // { /* forall */ }, 1412 // { 1413 // // Copy the declaration of this. 1414 // ast::deepCopy( this_decl ), 1415 // }, 1416 // { /* returns */ }, 1417 // nullptr, 1418 // 0, 1419 // ast::Linkage::Cforall, 1420 // { /* attributes */ }, 1421 // ast::Function::Inline 1422 // ); 1423 1424 // ast::IfStmt * outerLockIf = nullptr; 1425 // ast::IfStmt * outerUnlockIf = nullptr; 1426 // ast::IfStmt * lastLockIf = nullptr; 1427 // ast::IfStmt * lastUnlockIf = nullptr; 1428 1429 // //adds an if/elif clause for each lock to assign type from void ptr based on ptr address 1430 // for ( long unsigned int i = 0; i < args.size(); i++ ) { 1431 // ast::VariableExpr * thisParam = new ast::VariableExpr( location, InitTweak::getParamThis( lock_decl ) ); 1432 // ast::UntypedExpr * ifCond = new ast::UntypedExpr( location, 1433 // new ast::NameExpr( location, "?==?" ), { 1434 // thisParam, 1435 // new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() )) 1436 // } 1437 // ); 1438 1439 // ast::IfStmt * currLockIf = new ast::IfStmt( 1440 // location, 1441 // ast::deepCopy( ifCond ), 1442 // genVirtLockUnlockExpr( "lock", args.at(i), location, ast::deepCopy( thisParam ) ) 1443 // ); 1444 1445 // ast::IfStmt * currUnlockIf = new ast::IfStmt( 1446 // location, 1447 // ifCond, 1448 // genVirtLockUnlockExpr( "unlock", args.at(i), location, ast::deepCopy( thisParam ) ) 1449 // ); 1450 1451 // if ( i == 0 ) { 1452 // outerLockIf = currLockIf; 1453 // outerUnlockIf = currUnlockIf; 1454 // } else { 1455 // // add ifstmt to else of previous stmt 1456 // lastLockIf->else_ = currLockIf; 1457 // lastUnlockIf->else_ = currUnlockIf; 1458 // } 1459 1460 // lastLockIf = currLockIf; 1461 // lastUnlockIf = currUnlockIf; 1462 // } 1463 1464 // // add pointer typing if/elifs to body of routines 1465 // lock_decl->stmts = new ast::CompoundStmt( location, { outerLockIf } ); 1466 // unlock_decl->stmts = new ast::CompoundStmt( location, { outerUnlockIf } ); 1467 1468 // // add routines to scope 1469 // declsToAddBefore.push_back( lock_decl ); 1470 // declsToAddBefore.push_back( unlock_decl ); 1471 1472 // newBody->push_front(new ast::DeclStmt( location, lock_decl )); 1473 // newBody->push_front(new ast::DeclStmt( location, unlock_decl )); 1474 1475 return newBody; 452 1476 } 453 1477 … … 564 1588 565 1589 // -------------------------------------------------------------------------- 1590 // Interface Functions: 566 1591 567 1592 void implementKeywords( ast::TranslationUnit & translationUnit ) { 568 (void)translationUnit; 569 assertf(false, "Apply Keywords not implemented." ); 1593 ast::Pass<ThreadKeyword>::run( translationUnit ); 1594 ast::Pass<CoroutineKeyword>::run( translationUnit ); 1595 ast::Pass<MonitorKeyword>::run( translationUnit ); 1596 ast::Pass<GeneratorKeyword>::run( translationUnit ); 1597 ast::Pass<SuspendKeyword>::run( translationUnit ); 570 1598 } 571 1599 -
src/ControlStruct/ExceptTranslateNew.cpp
r4559b34 r92538ab 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Nov 8 11:53:00 2021 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Jan 31 18:49:58202213 // Update Count : 111 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 11 17:51:00 2022 13 // Update Count : 2 14 14 // 15 15 … … 26 26 namespace { 27 27 28 typedef std::list<ast::CatchStmt*> CatchList; 29 30 void split( CatchList& allHandlers, CatchList& terHandlers, 31 CatchList& resHandlers ) { 32 while ( !allHandlers.empty() ) { 33 ast::CatchStmt * stmt = allHandlers.front(); 34 allHandlers.pop_front(); 35 if (stmt->kind == ast::ExceptionKind::Terminate) { 36 terHandlers.push_back(stmt); 37 } else { 38 resHandlers.push_back(stmt); 39 } 40 } 41 } 28 typedef std::list<ast::CatchClause*> CatchList; 42 29 43 30 void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) { … … 58 45 {} 59 46 60 void previsit( const ast::Catch Stmt* stmt );47 void previsit( const ast::CatchClause * stmt ); 61 48 const ast::Stmt * postvisit( const ast::ThrowStmt * stmt ); 62 49 }; … … 101 88 } 102 89 103 void TranslateThrowsCore::previsit( const ast::Catch Stmt* stmt ) {90 void TranslateThrowsCore::previsit( const ast::CatchClause * stmt ) { 104 91 // Validate the statement's form. 105 92 const ast::ObjectDecl * decl = stmt->decl.as<ast::ObjectDecl>(); … … 160 147 ast::FunctionDecl * create_terminate_catch( CatchList &handlers ); 161 148 ast::CompoundStmt * create_single_matcher( 162 const ast::DeclWithType * except_obj, ast::Catch Stmt* modded_handler );149 const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler ); 163 150 ast::FunctionDecl * create_terminate_match( CatchList &handlers ); 164 151 ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper, … … 171 158 ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt ); 172 159 173 // Types used in translation, make sure to use clone. 160 // Types used in translation, first group are internal. 161 ast::ObjectDecl * make_index_object( CodeLocation const & ) const; 162 ast::ObjectDecl * make_exception_object( CodeLocation const & ) const; 163 ast::ObjectDecl * make_bool_object( CodeLocation const & ) const; 164 ast::ObjectDecl * make_voidptr_object( CodeLocation const & ) const; 165 ast::ObjectDecl * make_unused_index_object( CodeLocation const & ) const; 174 166 // void (*function)(); 175 ast::FunctionDecl * try_func_t;167 ast::FunctionDecl * make_try_function( CodeLocation const & ) const; 176 168 // void (*function)(int, exception); 177 ast::FunctionDecl * catch_func_t;169 ast::FunctionDecl * make_catch_function( CodeLocation const & ) const; 178 170 // int (*function)(exception); 179 ast::FunctionDecl * ma tch_func_t;171 ast::FunctionDecl * make_match_function( CodeLocation const & ) const; 180 172 // bool (*function)(exception); 181 ast::FunctionDecl * handle_func_t;173 ast::FunctionDecl * make_handle_function( CodeLocation const & ) const; 182 174 // void (*function)(__attribute__((unused)) void *); 183 ast::FunctionDecl * finally_func_t; 184 185 ast::StructInstType * create_except_type() { 186 assert( except_decl ); 187 return new ast::StructInstType( except_decl ); 188 } 189 void init_func_types(); 175 ast::FunctionDecl * make_finally_function( CodeLocation const & ) const; 190 176 191 177 public: … … 199 185 }; 200 186 201 void TryMutatorCore::init_func_types() { 187 ast::ObjectDecl * TryMutatorCore::make_index_object( 188 CodeLocation const & location ) const { 189 return new ast::ObjectDecl( 190 location, 191 "__handler_index", 192 new ast::BasicType(ast::BasicType::SignedInt), 193 nullptr, //init 194 ast::Storage::Classes{}, 195 ast::Linkage::Cforall 196 ); 197 } 198 199 ast::ObjectDecl * TryMutatorCore::make_exception_object( 200 CodeLocation const & location ) const { 202 201 assert( except_decl ); 203 204 ast::ObjectDecl index_obj( 205 {}, 206 "__handler_index", 207 new ast::BasicType(ast::BasicType::SignedInt) 208 ); 209 ast::ObjectDecl exception_obj( 210 {}, 202 return new ast::ObjectDecl( 203 location, 211 204 "__exception_inst", 212 205 new ast::PointerType( 213 206 new ast::StructInstType( except_decl ) 214 207 ), 215 NULL 216 ); 217 ast::ObjectDecl bool_obj( 218 {}, 208 nullptr, //init 209 ast::Storage::Classes{}, 210 ast::Linkage::Cforall 211 ); 212 } 213 214 ast::ObjectDecl * TryMutatorCore::make_bool_object( 215 CodeLocation const & location ) const { 216 return new ast::ObjectDecl( 217 location, 219 218 "__ret_bool", 220 219 new ast::BasicType( ast::BasicType::Bool ), … … 225 224 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 226 225 ); 227 ast::ObjectDecl voidptr_obj( 228 {}, 226 } 227 228 ast::ObjectDecl * TryMutatorCore::make_voidptr_object( 229 CodeLocation const & location ) const { 230 return new ast::ObjectDecl( 231 location, 229 232 "__hook", 230 233 new ast::PointerType( … … 237 240 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 238 241 ); 239 240 ast::ObjectDecl unused_index_obj( 241 {}, 242 } 243 244 ast::ObjectDecl * TryMutatorCore::make_unused_index_object( 245 CodeLocation const & location ) const { 246 return new ast::ObjectDecl( 247 location, 242 248 "__handler_index", 243 249 new ast::BasicType(ast::BasicType::SignedInt), … … 248 254 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 249 255 ); 250 //unused_index_obj->attributes.push_back( new Attribute( "unused" ) ); 251 252 try_func_t = new ast::FunctionDecl( 253 {}, 256 } 257 258 ast::FunctionDecl * TryMutatorCore::make_try_function( 259 CodeLocation const & location ) const { 260 return new ast::FunctionDecl( 261 location, 254 262 "try", 255 263 {}, //forall … … 260 268 ast::Linkage::Cforall 261 269 ); 262 263 catch_func_t = new ast::FunctionDecl( 264 {}, 270 } 271 272 ast::FunctionDecl * TryMutatorCore::make_catch_function( 273 CodeLocation const & location ) const { 274 return new ast::FunctionDecl( 275 location, 265 276 "catch", 266 277 {}, //forall 267 { ast::deepCopy(&index_obj), ast::deepCopy(&exception_obj)},//param278 { make_index_object( location ), make_exception_object( location ) }, 268 279 {}, //return void 269 280 nullptr, … … 271 282 ast::Linkage::Cforall 272 283 ); 273 274 match_func_t = new ast::FunctionDecl( 275 {}, 284 } 285 286 ast::FunctionDecl * TryMutatorCore::make_match_function( 287 CodeLocation const & location ) const { 288 return new ast::FunctionDecl( 289 location, 276 290 "match", 277 291 {}, //forall 278 { ast::deepCopy(&exception_obj)},279 { ast::deepCopy(&unused_index_obj)},292 { make_exception_object( location ) }, 293 { make_unused_index_object( location ) }, 280 294 nullptr, 281 295 ast::Storage::Classes{}, 282 296 ast::Linkage::Cforall 283 297 ); 284 285 handle_func_t = new ast::FunctionDecl( 286 {}, 298 } 299 300 ast::FunctionDecl * TryMutatorCore::make_handle_function( 301 CodeLocation const & location ) const { 302 return new ast::FunctionDecl( 303 location, 287 304 "handle", 288 305 {}, //forall 289 { ast::deepCopy(&exception_obj)},290 { ast::deepCopy(&bool_obj)},306 { make_exception_object( location ) }, 307 { make_bool_object( location ) }, 291 308 nullptr, 292 309 ast::Storage::Classes{}, 293 310 ast::Linkage::Cforall 294 311 ); 295 296 finally_func_t = new ast::FunctionDecl( 297 {}, 312 } 313 314 ast::FunctionDecl * TryMutatorCore::make_finally_function( 315 CodeLocation const & location ) const { 316 return new ast::FunctionDecl( 317 location, 298 318 "finally", 299 319 {}, //forall 300 { ast::deepCopy(&voidptr_obj)},320 { make_voidptr_object( location ) }, 301 321 {}, //return void 302 322 nullptr, … … 304 324 ast::Linkage::Cforall 305 325 ); 306 307 //catch_func_t.get_parameters().push_back( index_obj.clone() );308 //catch_func_t.get_parameters().push_back( exception_obj.clone() );309 //match_func_t.get_returnVals().push_back( unused_index_obj );310 //match_func_t.get_parameters().push_back( exception_obj.clone() );311 //handle_func_t.get_returnVals().push_back( bool_obj.clone() );312 //handle_func_t.get_parameters().push_back( exception_obj.clone() );313 //finally_func_t.get_parameters().push_back( voidptr_obj.clone() );314 326 } 315 327 316 328 // TryStmt Mutation Helpers 317 318 /*319 ast::CompoundStmt * TryMutatorCore::take_try_block( ast::TryStmt *tryStmt ) {320 ast::CompoundStmt * block = tryStmt->body;321 tryStmt->body = nullptr;322 return block;323 }324 */325 329 326 330 ast::FunctionDecl * TryMutatorCore::create_try_wrapper( 327 331 const ast::CompoundStmt *body ) { 328 332 329 ast::FunctionDecl * ret = ast::deepCopy(try_func_t);333 ast::FunctionDecl * ret = make_try_function( body->location ); 330 334 ret->stmts = body; 331 335 return ret; … … 334 338 ast::FunctionDecl * TryMutatorCore::create_terminate_catch( 335 339 CatchList &handlers ) { 336 std::vector<ast::ptr<ast:: Stmt>> handler_wrappers;340 std::vector<ast::ptr<ast::CaseClause>> handler_wrappers; 337 341 338 342 assert (!handlers.empty()); 339 343 const CodeLocation loc = handlers.front()->location; 340 344 341 ast::FunctionDecl * func_t = ast::deepCopy(catch_func_t);345 ast::FunctionDecl * func_t = make_catch_function( loc ); 342 346 const ast::DeclWithType * index_obj = func_t->params.front(); 343 347 const ast::DeclWithType * except_obj = func_t->params.back(); … … 348 352 for ( ; it != handlers.end() ; ++it ) { 349 353 ++index; 350 ast::Catch Stmt* handler = *it;354 ast::CatchClause * handler = *it; 351 355 const CodeLocation loc = handler->location; 352 356 … … 386 390 // handler->body = nullptr; 387 391 388 handler_wrappers.push_back( new ast::Case Stmt(loc,392 handler_wrappers.push_back( new ast::CaseClause(loc, 389 393 ast::ConstantExpr::from_int(loc, index) , 390 394 { block, new ast::ReturnStmt( loc, nullptr ) } … … 393 397 // TODO: Some sort of meaningful error on default perhaps? 394 398 395 /* 396 std::list<Statement*> stmt_handlers; 397 while ( !handler_wrappers.empty() ) { 398 stmt_handlers.push_back( handler_wrappers.front() ); 399 handler_wrappers.pop_front(); 400 } 401 */ 402 403 ast::SwitchStmt * handler_lookup = new ast::SwitchStmt(loc, 399 ast::SwitchStmt * handler_lookup = new ast::SwitchStmt( loc, 404 400 new ast::VariableExpr( loc, index_obj ), 405 401 std::move(handler_wrappers) 406 402 ); 407 ast::CompoundStmt * body = new ast::CompoundStmt(loc, 408 {handler_lookup}); 403 ast::CompoundStmt * body = new ast::CompoundStmt( loc, {handler_lookup} ); 409 404 410 405 func_t->stmts = body; … … 415 410 // except_obj is referenced, modded_handler will be freed. 416 411 ast::CompoundStmt * TryMutatorCore::create_single_matcher( 417 const ast::DeclWithType * except_obj, ast::Catch Stmt* modded_handler ) {412 const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler ) { 418 413 // { 419 414 // `modded_handler.decl` … … 433 428 434 429 // Check for type match. 435 ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc, 430 ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc, 436 431 new ast::VariableExpr(loc, except_obj ), 437 432 local_except->get_type() … … 445 440 } 446 441 // Construct the match condition. 447 block->push_back( new ast::IfStmt(loc, 442 block->push_back( new ast::IfStmt(loc, 448 443 cond, modded_handler->body, nullptr ) ); 449 444 450 // xxx - how does this work in new ast451 //modded_handler->set_decl( nullptr );452 //modded_handler->set_cond( nullptr );453 //modded_handler->set_body( nullptr );454 //delete modded_handler;455 445 return block; 456 446 } … … 467 457 ast::CompoundStmt * body = new ast::CompoundStmt(loc); 468 458 469 ast::FunctionDecl * func_t = ast::deepCopy(match_func_t);459 ast::FunctionDecl * func_t = make_match_function( loc ); 470 460 const ast::DeclWithType * except_obj = func_t->params.back(); 471 461 … … 475 465 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) { 476 466 ++index; 477 ast::Catch Stmt* handler = *it;467 ast::CatchClause * handler = *it; 478 468 479 469 // Body should have been taken by create_terminate_catch. … … 490 480 } 491 481 492 body->push_back( new ast::ReturnStmt(loc, 482 body->push_back( new ast::ReturnStmt(loc, 493 483 ast::ConstantExpr::from_int( loc, 0 ) )); 494 484 … … 525 515 ast::CompoundStmt * body = new ast::CompoundStmt(loc); 526 516 527 ast::FunctionDecl * func_t = ast::deepCopy(handle_func_t);517 ast::FunctionDecl * func_t = make_handle_function( loc ); 528 518 const ast::DeclWithType * except_obj = func_t->params.back(); 529 519 530 520 CatchList::iterator it; 531 521 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) { 532 ast::Catch Stmt* handler = *it;522 ast::CatchClause * handler = *it; 533 523 const CodeLocation loc = handler->location; 534 524 // Modifiy body. 535 525 ast::CompoundStmt * handling_code; 536 526 if (handler->body.as<ast::CompoundStmt>()) { 537 handling_code = 538 strict_dynamic_cast<ast::CompoundStmt*>(handler->body.get_and_mutate() );527 handling_code = strict_dynamic_cast<ast::CompoundStmt*>( 528 handler->body.get_and_mutate() ); 539 529 } else { 540 530 handling_code = new ast::CompoundStmt(loc); … … 597 587 ast::TryStmt * tryStmt ) { 598 588 // void finally() { `finally->block` } 599 const ast::Finally Stmt* finally = tryStmt->finally;589 const ast::FinallyClause * finally = tryStmt->finally; 600 590 const ast::CompoundStmt * body = finally->body; 601 591 602 ast::FunctionDecl * func_t = ast::deepCopy(finally_func_t);592 ast::FunctionDecl * func_t = make_finally_function( tryStmt->location ); 603 593 func_t->stmts = body; 604 594 605 // finally->set_block( nullptr );606 // delete finally;607 595 tryStmt->finally = nullptr; 608 609 596 610 597 return func_t; … … 617 604 618 605 const CodeLocation loc = finally_wrapper->location; 619 // Make Cleanup Attribute.620 /*621 std::list< ast::Attribute * > attributes;622 {623 std::list< > attr_params;624 attr_params.push_back( nameOf( finally_wrapper ) );625 attributes.push_back( new Attribute( "cleanup", attr_params ) );626 }627 */628 629 606 return new ast::ObjectDecl( 630 607 loc, … … 644 621 // return false; 645 622 const CodeLocation loc = throwStmt->location; 646 ast::Stmt * result = new ast::ReturnStmt(loc, 623 ast::Stmt * result = new ast::ReturnStmt(loc, 647 624 ast::ConstantExpr::from_bool( loc, false ) 648 625 ); 649 626 result->labels = throwStmt->labels; 650 // delete throwStmt; done by postvisit651 627 return result; 652 628 } … … 660 636 assert( nullptr == except_decl ); 661 637 except_decl = structDecl; 662 init_func_types();663 638 } else if ( structDecl->name == "__cfaehm_try_resume_node" ) { 664 639 assert( nullptr == node_decl ); … … 706 681 } 707 682 } 708 // split( mutStmt->handlers,709 // termination_handlers, resumption_handlers );710 683 711 684 if ( resumption_handlers.size() ) { -
src/ControlStruct/LabelGeneratorNew.cpp
r4559b34 r92538ab 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // LabelGenerator .cc--7 // LabelGeneratorNew.cpp -- 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Feb 2 09:11:17202213 // Update Count : 7 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Mar 28 10:03:00 2022 13 // Update Count : 73 14 14 // 15 15 … … 25 25 namespace ControlStruct { 26 26 27 Label newLabel( const string & suffix, const Stmt * stmt ) { 27 enum { size = 128 }; 28 29 static int newLabelPre( char buf[size], const string & suffix ) { 28 30 static int current = 0; 29 31 30 assertf( stmt, "CFA internal error: parameter statement cannot be null pointer" );31 32 enum { size = 128 };33 char buf[size]; // space to build label34 32 int len = snprintf( buf, size, "__L%d__%s", current++, suffix.c_str() ); 35 33 assertf( len < size, "CFA Internal error: buffer overflow creating label" ); 34 return len; 35 } 36 37 static Label newLabelPost( char buf[size], const CodeLocation & location ) { 38 Label ret_label( location, buf ); 39 ret_label.attributes.push_back( new Attribute( "unused" ) ); 40 return ret_label; 41 } 42 43 Label newLabel( const string & suffix, const Stmt * stmt ) { 44 // Buffer for string manipulation. 45 char buf[size]; 46 47 assertf( stmt, "CFA internal error: parameter statement cannot be null pointer" ); 48 int len = newLabelPre( buf, suffix ); 36 49 37 50 // What does this do? … … 41 54 } // if 42 55 43 Label ret_label( stmt->location, buf ); 44 ret_label.attributes.push_back( new Attribute( "unused" ) ); 45 return ret_label; 56 return newLabelPost( buf, stmt->location ); 57 } 58 59 Label newLabel( const string & suffix, const CodeLocation & location ) { 60 // Buffer for string manipulation. 61 char buf[size]; 62 63 newLabelPre( buf, suffix ); 64 return newLabelPost( buf, location ); 46 65 } 47 66 -
src/ControlStruct/LabelGeneratorNew.hpp
r4559b34 r92538ab 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Jan 31 18:03:09202213 // Update Count : 2 711 // Last Modified By : Andrew Beach 12 // Last Modified On : Fir Mar 25 15:40:00 2022 13 // Update Count : 28 14 14 // 15 15 … … 18 18 #include <string> // for string 19 19 20 class Statement;20 class CodeLocation; 21 21 22 22 namespace ast { 23 class Label; 23 24 class Stmt; 24 class Label;25 25 } // namespace ast 26 26 27 27 namespace ControlStruct { 28 28 ast::Label newLabel( const std::string &, const ast::Stmt * ); 29 ast::Label newLabel( const std::string &, const CodeLocation & ); 29 30 } // namespace ControlStruct 30 31 -
src/ControlStruct/MultiLevelExit.cpp
r4559b34 r92538ab 9 9 // Author : Andrew Beach 10 10 // Created On : Mon Nov 1 13:48:00 2021 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Feb 2 23:07:54202213 // Update Count : 3 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Mar 28 9:42:00 2022 13 // Update Count : 34 14 14 // 15 15 … … 40 40 41 41 enum Kind { 42 ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, Case StmtK, SwitchStmtK, TryStmtK42 ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, CaseClauseK, SwitchStmtK, TryStmtK 43 43 } kind; 44 44 … … 58 58 Entry( const IfStmt *stmt, Label breakExit ) : 59 59 stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( IfStmtK ) {} 60 Entry( const Case Stmt *stmt, Label fallExit ) :61 stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( Case StmtK ) {}60 Entry( const CaseClause *, const CompoundStmt *stmt, Label fallExit ) : 61 stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( CaseClauseK ) {} 62 62 Entry( const SwitchStmt *stmt, Label breakExit, Label fallDefaultExit ) : 63 63 stmt( stmt ), firstTarget( breakExit ), secondTarget( fallDefaultExit ), kind( SwitchStmtK ) {} … … 66 66 67 67 bool isContTarget() const { return kind <= WhileDoStmtK; } 68 bool isBreakTarget() const { return kind != Case StmtK; }69 bool isFallTarget() const { return kind == Case StmtK; }68 bool isBreakTarget() const { return kind != CaseClauseK; } 69 bool isFallTarget() const { return kind == CaseClauseK; } 70 70 bool isFallDefaultTarget() const { return kind == SwitchStmtK; } 71 71 72 72 // These routines set a target as being "used" by a BranchStmt 73 73 Label useContExit() { assert( kind <= WhileDoStmtK ); return useTarget(secondTarget); } 74 Label useBreakExit() { assert( kind != Case StmtK ); return useTarget(firstTarget); }75 Label useFallExit() { assert( kind == Case StmtK ); return useTarget(firstTarget); }74 Label useBreakExit() { assert( kind != CaseClauseK ); return useTarget(firstTarget); } 75 Label useFallExit() { assert( kind == CaseClauseK ); return useTarget(firstTarget); } 76 76 Label useFallDefaultExit() { assert( kind == SwitchStmtK ); return useTarget(secondTarget); } 77 77 78 78 // These routines check if a specific label for a statement is used by a BranchStmt 79 79 bool isContUsed() const { assert( kind <= WhileDoStmtK ); return secondTarget.used; } 80 bool isBreakUsed() const { assert( kind != Case StmtK ); return firstTarget.used; }81 bool isFallUsed() const { assert( kind == Case StmtK ); return firstTarget.used; }80 bool isBreakUsed() const { assert( kind != CaseClauseK ); return firstTarget.used; } 81 bool isFallUsed() const { assert( kind == CaseClauseK ); return firstTarget.used; } 82 82 bool isFallDefaultUsed() const { assert( kind == SwitchStmtK ); return secondTarget.used; } 83 83 void seenDefault() { fallDefaultValid = false; } … … 115 115 void previsit( const ForStmt * ); 116 116 const ForStmt * postvisit( const ForStmt * ); 117 const Case Stmt * previsit( const CaseStmt* );117 const CaseClause * previsit( const CaseClause * ); 118 118 void previsit( const IfStmt * ); 119 119 const IfStmt * postvisit( const IfStmt * ); … … 123 123 void previsit( const TryStmt * ); 124 124 void postvisit( const TryStmt * ); 125 void previsit( const Finally Stmt* );125 void previsit( const FinallyClause * ); 126 126 127 127 const Stmt * mutateLoop( const Stmt * body, Entry& ); … … 288 288 auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt ); 289 289 bool foundDefault = false; 290 for ( auto subStmt : switchStmt->stmts ) { 291 const CaseStmt * caseStmt = subStmt.strict_as<CaseStmt>(); 290 for ( auto caseStmt : switchStmt->cases ) { 292 291 if ( caseStmt->isDefault() ) { 293 292 foundDefault = true; … … 365 364 } 366 365 367 const Case Stmt * MultiLevelExitCore::previsit( const CaseStmt* stmt ) {366 const CaseClause * MultiLevelExitCore::previsit( const CaseClause * stmt ) { 368 367 visit_children = false; 369 368 … … 375 374 376 375 // The cond may not exist, but if it does update it now. 377 visitor->maybe_accept( stmt, &Case Stmt::cond );376 visitor->maybe_accept( stmt, &CaseClause::cond ); 378 377 379 378 // Just save the mutated node for simplicity. 380 Case Stmt* mutStmt = mutate( stmt );381 382 Label fallLabel = newLabel( "fallThrough", stmt );379 CaseClause * mutStmt = mutate( stmt ); 380 381 Label fallLabel = newLabel( "fallThrough", stmt->location ); 383 382 if ( ! mutStmt->stmts.empty() ) { 383 // These should already be in a block. 384 auto first = mutStmt->stmts.front().get_and_mutate(); 385 auto block = strict_dynamic_cast<CompoundStmt *>( first ); 386 384 387 // Ensure that the stack isn't corrupted by exceptions in fixBlock. 385 388 auto guard = makeFuncGuard( 386 [&](){ enclosing_control_structures.emplace_back( mutStmt, fallLabel ); },389 [&](){ enclosing_control_structures.emplace_back( mutStmt, block, fallLabel ); }, 387 390 [this](){ enclosing_control_structures.pop_back(); } 388 391 ); 389 392 390 // These should already be in a block.391 auto block = mutate( mutStmt->stmts.front().strict_as<CompoundStmt>() );392 393 block->kids = fixBlock( block->kids, true ); 393 394 … … 396 397 Entry & entry = enclosing_control_structures.back(); 397 398 if ( entry.isFallUsed() ) { 398 mutStmt->stmts.push_back( labelledNullStmt( mutStmt->location, entry.useFallExit() ) );399 mutStmt->stmts.push_back( labelledNullStmt( block->location, entry.useFallExit() ) ); 399 400 } 400 401 } … … 433 434 } 434 435 435 bool isDefaultCase( const ptr<Stmt> & stmt ) { 436 const CaseStmt * caseStmt = stmt.strict_as<CaseStmt>(); 437 return caseStmt->isDefault(); 436 static bool isDefaultCase( const ptr<CaseClause> & caseClause ) { 437 return caseClause->isDefault(); 438 438 } 439 439 440 440 void MultiLevelExitCore::previsit( const SwitchStmt * stmt ) { 441 441 Label label = newLabel( "switchBreak", stmt ); 442 auto it = find_if( stmt-> stmts.rbegin(), stmt->stmts.rend(), isDefaultCase );443 444 const Case Stmt * defaultCase = it != stmt->stmts.rend() ? (it)->strict_as<CaseStmt>() : nullptr;445 Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ) : Label( stmt->location, "" );442 auto it = find_if( stmt->cases.rbegin(), stmt->cases.rend(), isDefaultCase ); 443 444 const CaseClause * defaultCase = it != stmt->cases.rend() ? (*it) : nullptr; 445 Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase->location ) : Label( stmt->location, "" ); 446 446 enclosing_control_structures.emplace_back( stmt, label, defaultLabel ); 447 447 GuardAction( [this]() { enclosing_control_structures.pop_back(); } ); … … 449 449 // Collect valid labels for fallthrough. It starts with all labels at this level, then remove as each is seen during 450 450 // traversal. 451 for ( const Stmt * stmt : stmt->stmts ) { 452 auto * caseStmt = strict_dynamic_cast< const CaseStmt * >( stmt ); 451 for ( const CaseClause * caseStmt : stmt->cases ) { 453 452 if ( caseStmt->stmts.empty() ) continue; 454 453 auto block = caseStmt->stmts.front().strict_as<CompoundStmt>(); … … 471 470 // exit label and break to the last case, create a default case if no cases. 472 471 SwitchStmt * mutStmt = mutate( stmt ); 473 if ( mutStmt-> stmts.empty() ) {474 mutStmt-> stmts.push_back( new CaseStmt( mutStmt->location, nullptr, {} ) );475 } 476 477 auto caseStmt = mutStmt-> stmts.back().strict_as<CaseStmt>();472 if ( mutStmt->cases.empty() ) { 473 mutStmt->cases.push_back( new CaseClause( mutStmt->location, nullptr, {} ) ); 474 } 475 476 auto caseStmt = mutStmt->cases.back().get(); 478 477 auto mutCase = mutate( caseStmt ); 479 mutStmt-> stmts.back() = mutCase;478 mutStmt->cases.back() = mutCase; 480 479 481 480 Label label( mutCase->location, "breakLabel" ); … … 514 513 } 515 514 516 void MultiLevelExitCore::previsit( const Finally Stmt* ) {515 void MultiLevelExitCore::previsit( const FinallyClause * ) { 517 516 GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); }); 518 517 enclosing_control_structures = vector<Entry>(); -
src/InitTweak/FixGlobalInit.cc
r4559b34 r92538ab 113 113 accept_all(translationUnit, fixer); 114 114 115 // Say these magic declarations come at the end of the file. 116 CodeLocation const & location = translationUnit.decls.back()->location; 117 115 118 if ( !fixer.core.initStmts.empty() ) { 116 119 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 if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int(location, 200)); 121 auto initFunction = new ast::FunctionDecl(location, 122 "__global_init__", {}, {}, {}, 123 new ast::CompoundStmt(location, std::move(fixer.core.initStmts)), 124 ast::Storage::Static, ast::Linkage::C, 125 {new ast::Attribute("constructor", std::move(ctorParams))}); 120 126 121 127 translationUnit.decls.emplace_back( initFunction ); … … 124 130 if ( !fixer.core.destroyStmts.empty() ) { 125 131 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))}); 132 if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int(location, 200)); 133 auto destroyFunction = new ast::FunctionDecl( location, 134 "__global_destroy__", {}, {}, {}, 135 new ast::CompoundStmt(location, std::move(fixer.core.destroyStmts)), 136 ast::Storage::Static, ast::Linkage::C, 137 {new ast::Attribute("destructor", std::move(dtorParams))}); 129 138 130 139 translationUnit.decls.emplace_back(destroyFunction); -
src/InitTweak/FixInitNew.cpp
r4559b34 r92538ab 16 16 #include "CodeGen/GenType.h" // for genPrettyType 17 17 #include "CodeGen/OperatorTable.h" 18 #include "Common/CodeLocationTools.hpp" 18 19 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 19 20 #include "Common/SemanticError.h" // for SemanticError … … 85 86 /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both 86 87 /// arguments and return value temporaries 87 struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors> {88 struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors>, public ast::WithConstTranslationUnit { 88 89 const ast::Expr * postvisit( const ast::ImplicitCopyCtorExpr * impCpCtorExpr ); 89 90 const ast::StmtExpr * previsit( const ast::StmtExpr * stmtExpr ); … … 189 190 /// for any member that is missing a corresponding ctor/dtor call. 190 191 /// error if a member is used before constructed 191 struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls> {192 struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls>, public ast::WithConstTranslationUnit { 192 193 void previsit( const ast::FunctionDecl * funcDecl ); 193 194 const ast::DeclWithType * postvisit( const ast::FunctionDecl * funcDecl ); … … 214 215 215 216 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 216 struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting {217 struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithConstTranslationUnit { 217 218 const ast::Expr * postvisit( const ast::ConstructorExpr * ctorExpr ); 218 219 }; … … 509 510 // (VariableExpr and already resolved expression) 510 511 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 511 ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, symtab);512 ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, { symtab, transUnit().global } ); 512 513 assert( resolved ); 513 514 if ( resolved->env ) { … … 553 554 ast::ptr<ast::Expr> guard = mutArg; 554 555 555 ast::ptr<ast::ObjectDecl> tmp = new ast::ObjectDecl( {}, "__tmp", mutResult, nullptr );556 ast::ptr<ast::ObjectDecl> tmp = new ast::ObjectDecl(loc, "__tmp", mutResult, nullptr ); 556 557 557 558 // create and resolve copy constructor … … 587 588 588 589 ast::Expr * ResolveCopyCtors::destructRet( const ast::ObjectDecl * ret, const ast::Expr * arg ) { 590 auto global = transUnit().global; 589 591 // TODO: refactor code for generating cleanup attribute, since it's common and reused in ~3-4 places 590 592 // check for existing cleanup attribute before adding another(?) 591 593 // need to add __Destructor for _tmp_cp variables as well 592 594 593 assertf( ast::dtorStruct, "Destructor generation requires __Destructor definition." );594 assertf( ast::dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );595 assertf( ast::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );595 assertf( global.dtorStruct, "Destructor generation requires __Destructor definition." ); 596 assertf( global.dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." ); 597 assertf( global.dtorDestroy, "Destructor generation requires __destroy_Destructor." ); 596 598 597 599 const CodeLocation loc = ret->location; … … 610 612 auto dtorFunc = getDtorFunc( ret, new ast::ExprStmt(loc, dtor ), stmtsToAddBefore ); 611 613 612 auto dtorStructType = new ast::StructInstType( ast::dtorStruct);614 auto dtorStructType = new ast::StructInstType( global.dtorStruct ); 613 615 614 616 // what does this do??? … … 622 624 static UniqueName namer( "_ret_dtor" ); 623 625 auto retDtor = new ast::ObjectDecl(loc, namer.newName(), dtorStructType, new ast::ListInit(loc, { new ast::SingleInit(loc, ast::ConstantExpr::null(loc) ), new ast::SingleInit(loc, new ast::CastExpr( new ast::VariableExpr(loc, dtorFunc ), dtorType ) ) } ) ); 624 retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, ast::dtorStructDestroy ) } ) );626 retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, global.dtorDestroy ) } ) ); 625 627 stmtsToAddBefore.push_back( new ast::DeclStmt(loc, retDtor ) ); 626 628 627 629 if ( arg ) { 628 auto member = new ast::MemberExpr(loc, ast::dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) );630 auto member = new ast::MemberExpr(loc, global.dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) ); 629 631 auto object = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, ret ) ), new ast::PointerType(new ast::VoidType() ) ); 630 632 ast::Expr * assign = createBitwiseAssignment( member, object ); … … 799 801 // to prevent warnings ('_unq0' may be used uninitialized in this function), 800 802 // insert an appropriate zero initializer for UniqueExpr temporaries. 801 ast::Init * makeInit( const ast::Type * t ) {803 ast::Init * makeInit( const ast::Type * t, CodeLocation const & loc ) { 802 804 if ( auto inst = dynamic_cast< const ast::StructInstType * >( t ) ) { 803 805 // initizer for empty struct must be empty 804 if ( inst->base->members.empty() ) return new ast::ListInit({}, {}); 806 if ( inst->base->members.empty() ) { 807 return new ast::ListInit( loc, {} ); 808 } 805 809 } else if ( auto inst = dynamic_cast< const ast::UnionInstType * >( t ) ) { 806 810 // initizer for empty union must be empty 807 if ( inst->base->members.empty() ) return new ast::ListInit({}, {}); 808 } 809 810 return new ast::ListInit( {}, { new ast::SingleInit( {}, ast::ConstantExpr::from_int({}, 0) ) } ); 811 if ( inst->base->members.empty() ) { 812 return new ast::ListInit( loc, {} ); 813 } 814 } 815 816 return new ast::ListInit( loc, { 817 new ast::SingleInit( loc, ast::ConstantExpr::from_int( loc, 0 ) ) 818 } ); 811 819 } 812 820 … … 832 840 } else { 833 841 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 834 mutExpr->object = new ast::ObjectDecl( mutExpr->location, toString("_unq", mutExpr->id), mutExpr->result, makeInit( mutExpr->result ) );842 mutExpr->object = new ast::ObjectDecl( mutExpr->location, toString("_unq", mutExpr->id), mutExpr->result, makeInit( mutExpr->result, mutExpr->location ) ); 835 843 mutExpr->var = new ast::VariableExpr( mutExpr->location, mutExpr->object ); 836 844 } … … 1172 1180 auto guard = makeFuncGuard( [this]() { symtab.enterScope(); }, [this]() { symtab.leaveScope(); } ); 1173 1181 symtab.addFunction( function ); 1182 auto global = transUnit().global; 1174 1183 1175 1184 // need to iterate through members in reverse in order for … … 1217 1226 1218 1227 static UniqueName memberDtorNamer = { "__memberDtor" }; 1219 assertf( ast::dtorStruct, "builtin __Destructor not found." );1220 assertf( ast::dtorStructDestroy, "builtin __destroy_Destructor not found." );1228 assertf( global.dtorStruct, "builtin __Destructor not found." ); 1229 assertf( global.dtorDestroy, "builtin __destroy_Destructor not found." ); 1221 1230 1222 1231 ast::Expr * thisExpr = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, thisParam ) ), new ast::PointerType( new ast::VoidType(), ast::CV::Qualifiers() ) ); … … 1228 1237 auto dtorType = new ast::PointerType( dtorFtype ); 1229 1238 1230 auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( ast::dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) );1231 destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr( {}, ast::dtorStructDestroy ) } ) );1239 auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( global.dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) ); 1240 destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr( loc, global.dtorDestroy ) } ) ); 1232 1241 mutStmts->push_front( new ast::DeclStmt(loc, destructor ) ); 1233 1242 mutStmts->kids.splice( mutStmts->kids.begin(), stmtsToAdd ); … … 1323 1332 1324 1333 const ast::Expr * GenStructMemberCalls::postvisit( const ast::UntypedExpr * untypedExpr ) { 1325 // Expression * newExpr = untypedExpr;1326 1334 // xxx - functions returning ast::ptr seems wrong... 1327 auto res = ResolvExpr::findVoidExpression( untypedExpr, symtab ); 1328 return res.release(); 1329 // return newExpr; 1335 auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } ); 1336 // Fix CodeLocation (at least until resolver is fixed). 1337 auto fix = localFillCodeLocations( untypedExpr->location, res.release() ); 1338 return strict_dynamic_cast<const ast::Expr *>( fix ); 1330 1339 } 1331 1340 … … 1361 1370 1362 1371 // resolve assignment and dispose of new env 1363 auto resolved = ResolvExpr::findVoidExpression( assign, symtab);1372 auto resolved = ResolvExpr::findVoidExpression( assign, { symtab, transUnit().global } ); 1364 1373 auto mut = resolved.get_and_mutate(); 1365 1374 assertf(resolved.get() == mut, "newly resolved expression must be unique"); -
src/InitTweak/InitTweak.cc
r4559b34 r92538ab 423 423 loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } }; 424 424 425 std::vector< ast::ptr< ast:: Stmt> > branches;425 std::vector< ast::ptr< ast::CaseClause > > branches; 426 426 for ( const ast::Init * init : *listInit ) { 427 427 auto condition = ast::ConstantExpr::from_ulong( loc, cond ); … … 432 432 stmts.emplace_back( 433 433 new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } ); 434 branches.emplace_back( new ast::Case Stmt{ loc, condition, std::move( stmts ) } );434 branches.emplace_back( new ast::CaseClause{ loc, condition, std::move( stmts ) } ); 435 435 } 436 436 out.emplace_back( new ast::SwitchStmt{ loc, index, std::move( branches ) } ); -
src/Parser/parser.yy
r4559b34 r92538ab 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 1 11:06:13202213 // Update Count : 5 16712 // Last Modified On : Mon Mar 14 16:35:29 2022 13 // Update Count : 5276 14 14 // 15 15 … … 610 610 // | RESUME '(' comma_expression ')' compound_statement 611 611 // { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; } 612 | IDENTIFIER IDENTIFIER // syntax error 613 { 614 SemanticError( yylloc, ::toString( "Adjacent identifiers are not meaningful in an expression. " 615 "Possible problem is identifier \"", *$1.str, 616 "\" is a misspelled typename or an incorrectly specified type name, " 617 "e.g., missing generic parameter or missing struct/union/enum before typename." ) ); 618 $$ = nullptr; 619 } 620 | IDENTIFIER direct_type // syntax error 621 { 622 SemanticError( yylloc, ::toString( "Identifier \"", *$1.str, "\" cannot appear before a type. " 623 "Possible problem is misspelled storage or CV qualifier." ) ); 624 $$ = nullptr; 625 } 612 626 ; 613 627 … … 638 652 // Historic, transitional: Disallow commas in subscripts. 639 653 // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts. 640 // { SemanticError( yylloc, "New array subscript is currently unimplemented." ); $$ = nullptr; }641 654 // Current: Commas in subscripts make tuples. 642 655 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); } … … 647 660 // equivalent to the old x[i,j]. 648 661 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); } 662 | constant '[' assignment_expression ']' // 3[a], 'a'[a], 3.5[a] 663 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); } 664 | string_literal '[' assignment_expression ']' // "abc"[3], 3["abc"] 665 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); } 649 666 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call 650 667 { … … 1052 1069 identifier_or_type_name ':' attribute_list_opt statement 1053 1070 { $$ = $4->add_label( $1, $3 ); } 1071 | identifier_or_type_name ':' attribute_list_opt error // syntax error 1072 { 1073 SemanticError( yylloc, ::toString( "Label \"", *$1.str, "\" must be associated with a statement, " 1074 "where a declaration, case, or default is not a statement. " 1075 "Move the label or terminate with a semi-colon." ) ); 1076 $$ = nullptr; 1077 } 1054 1078 ; 1055 1079 … … 1086 1110 | statement_list_nodecl statement 1087 1111 { assert( $1 ); $1->set_last( $2 ); $$ = $1; } 1112 | statement_list_nodecl error // syntax error 1113 { SemanticError( yylloc, "Declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; } 1088 1114 ; 1089 1115 … … 1093 1119 | MUTEX '(' ')' comma_expression ';' 1094 1120 { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); } 1095 // { SemanticError( yylloc, "Mutex expression is currently unimplemented." ); $$ = nullptr; }1096 1121 ; 1097 1122 … … 1113 1138 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1114 1139 } 1140 | SWITCH '(' comma_expression ')' '{' error '}' // CFA, syntax error 1141 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; } 1115 1142 | CHOOSE '(' comma_expression ')' case_clause // CFA 1116 1143 { $$ = new StatementNode( build_switch( false, $3, $5 ) ); } … … 1120 1147 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1121 1148 } 1149 | CHOOSE '(' comma_expression ')' '{' error '}' // CFA, syntax error 1150 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; } 1122 1151 ; 1123 1152 … … 1158 1187 1159 1188 case_label: // CFA 1160 CASE case_value_list ':' { $$ = $2; } 1189 CASE error // syntax error 1190 { SemanticError( yylloc, "Missing case list after case." ); $$ = nullptr; } 1191 | CASE case_value_list ':' { $$ = $2; } 1192 | CASE case_value_list error // syntax error 1193 { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; } 1161 1194 | DEFAULT ':' { $$ = new StatementNode( build_default() ); } 1162 1195 // A semantic check is required to ensure only one default clause per switch/choose statement. 1163 ; 1164 1165 //label_list_opt: 1166 // // empty 1167 // | identifier_or_type_name ':' 1168 // | label_list_opt identifier_or_type_name ':' 1169 // ; 1196 | DEFAULT error // syntax error 1197 { SemanticError( yylloc, "Missing colon after default." ); $$ = nullptr; } 1198 ; 1170 1199 1171 1200 case_label_list: // CFA … … 1197 1226 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); } 1198 1227 | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA 1199 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }1200 1228 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); } 1201 1229 | DO statement WHILE '(' ')' ';' // CFA => do while( 1 ) … … 1204 1232 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); } 1205 1233 | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA 1206 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }1207 1234 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); } 1208 1235 | FOR '(' ')' statement // CFA => for ( ;; ) … … 1211 1238 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); } 1212 1239 | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA 1213 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }1214 1240 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); } 1215 1241 ; … … 1406 1432 | when_clause_opt ELSE statement 1407 1433 { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); } 1408 1409 | when_clause_opt timeout statement WOR ELSE statement 1434 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1435 | when_clause_opt timeout statement WOR ELSE statement // syntax error 1410 1436 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1411 1437 | when_clause_opt timeout statement WOR when_clause ELSE statement … … 2735 2761 | ASM '(' string_literal ')' ';' // GCC, global assembler statement 2736 2762 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) ); } 2763 | EXTERN STRINGliteral 2764 { 2765 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 2766 linkage = LinkageSpec::update( yylloc, linkage, $2 ); 2767 } 2768 up external_definition down 2769 { 2770 linkage = linkageStack.top(); 2771 linkageStack.pop(); 2772 $$ = $5; 2773 } 2737 2774 | EXTERN STRINGliteral // C++-style linkage specifier 2738 2775 { -
src/ResolvExpr/CandidateFinder.cpp
r4559b34 r92538ab 10 10 // Created On : Wed Jun 5 14:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 1 14:55:00 201913 // Update Count : 212 // Last Modified On : Wed Mar 16 11:58:00 2022 13 // Update Count : 3 14 14 // 15 15 … … 595 595 /// Actually visits expressions to find their candidate interpretations 596 596 class Finder final : public ast::WithShortCircuiting { 597 const ResolveContext & context; 597 598 const ast::SymbolTable & symtab; 598 599 public: … … 618 619 619 620 Finder( CandidateFinder & f ) 620 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env),621 targetType( f.targetType ) {}621 : context( f.context ), symtab( context.symtab ), selfFinder( f ), 622 candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {} 622 623 623 624 void previsit( const ast::Node * ) { visit_children = false; } … … 872 873 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates ); 873 874 874 CandidateFinder funcFinder { symtab, tenv };875 CandidateFinder funcFinder( context, tenv ); 875 876 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) { 876 877 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); … … 918 919 // find function operators 919 920 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; 920 CandidateFinder opFinder { symtab, tenv };921 CandidateFinder opFinder( context, tenv ); 921 922 // okay if there aren't any function operations 922 923 opFinder.find( opExpr, ResolvMode::withoutFailFast() ); … … 1059 1060 1060 1061 void postvisit( const ast::AddressExpr * addressExpr ) { 1061 CandidateFinder finder { symtab, tenv };1062 CandidateFinder finder( context, tenv ); 1062 1063 finder.find( addressExpr->arg ); 1063 1064 … … 1079 1080 ast::ptr< ast::Type > toType = castExpr->result; 1080 1081 assert( toType ); 1081 toType = resolveTypeof( toType, symtab);1082 toType = resolveTypeof( toType, context ); 1082 1083 // toType = SymTab::validateType( castExpr->location, toType, symtab ); 1083 1084 toType = adjustExprType( toType, tenv, symtab ); 1084 1085 1085 CandidateFinder finder { symtab, tenv, toType };1086 CandidateFinder finder( context, tenv, toType ); 1086 1087 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1087 1088 … … 1136 1137 void postvisit( const ast::VirtualCastExpr * castExpr ) { 1137 1138 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." ); 1138 CandidateFinder finder { symtab, tenv };1139 CandidateFinder finder( context, tenv ); 1139 1140 // don't prune here, all alternatives guaranteed to have same type 1140 1141 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); … … 1153 1154 auto target = inst->base.get(); 1154 1155 1155 CandidateFinder finder { symtab, tenv };1156 CandidateFinder finder( context, tenv ); 1156 1157 1157 1158 auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) { … … 1202 1203 1203 1204 void postvisit( const ast::UntypedMemberExpr * memberExpr ) { 1204 CandidateFinder aggFinder { symtab, tenv };1205 CandidateFinder aggFinder( context, tenv ); 1205 1206 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1206 1207 for ( CandidateRef & agg : aggFinder.candidates ) { … … 1287 1288 addCandidate( 1288 1289 new ast::SizeofExpr{ 1289 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab) },1290 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) }, 1290 1291 tenv ); 1291 1292 } else { 1292 1293 // find all candidates for the argument to sizeof 1293 CandidateFinder finder { symtab, tenv };1294 CandidateFinder finder( context, tenv ); 1294 1295 finder.find( sizeofExpr->expr ); 1295 1296 // find the lowest-cost candidate, otherwise ambiguous … … 1311 1312 addCandidate( 1312 1313 new ast::AlignofExpr{ 1313 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab) },1314 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) }, 1314 1315 tenv ); 1315 1316 } else { 1316 1317 // find all candidates for the argument to alignof 1317 CandidateFinder finder { symtab, tenv };1318 CandidateFinder finder( context, tenv ); 1318 1319 finder.find( alignofExpr->expr ); 1319 1320 // find the lowest-cost candidate, otherwise ambiguous … … 1354 1355 1355 1356 void postvisit( const ast::LogicalExpr * logicalExpr ) { 1356 CandidateFinder finder1 { symtab, tenv };1357 CandidateFinder finder1( context, tenv ); 1357 1358 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() ); 1358 1359 if ( finder1.candidates.empty() ) return; 1359 1360 1360 CandidateFinder finder2 { symtab, tenv };1361 CandidateFinder finder2( context, tenv ); 1361 1362 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 1362 1363 if ( finder2.candidates.empty() ) return; … … 1384 1385 void postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1385 1386 // candidates for condition 1386 CandidateFinder finder1 { symtab, tenv };1387 CandidateFinder finder1( context, tenv ); 1387 1388 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() ); 1388 1389 if ( finder1.candidates.empty() ) return; 1389 1390 1390 1391 // candidates for true result 1391 CandidateFinder finder2 { symtab, tenv };1392 CandidateFinder finder2( context, tenv ); 1392 1393 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 1393 1394 if ( finder2.candidates.empty() ) return; 1394 1395 1395 1396 // candidates for false result 1396 CandidateFinder finder3 { symtab, tenv };1397 CandidateFinder finder3( context, tenv ); 1397 1398 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1398 1399 if ( finder3.candidates.empty() ) return; … … 1445 1446 void postvisit( const ast::CommaExpr * commaExpr ) { 1446 1447 ast::TypeEnvironment env{ tenv }; 1447 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );1448 1449 CandidateFinder finder2 { symtab, env };1448 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env ); 1449 1450 CandidateFinder finder2( context, env ); 1450 1451 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); 1451 1452 … … 1460 1461 1461 1462 void postvisit( const ast::ConstructorExpr * ctorExpr ) { 1462 CandidateFinder finder { symtab, tenv };1463 CandidateFinder finder( context, tenv ); 1463 1464 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() ); 1464 1465 for ( CandidateRef & r : finder.candidates ) { … … 1469 1470 void postvisit( const ast::RangeExpr * rangeExpr ) { 1470 1471 // resolve low and high, accept candidates where low and high types unify 1471 CandidateFinder finder1 { symtab, tenv };1472 CandidateFinder finder1( context, tenv ); 1472 1473 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() ); 1473 1474 if ( finder1.candidates.empty() ) return; 1474 1475 1475 CandidateFinder finder2 { symtab, tenv };1476 CandidateFinder finder2( context, tenv ); 1476 1477 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 1477 1478 if ( finder2.candidates.empty() ) return; … … 1549 1550 1550 1551 void postvisit( const ast::UniqueExpr * unqExpr ) { 1551 CandidateFinder finder { symtab, tenv };1552 CandidateFinder finder( context, tenv ); 1552 1553 finder.find( unqExpr->expr, ResolvMode::withAdjustment() ); 1553 1554 for ( CandidateRef & r : finder.candidates ) { … … 1558 1559 1559 1560 void postvisit( const ast::StmtExpr * stmtExpr ) { 1560 addCandidate( resolveStmtExpr( stmtExpr, symtab), tenv );1561 addCandidate( resolveStmtExpr( stmtExpr, context ), tenv ); 1561 1562 } 1562 1563 … … 1570 1571 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) { 1571 1572 // calculate target type 1572 const ast::Type * toType = resolveTypeof( initAlt.type, symtab);1573 const ast::Type * toType = resolveTypeof( initAlt.type, context ); 1573 1574 // toType = SymTab::validateType( initExpr->location, toType, symtab ); 1574 1575 toType = adjustExprType( toType, tenv, symtab ); … … 1576 1577 // types are not bound to the initialization type, since return type variables are 1577 1578 // only open for the duration of resolving the UntypedExpr. 1578 CandidateFinder finder { symtab, tenv, toType };1579 CandidateFinder finder( context, tenv, toType ); 1579 1580 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1580 1581 for ( CandidateRef & cand : finder.candidates ) { … … 1693 1694 } 1694 1695 else { 1695 satisfyAssertions(candidate, localSyms, satisfied, errors);1696 satisfyAssertions(candidate, context.symtab, satisfied, errors); 1696 1697 needRecomputeKey = true; 1697 1698 } … … 1855 1856 r->expr = ast::mutate_field( 1856 1857 r->expr.get(), &ast::Expr::result, 1857 adjustExprType( r->expr->result, r->env, localSyms) );1858 adjustExprType( r->expr->result, r->env, context.symtab ) ); 1858 1859 } 1859 1860 } … … 1873 1874 1874 1875 for ( const auto & x : xs ) { 1875 out.emplace_back( localSyms, env );1876 out.emplace_back( context, env ); 1876 1877 out.back().find( x, ResolvMode::withAdjustment() ); 1877 1878 -
src/ResolvExpr/CandidateFinder.hpp
r4559b34 r92538ab 10 10 // Created On : Wed Jun 5 14:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Oct 1 9:51:00 201913 // Update Count : 212 // Last Modified On : Wed Mar 16 15:22:00 2022 13 // Update Count : 3 14 14 // 15 15 … … 25 25 namespace ResolvExpr { 26 26 27 struct ResolveContext; 28 27 29 /// Data to perform expression resolution 28 30 struct CandidateFinder { 29 31 CandidateList candidates; ///< List of candidate resolutions 30 const ast::SymbolTable & localSyms; ///< Symbol table to lookup candidates32 const ResolveContext & context; ///< Information about where the canditates are being found. 31 33 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 32 34 ast::ptr< ast::Type > targetType; ///< Target type for resolution … … 34 36 35 37 CandidateFinder( 36 const ast::SymbolTable & syms, const ast::TypeEnvironment & env,38 const ResolveContext & context, const ast::TypeEnvironment & env, 37 39 const ast::Type * tt = nullptr ) 38 : candidates(), localSyms( syms), env( env ), targetType( tt ) {}40 : candidates(), context( context ), env( env ), targetType( tt ) {} 39 41 40 42 /// Fill candidates with feasible resolutions for `expr` -
src/ResolvExpr/CandidatePrinter.cpp
r4559b34 r92538ab 10 10 // Created On : Tue Nov 9 9:54:00 2021 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Nov 9 15:47:00 202113 // Update Count : 012 // Last Modified On : Wed Mar 16 13:56:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 22 22 #include "AST/TranslationUnit.hpp" 23 23 #include "ResolvExpr/CandidateFinder.hpp" 24 #include "ResolvExpr/Resolver.h" 24 25 25 26 #include <iostream> … … 29 30 namespace { 30 31 31 class CandidatePrintCore : public ast::WithSymbolTable { 32 class CandidatePrintCore : public ast::WithSymbolTable, 33 public ast::WithConstTranslationUnit { 32 34 std::ostream & os; 33 35 public: … … 36 38 void postvisit( const ast::ExprStmt * stmt ) { 37 39 ast::TypeEnvironment env; 38 CandidateFinder finder( symtab, env );40 CandidateFinder finder( { symtab, transUnit().global }, env ); 39 41 finder.find( stmt->expr, ResolvMode::withAdjustment() ); 40 42 int count = 1; -
src/ResolvExpr/RenameVars.h
r4559b34 r92538ab 36 36 }; 37 37 const ast::Type * renameTyVars( const ast::Type *, RenameMode mode = GEN_USAGE, bool reset = true ); 38 39 38 40 39 /// resets internal state of renamer to avoid overflow 41 40 void resetTyVarRenaming(); 42 43 44 41 } // namespace ResolvExpr 45 42 -
src/ResolvExpr/ResolveTypeof.cc
r4559b34 r92538ab 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:12:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue May 19 16:49:04 201513 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 16:09:00 2022 13 // Update Count : 4 14 14 // 15 15 … … 22 22 #include "AST/Node.hpp" 23 23 #include "AST/Pass.hpp" 24 #include "AST/TranslationUnit.hpp" 24 25 #include "AST/Type.hpp" 25 26 #include "AST/TypeEnvironment.hpp" … … 119 120 namespace { 120 121 struct ResolveTypeof_new : public ast::WithShortCircuiting { 121 const ast::SymbolTable & localSymtab; 122 123 ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {} 122 const ResolveContext & context; 123 124 ResolveTypeof_new( const ResolveContext & context ) : 125 context( context ) {} 124 126 125 127 void previsit( const ast::TypeofType * ) { visit_children = false; } … … 137 139 ast::TypeEnvironment dummy; 138 140 ast::ptr< ast::Expr > newExpr = 139 resolveInVoidContext( typeofType->expr, localSymtab, dummy );141 resolveInVoidContext( typeofType->expr, context, dummy ); 140 142 assert( newExpr->result && ! newExpr->result->isVoid() ); 141 143 newType = newExpr->result; … … 161 163 } // anonymous namespace 162 164 163 const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab) {164 ast::Pass< ResolveTypeof_new > mutator { symtab };165 const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) { 166 ast::Pass< ResolveTypeof_new > mutator( context ); 165 167 return type->accept( mutator ); 166 168 } 167 169 168 170 struct FixArrayDimension { 169 // should not require a mutable symbol table - prevent pass template instantiation 170 const ast::SymbolTable & _symtab; 171 FixArrayDimension(const ast::SymbolTable & symtab): _symtab(symtab) {} 171 const ResolveContext & context; 172 FixArrayDimension(const ResolveContext & context) : context( context ) {} 172 173 173 174 const ast::ArrayType * previsit (const ast::ArrayType * arrayType) { 174 175 if (!arrayType->dimension) return arrayType; 175 176 auto mutType = mutate(arrayType); 176 ast::ptr<ast::Type> sizetype = ast::sizeType ? ast::sizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt); 177 mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, _symtab); 177 auto globalSizeType = context.global.sizeType; 178 ast::ptr<ast::Type> sizetype = globalSizeType ? globalSizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt); 179 mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, context ); 178 180 179 181 if (InitTweak::isConstExpr(mutType->dimension)) { … … 187 189 }; 188 190 189 const ast::Type * fixArrayType( const ast::Type * type, const ast::SymbolTable & symtab) {190 ast::Pass<FixArrayDimension> visitor {symtab};191 const ast::Type * fixArrayType( const ast::Type * type, const ResolveContext & context ) { 192 ast::Pass<FixArrayDimension> visitor(context); 191 193 return type->accept(visitor); 192 194 } 193 195 194 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab ) { 195 if (!decl->isTypeFixed) { 196 auto mutDecl = mutate(decl); 197 auto resolvedType = resolveTypeof(decl->type, symtab); 198 resolvedType = fixArrayType(resolvedType, symtab); 196 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) { 197 if (decl->isTypeFixed) { 198 return decl; 199 } 200 201 auto mutDecl = mutate(decl); 202 { 203 auto resolvedType = resolveTypeof(decl->type, context); 204 resolvedType = fixArrayType(resolvedType, context); 199 205 mutDecl->type = resolvedType; 200 201 // check variable length if object is an array. 202 // xxx - should this be part of fixObjectType? 203 204 /* 205 if (auto arrayType = dynamic_cast<const ast::ArrayType *>(resolvedType)) { 206 auto dimExpr = findSingleExpression(arrayType->dimension, ast::sizeType, symtab); 207 if (auto varexpr = arrayType->dimension.as<ast::VariableExpr>()) {// hoisted previously 208 if (InitTweak::isConstExpr(varexpr->var.strict_as<ast::ObjectDecl>()->init)) { 209 auto mutType = mutate(arrayType); 210 mutType->isVarLen = ast::LengthFlag::VariableLen; 211 mutDecl->type = mutType; 212 } 213 } 214 } 215 */ 216 217 218 if (!mutDecl->name.empty()) 219 mutDecl->mangleName = Mangle::mangle(mutDecl); // do not mangle unnamed variables 220 221 mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID); 222 mutDecl->isTypeFixed = true; 223 return mutDecl; 224 } 225 return decl; 206 } 207 208 // Do not mangle unnamed variables. 209 if (!mutDecl->name.empty()) { 210 mutDecl->mangleName = Mangle::mangle(mutDecl); 211 } 212 213 mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID); 214 mutDecl->isTypeFixed = true; 215 return mutDecl; 226 216 } 227 217 -
src/ResolvExpr/ResolveTypeof.h
r4559b34 r92538ab 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ResolveTypeof.h -- 7 // ResolveTypeof.h -- 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:14:53 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:38:35 201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 11:33:00 2022 13 // Update Count : 4 14 14 // 15 15 … … 22 22 namespace ast { 23 23 class Type; 24 class SymbolTable;25 24 class ObjectDecl; 26 25 } 27 26 28 27 namespace ResolvExpr { 28 struct ResolveContext; 29 29 30 Type *resolveTypeof( Type*, const SymTab::Indexer &indexer ); 30 const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable& );31 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab);31 const ast::Type * resolveTypeof( const ast::Type *, const ResolveContext & ); 32 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & ); 32 33 } // namespace ResolvExpr 33 34 -
src/ResolvExpr/Resolver.cc
r4559b34 r92538ab 9 9 // Author : Aaron B. Moss 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue Feb 1 16:27:14202213 // Update Count : 24 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 18 10:41:00 2022 13 // Update Count : 247 14 14 // 15 15 … … 997 997 /// Calls the CandidateFinder and finds the single best candidate 998 998 CandidateRef findUnfinishedKindExpression( 999 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,999 const ast::Expr * untyped, const ResolveContext & context, const std::string & kind, 1000 1000 std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {} 1001 1001 ) { … … 1007 1007 ++recursion_level; 1008 1008 ast::TypeEnvironment env; 1009 CandidateFinder finder { symtab, env };1009 CandidateFinder finder( context, env ); 1010 1010 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 1011 1011 --recursion_level; … … 1129 1129 1130 1130 ast::ptr< ast::Expr > resolveInVoidContext( 1131 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1131 const ast::Expr * expr, const ResolveContext & context, 1132 ast::TypeEnvironment & env 1132 1133 ) { 1133 1134 assertf( expr, "expected a non-null expression" ); … … 1136 1137 ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr }; 1137 1138 CandidateRef choice = findUnfinishedKindExpression( 1138 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );1139 untyped, context, "", anyCandidate, ResolvMode::withAdjustment() ); 1139 1140 1140 1141 // a cast expression has either 0 or 1 interpretations (by language rules); … … 1149 1150 /// context. 1150 1151 ast::ptr< ast::Expr > findVoidExpression( 1151 const ast::Expr * untyped, const ast::SymbolTable & symtab1152 const ast::Expr * untyped, const ResolveContext & context 1152 1153 ) { 1153 1154 ast::TypeEnvironment env; 1154 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );1155 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env ); 1155 1156 finishExpr( newExpr, env, untyped->env ); 1156 1157 return newExpr; … … 1163 1164 /// lowest cost, returning the resolved version 1164 1165 ast::ptr< ast::Expr > findKindExpression( 1165 const ast::Expr * untyped, const ast::SymbolTable & symtab,1166 const ast::Expr * untyped, const ResolveContext & context, 1166 1167 std::function<bool(const Candidate &)> pred = anyCandidate, 1167 1168 const std::string & kind = "", ResolvMode mode = {} … … 1169 1170 if ( ! untyped ) return {}; 1170 1171 CandidateRef choice = 1171 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );1172 findUnfinishedKindExpression( untyped, context, kind, pred, mode ); 1172 1173 ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env ); 1173 1174 return std::move( choice->expr ); … … 1176 1177 /// Resolve `untyped` to the single expression whose candidate is the best match 1177 1178 ast::ptr< ast::Expr > findSingleExpression( 1178 const ast::Expr * untyped, const ast::SymbolTable & symtab1179 const ast::Expr * untyped, const ResolveContext & context 1179 1180 ) { 1180 1181 Stats::ResolveTime::start( untyped ); 1181 auto res = findKindExpression( untyped, symtab);1182 auto res = findKindExpression( untyped, context ); 1182 1183 Stats::ResolveTime::stop(); 1183 1184 return res; … … 1186 1187 1187 1188 ast::ptr< ast::Expr > findSingleExpression( 1188 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab 1189 const ast::Expr * untyped, const ast::Type * type, 1190 const ResolveContext & context 1189 1191 ) { 1190 1192 assert( untyped && type ); 1191 1193 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type }; 1192 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab);1193 removeExtraneousCast( newExpr, symtab );1194 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context ); 1195 removeExtraneousCast( newExpr, context.symtab ); 1194 1196 return newExpr; 1195 1197 } … … 1217 1219 /// Resolve `untyped` as an integral expression, returning the resolved version 1218 1220 ast::ptr< ast::Expr > findIntegralExpression( 1219 const ast::Expr * untyped, const ast::SymbolTable & symtab1221 const ast::Expr * untyped, const ResolveContext & context 1220 1222 ) { 1221 return findKindExpression( untyped, symtab, hasIntegralType, "condition" );1223 return findKindExpression( untyped, context, hasIntegralType, "condition" ); 1222 1224 } 1223 1225 … … 1249 1251 // for work previously in GenInit 1250 1252 static InitTweak::ManagedTypes_new managedTypes; 1253 ResolveContext context; 1251 1254 1252 1255 bool inEnumDecl = false; … … 1254 1257 public: 1255 1258 static size_t traceId; 1256 Resolver_new() = default; 1257 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } 1259 Resolver_new( const ast::TranslationGlobal & global ) : 1260 context{ symtab, global } {} 1261 Resolver_new( const ResolveContext & context ) : 1262 ast::WithSymbolTable{ context.symtab }, 1263 context{ symtab, context.global } {} 1258 1264 1259 1265 const ast::FunctionDecl * previsit( const ast::FunctionDecl * ); … … 1272 1278 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 1273 1279 const ast::IfStmt * previsit( const ast::IfStmt * ); 1274 const ast::WhileDoStmt * 1280 const ast::WhileDoStmt * previsit( const ast::WhileDoStmt * ); 1275 1281 const ast::ForStmt * previsit( const ast::ForStmt * ); 1276 1282 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 1277 const ast::Case Stmt * previsit( const ast::CaseStmt* );1283 const ast::CaseClause * previsit( const ast::CaseClause * ); 1278 1284 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 1279 1285 const ast::ReturnStmt * previsit( const ast::ReturnStmt * ); 1280 1286 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 1281 const ast::Catch Stmt * previsit( const ast::CatchStmt* );1282 const ast::Catch Stmt * postvisit( const ast::CatchStmt* );1287 const ast::CatchClause * previsit( const ast::CatchClause * ); 1288 const ast::CatchClause * postvisit( const ast::CatchClause * ); 1283 1289 const ast::WaitForStmt * previsit( const ast::WaitForStmt * ); 1284 1290 const ast::WithStmt * previsit( const ast::WithStmt * ); … … 1299 1305 1300 1306 void resolve( ast::TranslationUnit& translationUnit ) { 1301 ast::Pass< Resolver_new >::run( translationUnit );1307 ast::Pass< Resolver_new >::run( translationUnit, translationUnit.global ); 1302 1308 } 1303 1309 1304 1310 ast::ptr< ast::Init > resolveCtorInit( 1305 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab1311 const ast::ConstructorInit * ctorInit, const ResolveContext & context 1306 1312 ) { 1307 1313 assert( ctorInit ); 1308 ast::Pass< Resolver_new > resolver { symtab };1314 ast::Pass< Resolver_new > resolver( context ); 1309 1315 return ctorInit->accept( resolver ); 1310 1316 } 1311 1317 1312 1318 const ast::Expr * resolveStmtExpr( 1313 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab1319 const ast::StmtExpr * stmtExpr, const ResolveContext & context 1314 1320 ) { 1315 1321 assert( stmtExpr ); 1316 ast::Pass< Resolver_new > resolver { symtab };1322 ast::Pass< Resolver_new > resolver( context ); 1317 1323 auto ret = mutate(stmtExpr->accept(resolver)); 1318 1324 strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult(); … … 1321 1327 1322 1328 namespace { 1323 const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {1329 const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) { 1324 1330 std::string name = attr->normalizedName(); 1325 1331 if (name == "constructor" || name == "destructor") { 1326 1332 if (attr->params.size() == 1) { 1327 1333 auto arg = attr->params.front(); 1328 auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab);1334 auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context ); 1329 1335 auto result = eval(arg); 1330 1336 … … 1369 1375 1370 1376 for (auto & attr: mutDecl->attributes) { 1371 attr = handleAttribute(mutDecl->location, attr, symtab);1377 attr = handleAttribute(mutDecl->location, attr, context ); 1372 1378 } 1373 1379 … … 1379 1385 for (auto & typeParam : mutDecl->type_params) { 1380 1386 symtab.addType(typeParam); 1381 mutType->forall.emplace_back(new ast::TypeInstType(typeParam ->name, typeParam));1387 mutType->forall.emplace_back(new ast::TypeInstType(typeParam)); 1382 1388 } 1383 1389 for (auto & asst : mutDecl->assertions) { 1384 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);1390 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context); 1385 1391 symtab.addId(asst); 1386 1392 mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst)); … … 1394 1400 1395 1401 for (auto & param : mutDecl->params) { 1396 param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);1402 param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context); 1397 1403 symtab.addId(param); 1398 1404 paramTypes.emplace_back(param->get_type()); 1399 1405 } 1400 1406 for (auto & ret : mutDecl->returns) { 1401 ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);1407 ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context); 1402 1408 returnTypes.emplace_back(ret->get_type()); 1403 1409 } … … 1498 1504 else { 1499 1505 if (!objectDecl->isTypeFixed) { 1500 auto newDecl = fixObjectType(objectDecl, symtab);1506 auto newDecl = fixObjectType(objectDecl, context); 1501 1507 auto mutDecl = mutate(newDecl); 1502 1508 … … 1529 1535 // nested type decls are hoisted already. no need to do anything 1530 1536 if (auto obj = member.as<ast::ObjectDecl>()) { 1531 member = fixObjectType(obj, symtab);1537 member = fixObjectType(obj, context); 1532 1538 } 1533 1539 } … … 1552 1558 return ast::mutate_field( 1553 1559 assertDecl, &ast::StaticAssertDecl::cond, 1554 findIntegralExpression( assertDecl->cond, symtab) );1560 findIntegralExpression( assertDecl->cond, context ) ); 1555 1561 } 1556 1562 1557 1563 template< typename PtrType > 1558 const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab) {1564 const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) { 1559 1565 if ( type->dimension ) { 1560 ast::ptr< ast::Type > sizeType = ast::sizeType;1566 ast::ptr< ast::Type > sizeType = context.global.sizeType; 1561 1567 ast::mutate_field( 1562 1568 type, &PtrType::dimension, 1563 findSingleExpression( type->dimension, sizeType, symtab) );1569 findSingleExpression( type->dimension, sizeType, context ) ); 1564 1570 } 1565 1571 return type; … … 1567 1573 1568 1574 const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) { 1569 return handlePtrType( at, symtab);1575 return handlePtrType( at, context ); 1570 1576 } 1571 1577 1572 1578 const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) { 1573 return handlePtrType( pt, symtab);1579 return handlePtrType( pt, context ); 1574 1580 } 1575 1581 … … 1579 1585 1580 1586 return ast::mutate_field( 1581 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab) );1587 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) ); 1582 1588 } 1583 1589 … … 1586 1592 1587 1593 asmExpr = ast::mutate_field( 1588 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab) );1594 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) ); 1589 1595 1590 1596 return asmExpr; … … 1600 1606 const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1601 1607 return ast::mutate_field( 1602 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab) );1608 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) ); 1603 1609 } 1604 1610 1605 1611 const ast::WhileDoStmt * Resolver_new::previsit( const ast::WhileDoStmt * whileDoStmt ) { 1606 1612 return ast::mutate_field( 1607 whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, symtab) );1613 whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) ); 1608 1614 } 1609 1615 … … 1611 1617 if ( forStmt->cond ) { 1612 1618 forStmt = ast::mutate_field( 1613 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab) );1619 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) ); 1614 1620 } 1615 1621 1616 1622 if ( forStmt->inc ) { 1617 1623 forStmt = ast::mutate_field( 1618 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab) );1624 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) ); 1619 1625 } 1620 1626 … … 1626 1632 switchStmt = ast::mutate_field( 1627 1633 switchStmt, &ast::SwitchStmt::cond, 1628 findIntegralExpression( switchStmt->cond, symtab) );1634 findIntegralExpression( switchStmt->cond, context ) ); 1629 1635 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result }; 1630 1636 return switchStmt; 1631 1637 } 1632 1638 1633 const ast::Case Stmt * Resolver_new::previsit( const ast::CaseStmt* caseStmt ) {1639 const ast::CaseClause * Resolver_new::previsit( const ast::CaseClause * caseStmt ) { 1634 1640 if ( caseStmt->cond ) { 1635 1641 std::deque< ast::InitAlternative > initAlts = currentObject.getOptions(); … … 1639 1645 ast::ptr< ast::Expr > untyped = 1640 1646 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1641 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab);1647 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context ); 1642 1648 1643 1649 // case condition cannot have a cast in C, so it must be removed here, regardless of … … 1647 1653 } 1648 1654 1649 caseStmt = ast::mutate_field( caseStmt, &ast::Case Stmt::cond, newExpr );1655 caseStmt = ast::mutate_field( caseStmt, &ast::CaseClause::cond, newExpr ); 1650 1656 } 1651 1657 return caseStmt; … … 1660 1666 branchStmt = ast::mutate_field( 1661 1667 branchStmt, &ast::BranchStmt::computedTarget, 1662 findSingleExpression( branchStmt->computedTarget, target, symtab) );1668 findSingleExpression( branchStmt->computedTarget, target, context ) ); 1663 1669 } 1664 1670 return branchStmt; … … 1670 1676 returnStmt = ast::mutate_field( 1671 1677 returnStmt, &ast::ReturnStmt::expr, 1672 findSingleExpression( returnStmt->expr, functionReturn, symtab) );1678 findSingleExpression( returnStmt->expr, functionReturn, context ) ); 1673 1679 } 1674 1680 return returnStmt; … … 1685 1691 throwStmt = ast::mutate_field( 1686 1692 throwStmt, &ast::ThrowStmt::expr, 1687 findSingleExpression( throwStmt->expr, exceptType, symtab) );1693 findSingleExpression( throwStmt->expr, exceptType, context ) ); 1688 1694 } 1689 1695 return throwStmt; 1690 1696 } 1691 1697 1692 const ast::Catch Stmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt) {1698 const ast::CatchClause * Resolver_new::previsit( const ast::CatchClause * catchClause ) { 1693 1699 // Until we are very sure this invarent (ifs that move between passes have then) 1694 1700 // holds, check it. This allows a check for when to decode the mangling. 1695 if ( auto ifStmt = catch Stmt->body.as<ast::IfStmt>() ) {1701 if ( auto ifStmt = catchClause->body.as<ast::IfStmt>() ) { 1696 1702 assert( ifStmt->then ); 1697 1703 } 1698 1704 // Encode the catchStmt so the condition can see the declaration. 1699 if ( catch Stmt->cond ) {1700 ast::Catch Stmt * stmt = mutate( catchStmt);1701 stmt->body = new ast::IfStmt( stmt->location, stmt->cond, nullptr, stmt->body );1702 stmt->cond = nullptr;1703 return stmt;1704 } 1705 return catch Stmt;1706 } 1707 1708 const ast::Catch Stmt * Resolver_new::postvisit( const ast::CatchStmt * catchStmt) {1705 if ( catchClause->cond ) { 1706 ast::CatchClause * clause = mutate( catchClause ); 1707 clause->body = new ast::IfStmt( clause->location, clause->cond, nullptr, clause->body ); 1708 clause->cond = nullptr; 1709 return clause; 1710 } 1711 return catchClause; 1712 } 1713 1714 const ast::CatchClause * Resolver_new::postvisit( const ast::CatchClause * catchClause ) { 1709 1715 // Decode the catchStmt so everything is stored properly. 1710 const ast::IfStmt * ifStmt = catch Stmt->body.as<ast::IfStmt>();1716 const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>(); 1711 1717 if ( nullptr != ifStmt && nullptr == ifStmt->then ) { 1712 1718 assert( ifStmt->cond ); 1713 1719 assert( ifStmt->else_ ); 1714 ast::Catch Stmt * stmt = ast::mutate( catchStmt);1715 stmt->cond = ifStmt->cond;1716 stmt->body = ifStmt->else_;1720 ast::CatchClause * clause = ast::mutate( catchClause ); 1721 clause->cond = ifStmt->cond; 1722 clause->body = ifStmt->else_; 1717 1723 // ifStmt should be implicately deleted here. 1718 return stmt;1719 } 1720 return catch Stmt;1724 return clause; 1725 } 1726 return catchClause; 1721 1727 } 1722 1728 … … 1729 1735 1730 1736 ast::TypeEnvironment env; 1731 CandidateFinder funcFinder { symtab, env };1737 CandidateFinder funcFinder( context, env ); 1732 1738 1733 1739 // Find all candidates for a function in canonical form … … 1943 1949 ); 1944 1950 1945 clause2.target.args.emplace_back( findSingleExpression( init, symtab) );1951 clause2.target.args.emplace_back( findSingleExpression( init, context ) ); 1946 1952 } 1947 1953 1948 1954 // Resolve the conditions as if it were an IfStmt, statements normally 1949 clause2.cond = findSingleExpression( clause.cond, symtab);1955 clause2.cond = findSingleExpression( clause.cond, context ); 1950 1956 clause2.stmt = clause.stmt->accept( *visitor ); 1951 1957 … … 1962 1968 ast::ptr< ast::Type > target = 1963 1969 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1964 timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab);1965 timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab);1970 timeout2.time = findSingleExpression( stmt->timeout.time, target, context ); 1971 timeout2.cond = findSingleExpression( stmt->timeout.cond, context ); 1966 1972 timeout2.stmt = stmt->timeout.stmt->accept( *visitor ); 1967 1973 … … 1976 1982 ast::WaitForStmt::OrElse orElse2; 1977 1983 1978 orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab);1984 orElse2.cond = findSingleExpression( stmt->orElse.cond, context ); 1979 1985 orElse2.stmt = stmt->orElse.stmt->accept( *visitor ); 1980 1986 … … 1997 2003 for (auto & expr : exprs) { 1998 2004 // only struct- and union-typed expressions are viable candidates 1999 expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );2005 expr = findKindExpression( expr, context, structOrUnion, "with expression" ); 2000 2006 2001 2007 // if with expression might be impure, create a temporary so that it is evaluated once … … 2023 2029 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{ 2024 2030 singleInit->location, singleInit->value, currentObject.getOptions() }; 2025 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab);2031 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context ); 2026 2032 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 2027 2033 -
src/ResolvExpr/Resolver.h
r4559b34 r92538ab 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:18:34 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Feb 18 20:40:38 201913 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 11:32:00 2022 13 // Update Count : 5 14 14 // 15 15 … … 23 23 class Declaration; 24 24 class Expression; 25 class DeletedExpr; 25 26 class StmtExpr; 27 class Type; 26 28 namespace SymTab { 27 29 class Indexer; … … 35 37 class StmtExpr; 36 38 class SymbolTable; 39 class TranslationGlobal; 37 40 class TranslationUnit; 38 41 class Type; … … 55 58 void resolveWithExprs( std::list< Declaration * > & translationUnit ); 56 59 60 /// Helper Type: Passes around information between various sub-calls. 61 struct ResolveContext { 62 const ast::SymbolTable & symtab; 63 const ast::TranslationGlobal & global; 64 }; 65 57 66 /// Checks types and binds syntactic constructs to typed representations 58 67 void resolve( ast::TranslationUnit& translationUnit ); … … 62 71 /// context. 63 72 ast::ptr< ast::Expr > resolveInVoidContext( 64 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );73 const ast::Expr * expr, const ResolveContext &, ast::TypeEnvironment & env ); 65 74 /// Resolve `untyped` to the single expression whose candidate is the best match for the 66 75 /// given type. 67 76 ast::ptr< ast::Expr > findSingleExpression( 68 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab);77 const ast::Expr * untyped, const ast::Type * type, const ResolveContext & ); 69 78 ast::ptr< ast::Expr > findVoidExpression( 70 const ast::Expr * untyped, const ast::SymbolTable & symtab);79 const ast::Expr * untyped, const ResolveContext & ); 71 80 /// Resolves a constructor init expression 72 81 ast::ptr< ast::Init > resolveCtorInit( 73 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab);82 const ast::ConstructorInit * ctorInit, const ResolveContext & context ); 74 83 /// Resolves a statement expression 75 84 const ast::Expr * resolveStmtExpr( 76 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab);85 const ast::StmtExpr * stmtExpr, const ResolveContext & context ); 77 86 } // namespace ResolvExpr 78 87 -
src/ResolvExpr/Unify.cc
r4559b34 r92538ab 943 943 // check that the other type is compatible and named the same 944 944 auto otherInst = dynamic_cast< const XInstType * >( other ); 945 this->result = otherInst && inst->name == otherInst->name;945 if (otherInst && inst->name == otherInst->name) this->result = otherInst; 946 946 return otherInst; 947 947 } -
src/SymTab/Validate.cc
r4559b34 r92538ab 194 194 }; 195 195 196 // These structs are the sub-sub-passes of ForallPointerDecay_old. 197 198 struct TraitExpander_old final { 199 void previsit( FunctionType * ); 200 void previsit( StructDecl * ); 201 void previsit( UnionDecl * ); 202 }; 203 204 struct AssertionFixer_old final { 205 void previsit( FunctionType * ); 206 void previsit( StructDecl * ); 207 void previsit( UnionDecl * ); 208 }; 209 210 struct CheckOperatorTypes_old final { 211 void previsit( ObjectDecl * ); 212 }; 213 214 struct FixUniqueIds_old final { 215 void previsit( DeclarationWithType * ); 216 }; 217 196 218 struct ReturnChecker : public WithGuards { 197 219 /// Checks that return statements return nothing if their return type is void … … 373 395 TranslateDimensionGenericParameters::translateDimensions( translationUnit ); 374 396 }); 397 if (!useNewAST) { 375 398 Stats::Time::TimeBlock("Resolve Enum Initializers", [&]() { 376 399 acceptAll( translationUnit, rei ); // must happen after translateDimensions because rei needs identifier lookup, which needs name mangling 377 400 }); 401 } 378 402 Stats::Time::TimeBlock("Check Function Returns", [&]() { 379 403 ReturnChecker::checkFunctionReturns( translationUnit ); … … 385 409 } 386 410 411 static void decayForallPointers( std::list< Declaration * > & translationUnit ) { 412 PassVisitor<TraitExpander_old> te; 413 acceptAll( translationUnit, te ); 414 PassVisitor<AssertionFixer_old> af; 415 acceptAll( translationUnit, af ); 416 PassVisitor<CheckOperatorTypes_old> cot; 417 acceptAll( translationUnit, cot ); 418 PassVisitor<FixUniqueIds_old> fui; 419 acceptAll( translationUnit, fui ); 420 } 421 387 422 void validate_D( std::list< Declaration * > & translationUnit ) { 388 PassVisitor<ForallPointerDecay_old> fpd;389 423 { 390 424 Stats::Heap::newPass("validate-D"); … … 394 428 }); 395 429 Stats::Time::TimeBlock("Forall Pointer Decay", [&]() { 396 acceptAll( translationUnit, fpd); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution430 decayForallPointers( translationUnit ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution 397 431 }); 398 432 Stats::Time::TimeBlock("Hoist Control Declarations", [&]() { … … 453 487 } 454 488 455 void decayForallPointers( std::list< Declaration * > & translationUnit ) {456 PassVisitor<ForallPointerDecay_old> fpd;457 acceptAll( translationUnit, fpd );458 }459 460 489 void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) { 461 490 validate_A( translationUnit ); … … 470 499 PassVisitor<EnumAndPointerDecay_old> epc; 471 500 PassVisitor<LinkReferenceToTypes_old> lrt( indexer ); 472 PassVisitor<ForallPointerDecay_old> fpd; 501 PassVisitor<TraitExpander_old> te; 502 PassVisitor<AssertionFixer_old> af; 503 PassVisitor<CheckOperatorTypes_old> cot; 504 PassVisitor<FixUniqueIds_old> fui; 473 505 type->accept( epc ); 474 506 type->accept( lrt ); 475 type->accept( fpd ); 507 type->accept( te ); 508 type->accept( af ); 509 type->accept( cot ); 510 type->accept( fui ); 476 511 } 477 512 … … 984 1019 } 985 1020 1021 /// Replace all traits in assertion lists with their assertions. 1022 void expandTraits( std::list< TypeDecl * > & forall ) { 1023 for ( TypeDecl * type : forall ) { 1024 std::list< DeclarationWithType * > asserts; 1025 asserts.splice( asserts.end(), type->assertions ); 1026 // expand trait instances into their members 1027 for ( DeclarationWithType * assertion : asserts ) { 1028 if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) { 1029 // expand trait instance into all of its members 1030 expandAssertions( traitInst, back_inserter( type->assertions ) ); 1031 delete traitInst; 1032 } else { 1033 // pass other assertions through 1034 type->assertions.push_back( assertion ); 1035 } // if 1036 } // for 1037 } 1038 } 1039 1040 /// Fix each function in the assertion list and check for invalid void type. 1041 void fixAssertions( 1042 std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) { 1043 for ( TypeDecl * type : forall ) { 1044 for ( DeclarationWithType *& assertion : type->assertions ) { 1045 bool isVoid = fixFunction( assertion ); 1046 if ( isVoid ) { 1047 SemanticError( node, "invalid type void in assertion of function " ); 1048 } // if 1049 } // for 1050 } 1051 } 1052 986 1053 void ForallPointerDecay_old::previsit( ObjectDecl * object ) { 987 1054 // ensure that operator names only apply to functions or function pointers … … 1006 1073 void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) { 1007 1074 forallFixer( aggrDecl->parameters, aggrDecl ); 1075 } 1076 1077 void TraitExpander_old::previsit( FunctionType * ftype ) { 1078 expandTraits( ftype->forall ); 1079 } 1080 1081 void TraitExpander_old::previsit( StructDecl * aggrDecl ) { 1082 expandTraits( aggrDecl->parameters ); 1083 } 1084 1085 void TraitExpander_old::previsit( UnionDecl * aggrDecl ) { 1086 expandTraits( aggrDecl->parameters ); 1087 } 1088 1089 void AssertionFixer_old::previsit( FunctionType * ftype ) { 1090 fixAssertions( ftype->forall, ftype ); 1091 } 1092 1093 void AssertionFixer_old::previsit( StructDecl * aggrDecl ) { 1094 fixAssertions( aggrDecl->parameters, aggrDecl ); 1095 } 1096 1097 void AssertionFixer_old::previsit( UnionDecl * aggrDecl ) { 1098 fixAssertions( aggrDecl->parameters, aggrDecl ); 1099 } 1100 1101 void CheckOperatorTypes_old::previsit( ObjectDecl * object ) { 1102 // ensure that operator names only apply to functions or function pointers 1103 if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) { 1104 SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." ) ); 1105 } 1106 } 1107 1108 void FixUniqueIds_old::previsit( DeclarationWithType * decl ) { 1109 decl->fixUniqueId(); 1008 1110 } 1009 1111 -
src/SymTab/Validate.h
r4559b34 r92538ab 42 42 void validate_E( std::list< Declaration * > &translationUnit ); 43 43 void validate_F( std::list< Declaration * > &translationUnit ); 44 void decayForallPointers( std::list< Declaration * > & translationUnit );45 44 46 45 const ast::Type * validateType( -
src/Tuples/TupleAssignment.cc
r4559b34 r92538ab 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Dec 13 23:45:33 201913 // Update Count : 911 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 16 14:06:00 2022 13 // Update Count : 10 14 14 // 15 15 … … 465 465 // resolve ctor/dtor for the new object 466 466 ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 467 InitTweak::genCtorInit( location, ret ), spotter.crntFinder. localSyms);467 InitTweak::genCtorInit( location, ret ), spotter.crntFinder.context ); 468 468 // remove environments from subexpressions of stmtExpr 469 469 ast::Pass< EnvRemover > rm{ env }; … … 560 560 // resolve the cast expression so that rhsCand return type is bound by the cast 561 561 // type as needed, and transfer the resulting environment 562 ResolvExpr::CandidateFinder finder { spotter.crntFinder.localSyms, env };562 ResolvExpr::CandidateFinder finder( spotter.crntFinder.context, env ); 563 563 finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() ); 564 564 assert( finder.candidates.size() == 1 ); … … 609 609 // explode the LHS so that each field of a tuple-valued expr is assigned 610 610 ResolvExpr::CandidateList lhs; 611 explode( *lhsCand, crntFinder. localSyms, back_inserter(lhs), true );611 explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true ); 612 612 for ( ResolvExpr::CandidateRef & cand : lhs ) { 613 613 // each LHS value must be a reference - some come in with a cast, if not … … 629 629 if ( isTuple( rhsCand->expr ) ) { 630 630 // multiple assignment 631 explode( *rhsCand, crntFinder. localSyms, back_inserter(rhs), true );631 explode( *rhsCand, crntFinder.context.symtab, back_inserter(rhs), true ); 632 632 matcher.reset( 633 633 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); … … 648 648 // multiple assignment 649 649 ResolvExpr::CandidateList rhs; 650 explode( rhsCand, crntFinder. localSyms, back_inserter(rhs), true );650 explode( rhsCand, crntFinder.context.symtab, back_inserter(rhs), true ); 651 651 matcher.reset( 652 652 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); … … 678 678 ) 679 679 680 ResolvExpr::CandidateFinder finder { crntFinder.localSyms, matcher->env };680 ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env ); 681 681 682 682 try { -
src/Validate/Autogen.cpp
r4559b34 r92538ab 248 248 structInst.params.push_back( new ast::TypeExpr( 249 249 typeDecl->location, 250 new ast::TypeInstType( typeDecl ->name, typeDecl)250 new ast::TypeInstType( typeDecl ) 251 251 ) ); 252 252 } … … 264 264 unionInst.params.push_back( new ast::TypeExpr( 265 265 unionDecl->location, 266 new ast::TypeInstType( typeDecl ->name, typeDecl)266 new ast::TypeInstType( typeDecl ) 267 267 ) ); 268 268 } -
src/Validate/FindSpecialDeclsNew.cpp
r4559b34 r92538ab 30 30 31 31 struct FindDeclsCore : public ast::WithShortCircuiting { 32 ast::Translation Unit::Global & global;33 FindDeclsCore( ast::Translation Unit::Global & g ) : global( g ) {}32 ast::TranslationGlobal & global; 33 FindDeclsCore( ast::TranslationGlobal & g ) : global( g ) {} 34 34 35 35 void previsit( const ast::Decl * decl ); … … 74 74 ast::Pass<FindDeclsCore>::run( translationUnit, translationUnit.global ); 75 75 76 // TODO: When everything gets the globals from the translation unit,77 // remove these.78 ast::dereferenceOperator = translationUnit.global.dereference;79 ast::dtorStruct = translationUnit.global.dtorStruct;80 ast::dtorStructDestroy = translationUnit.global.dtorDestroy;81 82 76 // TODO: conditionally generate 'fake' declarations for missing features, 83 77 // so that translation can proceed in the event that builtins, prelude, -
src/Validate/module.mk
r4559b34 r92538ab 20 20 Validate/CompoundLiteral.cpp \ 21 21 Validate/CompoundLiteral.hpp \ 22 Validate/ForallPointerDecay.cpp \ 23 Validate/ForallPointerDecay.hpp \ 22 24 Validate/HandleAttributes.cc \ 23 25 Validate/HandleAttributes.h \ -
src/Virtual/Tables.cc
r4559b34 r92538ab 10 10 // Created On : Mon Aug 31 11:11:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 21 15:36:00 2021 13 // Update Count : 2 14 // 15 12 // Last Modified On : Fri Mar 11 10:40:00 2022 13 // Update Count : 3 14 // 15 16 #include "AST/Attribute.hpp" 17 #include "AST/Copy.hpp" 18 #include "AST/Decl.hpp" 19 #include "AST/Expr.hpp" 20 #include "AST/Init.hpp" 21 #include "AST/Stmt.hpp" 22 #include "AST/Type.hpp" 16 23 #include <SynTree/Attribute.h> 17 24 #include <SynTree/Declaration.h> … … 77 84 } 78 85 86 static ast::ObjectDecl * makeVtableDeclaration( 87 CodeLocation const & location, std::string const & name, 88 ast::StructInstType const * type, ast::Init const * init ) { 89 ast::Storage::Classes storage; 90 if ( nullptr == init ) { 91 storage.is_extern = true; 92 } 93 return new ast::ObjectDecl( 94 location, 95 name, 96 type, 97 init, 98 storage, 99 ast::Linkage::Cforall 100 ); 101 } 102 79 103 ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) { 80 104 assert( type ); 81 105 return makeVtableDeclaration( name, type, nullptr ); 106 } 107 108 ast::ObjectDecl * makeVtableForward( 109 CodeLocation const & location, std::string const & name, 110 ast::StructInstType const * vtableType ) { 111 assert( vtableType ); 112 return makeVtableDeclaration( location, name, vtableType, nullptr ); 82 113 } 83 114 … … 123 154 } 124 155 156 static std::vector<ast::ptr<ast::Init>> buildInits( 157 CodeLocation const & location, 158 //std::string const & name, 159 ast::StructInstType const * vtableType, 160 ast::Type const * objectType ) { 161 ast::StructDecl const * vtableStruct = vtableType->base; 162 163 std::vector<ast::ptr<ast::Init>> inits; 164 inits.reserve( vtableStruct->members.size() ); 165 166 // This is designed to run before the resolver. 167 for ( auto field : vtableStruct->members ) { 168 if ( std::string( "parent" ) == field->name ) { 169 // This will not work with polymorphic state. 170 auto oField = field.strict_as<ast::ObjectDecl>(); 171 auto fieldType = oField->type.strict_as<ast::PointerType>(); 172 auto parentType = fieldType->base.strict_as<ast::StructInstType>(); 173 std::string const & parentInstance = instanceName( parentType->name ); 174 inits.push_back( 175 new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, parentInstance ) ) ) ); 176 } else if ( std::string( "__cfavir_typeid" ) == field->name ) { 177 std::string const & baseType = baseTypeName( vtableType->name ); 178 std::string const & typeId = typeIdName( baseType ); 179 inits.push_back( new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, typeId ) ) ) ); 180 } else if ( std::string( "size" ) == field->name ) { 181 inits.push_back( new ast::SingleInit( location, new ast::SizeofExpr( location, objectType ) 182 ) ); 183 } else if ( std::string( "align" ) == field->name ) { 184 inits.push_back( new ast::SingleInit( location, 185 new ast::AlignofExpr( location, objectType ) 186 ) ); 187 } else { 188 inits.push_back( new ast::SingleInit( location, 189 new ast::NameExpr( location, field->name ) 190 ) ); 191 } 192 //ast::Expr * expr = buildInitExpr(...); 193 //inits.push_back( new ast::SingleInit( location, expr ) ) 194 } 195 196 return inits; 197 } 198 199 ast::ObjectDecl * makeVtableInstance( 200 CodeLocation const & location, 201 std::string const & name, 202 ast::StructInstType const * vtableType, 203 ast::Type const * objectType, 204 ast::Init const * init ) { 205 assert( vtableType ); 206 assert( objectType ); 207 208 // Build the initialization. 209 if ( nullptr == init ) { 210 init = new ast::ListInit( location, 211 buildInits( location, vtableType, objectType ) ); 212 213 // The provided init should initialize everything except the parent 214 // pointer, the size-of and align-of fields. These should be inserted. 215 } else { 216 // Except this is not yet supported. 217 assert(false); 218 } 219 return makeVtableDeclaration( location, name, vtableType, init ); 220 } 221 125 222 namespace { 126 223 std::string const functionName = "get_exception_vtable"; … … 140 237 new ReferenceType( noQualifiers, vtableType ), 141 238 nullptr, 142 239 { new Attribute("unused") } 143 240 ) ); 144 241 type->parameters.push_back( new ObjectDecl( … … 157 254 type, 158 255 nullptr 256 ); 257 } 258 259 ast::FunctionDecl * makeGetExceptionForward( 260 CodeLocation const & location, 261 ast::Type const * vtableType, 262 ast::Type const * exceptType ) { 263 assert( vtableType ); 264 assert( exceptType ); 265 return new ast::FunctionDecl( 266 location, 267 functionName, 268 { /* forall */ }, 269 { new ast::ObjectDecl( 270 location, 271 "__unused", 272 new ast::PointerType( exceptType ) 273 ) }, 274 { new ast::ObjectDecl( 275 location, 276 "_retvalue", 277 new ast::ReferenceType( vtableType ) 278 ) }, 279 nullptr, 280 ast::Storage::Classes(), 281 ast::Linkage::Cforall, 282 { new ast::Attribute( "unused" ) } 159 283 ); 160 284 } … … 172 296 } 173 297 298 ast::FunctionDecl * makeGetExceptionFunction( 299 CodeLocation const & location, 300 ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType ) { 301 assert( vtableInstance ); 302 assert( exceptType ); 303 ast::FunctionDecl * func = makeGetExceptionForward( 304 location, ast::deepCopy( vtableInstance->type ), exceptType ); 305 func->stmts = new ast::CompoundStmt( location, { 306 new ast::ReturnStmt( location, new ast::VariableExpr( location, vtableInstance ) ) 307 } ); 308 return func; 309 } 310 174 311 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) { 175 312 assert( typeIdType ); … … 191 328 } 192 329 193 } 330 ast::ObjectDecl * makeTypeIdInstance( 331 CodeLocation const & location, 332 ast::StructInstType const * typeIdType ) { 333 assert( typeIdType ); 334 ast::StructInstType * type = ast::mutate( typeIdType ); 335 type->set_const( true ); 336 std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name ); 337 return new ast::ObjectDecl( 338 location, 339 typeid_name, 340 type, 341 new ast::ListInit( location, { 342 new ast::SingleInit( location, 343 new ast::AddressExpr( location, 344 new ast::NameExpr( location, "__cfatid_exception_t" ) ) ) 345 } ), 346 ast::Storage::Classes(), 347 ast::Linkage::Cforall, 348 nullptr, 349 { new ast::Attribute( "cfa_linkonce" ) } 350 ); 351 } 352 353 } -
src/Virtual/Tables.h
r4559b34 r92538ab 10 10 // Created On : Mon Aug 31 11:07:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : We d Apr 21 10:30:00 202113 // Update Count : 212 // Last Modified On : Wec Dec 8 16:58:00 2021 13 // Update Count : 3 14 14 // 15 15 16 16 #include <list> // for list 17 17 18 #include <string> 19 #include "AST/Fwd.hpp" 18 20 class Declaration; 19 21 class StructDecl; … … 35 37 * vtableType node is consumed. 36 38 */ 39 ast::ObjectDecl * makeVtableForward( 40 CodeLocation const & location, std::string const & name, 41 ast::StructInstType const * vtableType ); 37 42 38 43 ObjectDecl * makeVtableInstance( … … 43 48 * vtableType and init (if provided) nodes are consumed. 44 49 */ 50 ast::ObjectDecl * makeVtableInstance( 51 CodeLocation const & location, 52 std::string const & name, 53 ast::StructInstType const * vtableType, 54 ast::Type const * objectType, 55 ast::Init const * init = nullptr ); 45 56 46 57 // Some special code for how exceptions interact with virtual tables. … … 49 60 * linking the vtableType to the exceptType. Both nodes are consumed. 50 61 */ 62 ast::FunctionDecl * makeGetExceptionForward( 63 CodeLocation const & location, 64 ast::Type const * vtableType, 65 ast::Type const * exceptType ); 51 66 52 67 FunctionDecl * makeGetExceptionFunction( … … 55 70 * exceptType node is consumed. 56 71 */ 72 ast::FunctionDecl * makeGetExceptionFunction( 73 CodeLocation const & location, 74 ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType ); 57 75 58 76 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ); … … 60 78 * TODO: Should take the parent type. Currently locked to the exception_t. 61 79 */ 80 ast::ObjectDecl * makeTypeIdInstance( 81 const CodeLocation & location, ast::StructInstType const * typeIdType ); 62 82 63 83 } -
src/main.cc
r4559b34 r92538ab 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jan 26 14:09:00 202213 // Update Count : 67 012 // Last Modified On : Fri Mar 11 10:39:00 2022 13 // Update Count : 671 14 14 // 15 15 … … 76 76 #include "Validate/Autogen.hpp" // for autogenerateRoutines 77 77 #include "Validate/FindSpecialDecls.h" // for findGlobalDecls 78 #include "Validate/ForallPointerDecay.hpp" // for decayForallPointers 78 79 #include "Validate/CompoundLiteral.hpp" // for handleCompoundLiterals 79 80 #include "Validate/InitializerLength.hpp" // for setLengthFromInitializer … … 331 332 332 333 if( useNewAST ) { 333 PASS( "Apply Concurrent Keywords", Concurrency::applyKeywords( translationUnit ) );334 PASS( "Forall Pointer Decay", SymTab::decayForallPointers( translationUnit ) );335 334 CodeTools::fillLocations( translationUnit ); 336 335 … … 342 341 343 342 forceFillCodeLocations( transUnit ); 343 344 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) ); 345 346 // Must be after implement concurrent keywords; because uniqueIds 347 // must be set on declaration before resolution. 348 // Must happen before autogen routines are added. 349 PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) ); 344 350 345 351 // Must happen before autogen routines are added. … … 487 493 PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) ); 488 494 } 489 490 491 495 492 496 PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
Note:
See TracChangeset
for help on using the changeset viewer.