- Timestamp:
- Jun 24, 2019, 10:30:47 AM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 84917e2
- Parents:
- 3c6e417 (diff), 9e0a360 (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:
-
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.hpp
r3c6e417 r54dd994 248 248 AddressExpr( const CodeLocation & loc, const Expr * a ); 249 249 250 /// Generate AddressExpr wrapping given expression at same location 251 AddressExpr( const Expr * a ) : AddressExpr( a->location, a ) {} 252 250 253 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } 251 254 private: … … 281 284 /// Cast-to-void 282 285 CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast ); 286 287 /// Wrap a cast expression around an existing expression (always generated) 288 CastExpr( const Expr * a, const Type * to ) : CastExpr( a->location, a, to, GeneratedCast ) {} 289 290 /// Wrap a cast-to-void expression around an existing expression (always generated) 291 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {} 283 292 284 293 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } -
src/AST/Init.hpp
r3c6e417 r54dd994 55 55 ConstructFlag maybeConstructed; 56 56 57 Init( const CodeLocation & loc, ConstructFlag mc ) : ParseNode( loc ), maybeConstructed( mc ) {}57 Init( const CodeLocation & loc, ConstructFlag mc ) : ParseNode( loc ), maybeConstructed( mc ) {} 58 58 59 const Init * accept( Visitor & v ) const override = 0;59 const Init * accept( Visitor & v ) const override = 0; 60 60 private: 61 61 Init * clone() const override = 0; … … 69 69 ptr<Expr> value; 70 70 71 SingleInit( const CodeLocation & loc, Expr* val, ConstructFlag mc = DoConstruct )71 SingleInit( const CodeLocation & loc, const Expr * val, ConstructFlag mc = DoConstruct ) 72 72 : Init( loc, mc ), value( val ) {} 73 73 … … 87 87 std::vector<ptr<Designation>> designations; 88 88 89 ListInit( const CodeLocation & loc, std::vector<ptr<Init>>&& is,90 std::vector<ptr<Designation>> && ds = {}, ConstructFlag mc = DoConstruct );89 ListInit( const CodeLocation & loc, std::vector<ptr<Init>> && is, 90 std::vector<ptr<Designation>> && ds = {}, ConstructFlag mc = DoConstruct ); 91 91 92 92 using iterator = std::vector<ptr<Init>>::iterator; … … 114 114 ptr<Init> init; 115 115 116 ConstructorInit( const CodeLocation& loc, Stmt* ctor, Stmt* dtor, Init* init ) 116 ConstructorInit( 117 const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init ) 117 118 : Init( loc, DoConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {} 118 119 -
src/AST/Node.hpp
r3c6e417 r54dd994 17 17 18 18 #include <cassert> 19 #include <cstddef> // for nullptr_t 19 20 #include <iosfwd> 20 21 #include <type_traits> // for remove_reference … … 181 182 } 182 183 184 ptr_base & operator=( std::nullptr_t ) { 185 if ( node ) _dec(node); 186 node = nullptr; 187 return *this; 188 } 189 183 190 ptr_base & operator=( const ptr_base & o ) { 184 191 assign(o.node); -
src/AST/Stmt.hpp
r3c6e417 r54dd994 61 61 CompoundStmt( CompoundStmt&& o ) = default; 62 62 63 void push_back( Stmt * s ) { kids.emplace_back( s ); }64 void push_front( Stmt * s ) { kids.emplace_front( s ); }63 void push_back( const Stmt * s ) { kids.emplace_back( s ); } 64 void push_front( const Stmt * s ) { kids.emplace_front( s ); } 65 65 66 66 const CompoundStmt * accept( Visitor & v ) const override { return v.visit( this ); } … … 143 143 144 144 IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * thenPart, 145 Stmt * const elsePart, std::vector<ptr<Stmt>> && inits,145 const Stmt * elsePart = nullptr, std::vector<ptr<Stmt>> && inits = {}, 146 146 std::vector<Label> && labels = {} ) 147 147 : Stmt(loc, std::move(labels)), cond(cond), thenPart(thenPart), elsePart(elsePart), -
src/Common/utility.h
r3c6e417 r54dd994 16 16 #pragma once 17 17 18 #include <cassert> 18 19 #include <cctype> 19 20 #include <algorithm> … … 27 28 #include <type_traits> 28 29 #include <utility> 29 30 #include <cassert> 30 #include <vector> 31 31 32 32 #include "Common/Indenter.h" 33 33 34 34 class Expression; 35 36 /// bring std::move into global scope 37 using std::move; 38 39 /// partner to move that copies any copyable type 40 template<typename T> 41 T copy( const T & x ) { return x; } 35 42 36 43 template< typename T > … … 145 152 return ret; 146 153 } // switch 154 } 155 156 /// Splice src onto the end of dst, clearing src 157 template< typename T > 158 void splice( std::vector< T > & dst, std::vector< T > & src ) { 159 dst.reserve( dst.size() + src.size() ); 160 for ( T & x : src ) { dst.emplace_back( std::move( x ) ); } 161 src.clear(); 162 } 163 164 /// Splice src onto the begining of dst, clearing src 165 template< typename T > 166 void spliceBegin( std::vector< T > & dst, std::vector< T > & src ) { 167 splice( src, dst ); 168 dst.swap( src ); 147 169 } 148 170 -
src/InitTweak/FixInit.cc
r3c6e417 r54dd994 1111 1111 arg2 = new MemberExpr( field, new VariableExpr( params.back() ) ); 1112 1112 } 1113 InitExpander srcParam( arg2 );1113 InitExpander_old srcParam( arg2 ); 1114 1114 // cast away reference type and construct field. 1115 1115 Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() ); -
src/InitTweak/GenInit.cc
r3c6e417 r54dd994 18 18 #include <algorithm> // for any_of 19 19 #include <cassert> // for assert, strict_dynamic_cast, assertf 20 #include <deque> 20 21 #include <iterator> // for back_inserter, inserter, back_inse... 21 22 #include <list> // for _List_iterator, list 22 23 24 #include "AST/Decl.hpp" 25 #include "AST/Init.hpp" 26 #include "AST/Node.hpp" 27 #include "AST/Stmt.hpp" 23 28 #include "CodeGen/OperatorTable.h" 24 29 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... … … 274 279 assertf( objDecl, "genCtorDtor passed null objDecl" ); 275 280 std::list< Statement * > stmts; 276 InitExpander srcParam( maybeClone( arg ) );281 InitExpander_old srcParam( maybeClone( arg ) ); 277 282 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), fname, back_inserter( stmts ), objDecl ); 278 283 assert( stmts.size() <= 1 ); … … 286 291 std::list< Statement * > dtor; 287 292 288 InitExpander srcParam( objDecl->get_init() );289 InitExpander nullParam( (Initializer *)NULL );293 InitExpander_old srcParam( objDecl->get_init() ); 294 InitExpander_old nullParam( (Initializer *)NULL ); 290 295 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 291 296 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); … … 353 358 GuardScope( managedTypes ); 354 359 } 360 361 ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl ) { 362 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor for each 363 // constructable object 364 InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr }; 365 366 ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall( 367 srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl ); 368 ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall( 369 nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl, 370 SymTab::LoopBackward ); 371 372 // check that either both ctor and dtor are present, or neither 373 assert( (bool)ctor == (bool)dtor ); 374 375 if ( ctor ) { 376 // need to remember init expression, in case no ctors exist. If ctor does exist, want to 377 // use ctor expression instead of init. 378 ctor.strict_as< ast::ImplicitCtorDtorStmt >(); 379 dtor.strict_as< ast::ImplicitCtorDtorStmt >(); 380 381 return new ast::ConstructorInit{ loc, ctor, dtor, objDecl->init }; 382 } 383 384 return nullptr; 385 } 386 355 387 } // namespace InitTweak 356 388 -
src/InitTweak/GenInit.h
r3c6e417 r54dd994 19 19 #include <string> // for string 20 20 21 #include "AST/Fwd.hpp" 22 #include "Common/CodeLocation.h" 23 #include "GenPoly/ScopedSet.h" // for ScopedSet 21 24 #include "SynTree/SynTree.h" // for Visitor Nodes 22 23 #include "GenPoly/ScopedSet.h" // for ScopedSet24 25 25 26 namespace InitTweak { … … 35 36 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer 36 37 ConstructorInit * genCtorInit( ObjectDecl * objDecl ); 38 ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl ); 37 39 38 40 class ManagedTypes { -
src/InitTweak/InitTweak.cc
r3c6e417 r54dd994 22 22 23 23 #include "AST/Expr.hpp" 24 #include "AST/Init.hpp" 25 #include "AST/Node.hpp" 26 #include "AST/Pass.hpp" 24 27 #include "AST/Stmt.hpp" 25 28 #include "AST/Type.hpp" … … 84 87 }; 85 88 86 struct InitFlattener : public WithShortCircuiting {89 struct InitFlattener_old : public WithShortCircuiting { 87 90 void previsit( SingleInit * singleInit ) { 88 91 visit_children = false; … … 92 95 }; 93 96 94 } 97 struct InitFlattener_new : public ast::WithShortCircuiting { 98 std::vector< ast::ptr< ast::Expr > > argList; 99 100 void previsit( const ast::SingleInit * singleInit ) { 101 visit_children = false; 102 argList.emplace_back( singleInit->value ); 103 } 104 }; 105 106 } // anonymous namespace 95 107 96 108 std::list< Expression * > makeInitList( Initializer * init ) { 97 PassVisitor<InitFlattener > flattener;109 PassVisitor<InitFlattener_old> flattener; 98 110 maybeAccept( init, flattener ); 99 111 return flattener.pass.argList; … … 112 124 } 113 125 114 class InitExpander::ExpanderImpl { 126 std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) { 127 ast::Pass< InitFlattener_new > flattener; 128 maybe_accept( init, flattener ); 129 return std::move( flattener.pass.argList ); 130 } 131 132 class InitExpander_old::ExpanderImpl { 115 133 public: 116 134 virtual ~ExpanderImpl() = default; … … 119 137 }; 120 138 121 class InitImpl : public InitExpander::ExpanderImpl {139 class InitImpl_old : public InitExpander_old::ExpanderImpl { 122 140 public: 123 InitImpl ( Initializer * init ) : init( init ) {}124 virtual ~InitImpl () = default;141 InitImpl_old( Initializer * init ) : init( init ) {} 142 virtual ~InitImpl_old() = default; 125 143 126 144 virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) { … … 136 154 }; 137 155 138 class ExprImpl : public InitExpander::ExpanderImpl {156 class ExprImpl_old : public InitExpander_old::ExpanderImpl { 139 157 public: 140 ExprImpl ( Expression * expr ) : arg( expr ) {}141 virtual ~ExprImpl () { delete arg; }158 ExprImpl_old( Expression * expr ) : arg( expr ) {} 159 virtual ~ExprImpl_old() { delete arg; } 142 160 143 161 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { … … 163 181 }; 164 182 165 InitExpander ::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}166 167 InitExpander ::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}168 169 std::list< Expression * > InitExpander ::operator*() {183 InitExpander_old::InitExpander_old( Initializer * init ) : expander( new InitImpl_old( init ) ) {} 184 185 InitExpander_old::InitExpander_old( Expression * expr ) : expander( new ExprImpl_old( expr ) ) {} 186 187 std::list< Expression * > InitExpander_old::operator*() { 170 188 return cur; 171 189 } 172 190 173 InitExpander & InitExpander::operator++() {191 InitExpander_old & InitExpander_old::operator++() { 174 192 cur = expander->next( indices ); 175 193 return *this; … … 177 195 178 196 // use array indices list to build switch statement 179 void InitExpander ::addArrayIndex( Expression * index, Expression * dimension ) {197 void InitExpander_old::addArrayIndex( Expression * index, Expression * dimension ) { 180 198 indices.push_back( index ); 181 199 indices.push_back( dimension ); 182 200 } 183 201 184 void InitExpander ::clearArrayIndices() {202 void InitExpander_old::clearArrayIndices() { 185 203 deleteAll( indices ); 186 204 indices.clear(); 187 205 } 188 206 189 bool InitExpander ::addReference() {207 bool InitExpander_old::addReference() { 190 208 bool added = false; 191 209 for ( Expression *& expr : cur ) { … … 218 236 219 237 template< typename OutIterator > 220 void build( UntypedExpr * callExpr, InitExpander ::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {238 void build( UntypedExpr * callExpr, InitExpander_old::IndexList::iterator idx, InitExpander_old::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) { 221 239 if ( idx == idxEnd ) return; 222 240 Expression * index = *idx++; … … 275 293 // remaining elements. 276 294 // To accomplish this, generate switch statement, consuming all of expander's elements 277 Statement * InitImpl ::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {295 Statement * InitImpl_old::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 278 296 if ( ! init ) return nullptr; 279 297 CompoundStmt * block = new CompoundStmt(); … … 288 306 } 289 307 290 Statement * ExprImpl ::buildListInit( UntypedExpr *, std::list< Expression * > & ) {308 Statement * ExprImpl_old::buildListInit( UntypedExpr *, std::list< Expression * > & ) { 291 309 return nullptr; 292 310 } 293 311 294 Statement * InitExpander ::buildListInit( UntypedExpr * dst ) {312 Statement * InitExpander_old::buildListInit( UntypedExpr * dst ) { 295 313 return expander->buildListInit( dst, indices ); 296 314 } 315 316 class InitExpander_new::ExpanderImpl { 317 public: 318 virtual ~ExpanderImpl() = default; 319 virtual std::vector< ast::ptr< ast::Expr > > next( IndexList & indices ) = 0; 320 virtual ast::ptr< ast::Stmt > buildListInit( 321 ast::UntypedExpr * callExpr, IndexList & indices ) = 0; 322 }; 323 324 namespace { 325 template< typename Out > 326 void buildCallExpr( 327 ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension, 328 const ast::Init * init, Out & out 329 ) { 330 const CodeLocation & loc = init->location; 331 332 auto cond = new ast::UntypedExpr{ 333 loc, new ast::NameExpr{ loc, "?<?" }, { index, dimension } }; 334 335 std::vector< ast::ptr< ast::Expr > > args = makeInitList( init ); 336 splice( callExpr->args, args ); 337 338 out.emplace_back( new ast::IfStmt{ loc, cond, new ast::ExprStmt{ loc, callExpr } } ); 339 340 out.emplace_back( new ast::ExprStmt{ 341 loc, new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, "++?" }, { index } } } ); 342 } 343 344 template< typename Out > 345 void build( 346 ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices, 347 const ast::Init * init, Out & out 348 ) { 349 if ( indices.empty() ) return; 350 351 unsigned idx = 0; 352 353 const ast::Expr * index = indices[idx++]; 354 assert( idx != indices.size() ); 355 const ast::Expr * dimension = indices[idx++]; 356 357 if ( idx == indices.size() ) { 358 if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) { 359 for ( const ast::Init * init : *listInit ) { 360 buildCallExpr( callExpr, index, dimension, init, out ); 361 } 362 } else { 363 buildCallExpr( callExpr, index, dimension, init, out ); 364 } 365 } else { 366 const CodeLocation & loc = init->location; 367 368 unsigned long cond = 0; 369 auto listInit = dynamic_cast< const ast::ListInit * >( init ); 370 if ( ! listInit ) { SemanticError( loc, "unbalanced list initializers" ); } 371 372 static UniqueName targetLabel( "L__autogen__" ); 373 ast::Label switchLabel{ 374 loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } }; 375 376 std::vector< ast::ptr< ast::Stmt > > branches; 377 for ( const ast::Init * init : *listInit ) { 378 auto condition = ast::ConstantExpr::from_ulong( loc, cond ); 379 ++cond; 380 381 std::vector< ast::ptr< ast::Stmt > > stmts; 382 build( callExpr, indices, init, stmts ); 383 stmts.emplace_back( 384 new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } ); 385 branches.emplace_back( new ast::CaseStmt{ loc, condition, std::move( stmts ) } ); 386 } 387 out.emplace_back( new ast::SwitchStmt{ loc, index, std::move( branches ) } ); 388 out.emplace_back( new ast::NullStmt{ loc, { switchLabel } } ); 389 } 390 } 391 392 class InitImpl_new final : public InitExpander_new::ExpanderImpl { 393 ast::ptr< ast::Init > init; 394 public: 395 InitImpl_new( const ast::Init * i ) : init( i ) {} 396 397 std::vector< ast::ptr< ast::Expr > > next( InitExpander_new::IndexList & ) override { 398 return makeInitList( init ); 399 } 400 401 ast::ptr< ast::Stmt > buildListInit( 402 ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices 403 ) override { 404 // If array came with an initializer list, initialize each element. We may have more 405 // initializers than elements of the array; need to check at each index that we have 406 // not exceeded size. We may have fewer initializers than elements in the array; need 407 // to default-construct remaining elements. To accomplish this, generate switch 408 // statement consuming all of expander's elements 409 410 if ( ! init ) return {}; 411 412 std::list< ast::ptr< ast::Stmt > > stmts; 413 build( callExpr, indices, init, stmts ); 414 if ( stmts.empty() ) { 415 return {}; 416 } else { 417 auto block = new ast::CompoundStmt{ init->location, std::move( stmts ) }; 418 init = nullptr; // consumed in creating the list init 419 return block; 420 } 421 } 422 }; 423 424 class ExprImpl_new final : public InitExpander_new::ExpanderImpl { 425 ast::ptr< ast::Expr > arg; 426 public: 427 ExprImpl_new( const ast::Expr * a ) : arg( a ) {} 428 429 std::vector< ast::ptr< ast::Expr > > next( 430 InitExpander_new::IndexList & indices 431 ) override { 432 if ( ! arg ) return {}; 433 434 const CodeLocation & loc = arg->location; 435 const ast::Expr * expr = arg; 436 for ( auto it = indices.rbegin(); it != indices.rend(); ++it ) { 437 // go through indices and layer on subscript exprs ?[?] 438 ++it; 439 expr = new ast::UntypedExpr{ 440 loc, new ast::NameExpr{ loc, "?[?]" }, { expr, *it } }; 441 } 442 return { expr }; 443 } 444 445 ast::ptr< ast::Stmt > buildListInit( 446 ast::UntypedExpr *, InitExpander_new::IndexList & 447 ) override { 448 return {}; 449 } 450 }; 451 } // anonymous namespace 452 453 InitExpander_new::InitExpander_new( const ast::Init * init ) 454 : expander( new InitImpl_new{ init } ), crnt(), indices() {} 455 456 InitExpander_new::InitExpander_new( const ast::Expr * expr ) 457 : expander( new ExprImpl_new{ expr } ), crnt(), indices() {} 458 459 std::vector< ast::ptr< ast::Expr > > InitExpander_new::operator* () { return crnt; } 460 461 InitExpander_new & InitExpander_new::operator++ () { 462 crnt = expander->next( indices ); 463 return *this; 464 } 465 466 /// builds statement which has the same semantics as a C-style list initializer (for array 467 /// initializers) using callExpr as the base expression to perform initialization 468 ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) { 469 return expander->buildListInit( callExpr, indices ); 470 } 471 472 void InitExpander_new::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) { 473 indices.emplace_back( index ); 474 indices.emplace_back( dimension ); 475 } 476 477 void InitExpander_new::clearArrayIndices() { indices.clear(); } 478 479 bool InitExpander_new::addReference() { 480 for ( ast::ptr< ast::Expr > & expr : crnt ) { 481 expr = new ast::AddressExpr{ expr }; 482 } 483 return ! crnt.empty(); 484 } 297 485 298 486 Type * getTypeofThis( FunctionType * ftype ) { -
src/InitTweak/InitTweak.h
r3c6e417 r54dd994 44 44 /// transform Initializer into an argument list that can be passed to a call expression 45 45 std::list< Expression * > makeInitList( Initializer * init ); 46 std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ); 46 47 47 48 /// True if the resolver should try to construct dwt … … 101 102 bool isConstExpr( Initializer * init ); 102 103 103 class InitExpander {104 class InitExpander_old { 104 105 public: 105 106 // expand by stepping through init to get each list of arguments 106 InitExpander ( Initializer * init );107 InitExpander_old( Initializer * init ); 107 108 108 109 // always expand to expr 109 InitExpander ( Expression * expr );110 InitExpander_old( Expression * expr ); 110 111 111 112 // iterator-like interface 112 113 std::list< Expression * > operator*(); 113 InitExpander & operator++();114 InitExpander_old & operator++(); 114 115 115 116 // builds statement which has the same semantics as a C-style list initializer … … 130 131 IndexList indices; 131 132 }; 133 134 class InitExpander_new { 135 public: 136 using IndexList = std::vector< ast::ptr< ast::Expr > >; 137 class ExpanderImpl; 138 139 private: 140 std::shared_ptr< ExpanderImpl > expander; 141 std::vector< ast::ptr< ast::Expr > > crnt; 142 // invariant: list of size 2N (elements come in pairs [index, dimension]) 143 IndexList indices; 144 145 public: 146 /// Expand by stepping through init to get each list of arguments 147 InitExpander_new( const ast::Init * init ); 148 149 /// Always expand to expression 150 InitExpander_new( const ast::Expr * expr ); 151 152 std::vector< ast::ptr< ast::Expr > > operator* (); 153 InitExpander_new & operator++ (); 154 155 /// builds statement which has the same semantics as a C-style list initializer (for array 156 /// initializers) using callExpr as the base expression to perform initialization. 157 /// Mutates callExpr 158 ast::ptr< ast::Stmt > buildListInit( ast::UntypedExpr * callExpr ); 159 160 void addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ); 161 162 void clearArrayIndices(); 163 164 bool addReference(); 165 }; 132 166 } // namespace 133 167 -
src/ResolvExpr/Alternative.cc
r3c6e417 r54dd994 125 125 } 126 126 127 void splice( AltList& dst, AltList& src ) {128 dst.reserve( dst.size() + src.size() );129 for ( Alternative& alt : src ) {130 dst.push_back( std::move(alt) );131 }132 src.clear();133 }134 135 void spliceBegin( AltList& dst, AltList& src ) {136 splice( src, dst );137 dst.swap( src );138 }139 140 127 } // namespace ResolvExpr 141 128 -
src/ResolvExpr/Alternative.h
r3c6e417 r54dd994 112 112 typedef std::vector< Alternative > AltList; 113 113 114 /// Moves all elements from src to the end of dst115 void splice( AltList& dst, AltList& src );116 117 /// Moves all elements from src to the beginning of dst118 void spliceBegin( AltList& dst, AltList& src );119 120 114 static inline std::ostream & operator<<(std::ostream & os, const ResolvExpr::Alternative & alt) { 121 115 alt.print( os ); -
src/ResolvExpr/AlternativeFinder.cc
r3c6e417 r54dd994 56 56 #define PRINT( text ) if ( resolvep ) { text } 57 57 //#define DEBUG_COST 58 59 using std::move;60 61 /// copies any copyable type62 template<typename T>63 T copy(const T& x) { return x; }64 58 65 59 namespace ResolvExpr { -
src/ResolvExpr/Candidate.hpp
r3c6e417 r54dd994 75 75 using CandidateList = std::vector< CandidateRef >; 76 76 77 /// Splice src after dst, clearing src78 static inline void splice( CandidateList & dst, CandidateList & src ) {79 dst.reserve( dst.size() + src.size() );80 for ( CandidateRef & r : src ) { dst.emplace_back( std::move( r ) ); }81 src.clear();82 }83 84 /// Splice src before dst85 static inline void spliceBegin( CandidateList & dst, CandidateList & src ) {86 splice( src, dst );87 dst.swap( src );88 }89 90 77 /// Sum the cost of a list of candidates 91 78 static inline Cost sumCost( const CandidateList & candidates ) { -
src/ResolvExpr/CandidateFinder.cpp
r3c6e417 r54dd994 39 39 #include "AST/SymbolTable.hpp" 40 40 #include "AST/Type.hpp" 41 #include "Common/utility.h" // for move, copy 41 42 #include "SymTab/Mangler.h" 42 43 #include "SymTab/Validate.h" // for validateType … … 46 47 47 48 namespace ResolvExpr { 48 49 using std::move;50 51 /// partner to move that copies any copyable type52 template<typename T>53 T copy( const T & x ) { return x; }54 49 55 50 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) { … … 57 52 // cast away reference from expr 58 53 cost.incReference(); 59 return new ast::CastExpr{ expr ->location, expr, expr->result->stripReferences() };54 return new ast::CastExpr{ expr, expr->result->stripReferences() }; 60 55 } 61 56 … … 126 121 ast::ptr< ast::Type > newType = paramType; 127 122 env.apply( newType ); 128 return new ast::CastExpr{ arg ->location, arg, newType };123 return new ast::CastExpr{ arg, newType }; 129 124 130 125 // xxx - *should* be able to resolve this cast, but at the moment pointers are not … … 793 788 794 789 if ( aggrType.as< ast::ReferenceType >() ) { 795 aggrExpr = 796 new ast::CastExpr{ aggrExpr->location, aggrExpr, aggrType->stripReferences() }; 790 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; 797 791 } 798 792 -
src/ResolvExpr/Cost.h
r3c6e417 r54dd994 10 10 // Created On : Sun May 17 09:39:50 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 29 18:33:44201913 // Update Count : 4912 // Last Modified On : Fri Jun 21 11:39:13 2019 13 // Update Count : 63 14 14 // 15 15 … … 21 21 22 22 namespace ResolvExpr { 23 #if 024 25 //*************************** OLD ***************************26 27 class Cost {28 private:29 Cost( int unsafeCost, int polyCost, int safeCost, int signCost,30 int varCost, int specCost, int referenceCost );31 public:32 Cost & incUnsafe( int inc = 1 );33 Cost & incPoly( int inc = 1 );34 Cost & incSafe( int inc = 1 );35 Cost & incSign( int inc = 1 );36 Cost & incVar( int inc = 1 );37 Cost & decSpec( int inc = 1 );38 Cost & incReference( int inc = 1 );39 40 int get_unsafeCost() const { return unsafeCost; }41 int get_polyCost() const { return polyCost; }42 int get_safeCost() const { return safeCost; }43 int get_signCost() const { return signCost; }44 int get_varCost() const { return varCost; }45 int get_specCost() const { return specCost; }46 int get_referenceCost() const { return referenceCost; }47 48 Cost operator+( const Cost &other ) const;49 Cost &operator+=( const Cost &other );50 bool operator<( const Cost &other ) const;51 bool operator==( const Cost &other ) const;52 bool operator!=( const Cost &other ) const;53 friend std::ostream &operator<<( std::ostream &os, const Cost &cost );54 // returns negative for *this < other, 0 for *this == other, positive for *this > other55 int compare( const Cost &other ) const;56 57 static const Cost zero;58 static const Cost infinity;59 60 static const Cost unsafe;61 static const Cost poly;62 static const Cost safe;63 static const Cost sign;64 static const Cost var;65 static const Cost spec;66 static const Cost reference;67 68 private:69 int unsafeCost; ///< Unsafe (narrowing) conversions70 int polyCost; ///< Count of parameters and return values bound to some poly type71 int safeCost; ///< Safe (widening) conversions72 int signCost; ///< Count of safe sign conversions73 int varCost; ///< Count of polymorphic type variables74 int specCost; ///< Polymorphic type specializations (type assertions), negative cost75 int referenceCost; ///< reference conversions76 };77 78 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int signCost,79 int varCost, int specCost, int referenceCost )80 : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), signCost( signCost ),81 varCost( varCost ), specCost( specCost ), referenceCost( referenceCost ) {}82 83 inline Cost & Cost::incUnsafe( int inc ) {84 if ( *this == infinity ) return *this;85 unsafeCost += inc;86 return *this;87 }88 89 inline Cost & Cost::incPoly( int inc ) {90 if ( *this == infinity ) return *this;91 polyCost += inc;92 return *this;93 }94 95 inline Cost & Cost::incSafe( int inc ) {96 if ( *this == infinity ) return *this;97 safeCost += inc;98 return *this;99 }100 101 inline Cost & Cost::incSign( int inc ) {102 if ( *this == infinity ) return *this;103 signCost += inc;104 return *this;105 }106 107 inline Cost & Cost::incVar( int inc ) {108 if ( *this == infinity ) return *this;109 varCost += inc;110 return *this;111 }112 113 inline Cost& Cost::decSpec( int dec ) {114 if ( *this == infinity ) return *this;115 specCost -= dec;116 return *this;117 }118 119 inline Cost & Cost::incReference( int inc ) {120 if ( *this == infinity ) return *this;121 referenceCost += inc;122 return *this;123 }124 125 inline Cost Cost::operator+( const Cost &other ) const {126 if ( *this == infinity || other == infinity ) return infinity;127 return Cost{128 unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,129 signCost + other.signCost, varCost + other.varCost, specCost + other.specCost,130 referenceCost + other.referenceCost };131 }132 133 inline Cost &Cost::operator+=( const Cost &other ) {134 if ( *this == infinity ) return *this;135 if ( other == infinity ) {136 *this = infinity;137 return *this;138 }139 unsafeCost += other.unsafeCost;140 polyCost += other.polyCost;141 safeCost += other.safeCost;142 signCost += other.signCost;143 varCost += other.varCost;144 specCost += other.specCost;145 referenceCost += other.referenceCost;146 return *this;147 }148 149 inline bool Cost::operator<( const Cost &other ) const {150 if ( *this == infinity ) return false;151 if ( other == infinity ) return true;152 153 if ( unsafeCost > other.unsafeCost ) {154 return false;155 } else if ( unsafeCost < other.unsafeCost ) {156 return true;157 } else if ( polyCost > other.polyCost ) {158 return false;159 } else if ( polyCost < other.polyCost ) {160 return true;161 } else if ( safeCost > other.safeCost ) {162 return false;163 } else if ( safeCost < other.safeCost ) {164 return true;165 } else if ( signCost > other.signCost ) {166 return false;167 } else if ( signCost < other.signCost ) {168 return true;169 } else if ( varCost > other.varCost ) {170 return false;171 } else if ( varCost < other.varCost ) {172 return true;173 } else if ( specCost > other.specCost ) {174 return false;175 } else if ( specCost > other.specCost ) {176 return true;177 } else if ( referenceCost > other.referenceCost ) {178 return false;179 } else if ( referenceCost < other.referenceCost ) {180 return true;181 } else {182 return false;183 } // if184 }185 186 inline int Cost::compare( const Cost &other ) const {187 if ( *this == infinity ) return +1;188 if ( other == infinity ) return -1;189 190 int c = unsafeCost - other.unsafeCost; if ( c ) return c;191 c = polyCost - other.polyCost; if ( c ) return c;192 c = safeCost - other.safeCost; if ( c ) return c;193 c = signCost - other.signCost; if ( c ) return c;194 c = varCost - other.varCost; if ( c ) return c;195 c = specCost - other.specCost; if ( c ) return c;196 return referenceCost - other.referenceCost;197 }198 199 inline bool Cost::operator==( const Cost &other ) const {200 return unsafeCost == other.unsafeCost201 && polyCost == other.polyCost202 && safeCost == other.safeCost203 && signCost == other.signCost204 && varCost == other.varCost205 && specCost == other.specCost206 && referenceCost == other.referenceCost;207 }208 209 inline bool Cost::operator!=( const Cost &other ) const {210 return !( *this == other );211 }212 213 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {214 return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "215 << cost.safeCost << ", " << cost.signCost << ", "216 << cost.varCost << ", " << cost.specCost << ", "217 << cost.referenceCost << " )";218 }219 220 #else221 222 //*************************** NEW ***************************223 224 23 // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the 225 24 // specialization cost is a negative value so a correction is needed is a few places. … … 371 170 << ", " << cost.get_referenceCost() << " )"; 372 171 } 373 #endif // 0374 172 } // namespace ResolvExpr 375 173 -
src/ResolvExpr/RenameVars.cc
r3c6e417 r54dd994 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:05:18 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : T ue Apr 30 17:07:57201913 // Update Count : 711 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Jun 20 17:39:00 2019 13 // Update Count : 8 14 14 // 15 15 … … 19 19 #include <utility> // for pair 20 20 21 #include "AST/Pass.hpp" 22 #include "AST/Type.hpp" 21 23 #include "Common/PassVisitor.h" 24 #include "Common/ScopedMap.h" 22 25 #include "Common/SemanticError.h" // for SemanticError 23 26 #include "RenameVars.h" … … 28 31 29 32 namespace ResolvExpr { 30 namespace {31 struct RenameVars {32 RenameVars();33 void reset();34 33 35 void previsit( TypeInstType * instType ); 36 void previsit( Type * ); 37 void postvisit( Type * ); 34 namespace { 35 class RenamingData { 36 int level = 0; 37 int resetCount = 0; 38 ScopedMap< std::string, std::string > nameMap; 38 39 39 private: 40 int level, resetCount; 41 std::list< std::unordered_map< std::string, std::string > > mapStack; 42 }; 43 44 PassVisitor<RenameVars> global_renamer; 45 } // namespace 46 47 void renameTyVars( Type * t ) { 48 t->accept( global_renamer ); 49 } 50 51 void resetTyVarRenaming() { 52 global_renamer.pass.reset(); 53 } 54 55 namespace { 56 RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) { 57 mapStack.push_front( std::unordered_map< std::string, std::string >() ); 40 public: 41 void reset() { 42 level = 0; 43 ++resetCount; 58 44 } 59 45 60 void RenameVars::reset() { 61 level = 0; 62 resetCount++; 46 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator; 47 48 void rename( TypeInstType * type ) { 49 mapConstIterator it = nameMap.find( type->name ); 50 if ( it != nameMap.end() ) { 51 type->name = it->second; 52 } 63 53 } 64 54 65 void RenameVars::previsit( TypeInstType * instType ) { 66 previsit( (Type *)instType ); 67 std::unordered_map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name ); 68 if ( i != mapStack.front().end() ) { 69 instType->name = i->second; 70 } // if 71 } 72 73 void RenameVars::previsit( Type * type ) { 55 void openLevel( Type * type ) { 74 56 if ( ! type->forall.empty() ) { 75 // copies current name mapping into new mapping 76 mapStack.push_front( mapStack.front() ); 57 nameMap.beginScope(); 77 58 // renames all "forall" type names to `_${level}_${name}' 78 59 for ( auto td : type->forall ) { … … 80 61 output << "_" << resetCount << "_" << level << "_" << td->name; 81 62 std::string newname( output.str() ); 82 mapStack.front()[ td->get_name() ] = newname;63 nameMap[ td->get_name() ] = newname; 83 64 td->name = newname; 84 65 // ditto for assertion names, the next level in … … 89 70 } 90 71 91 void RenameVars::postvisit( Type * type ) { 92 // clears name mapping added by typeBefore() 93 if ( ! type->forall.empty() ) { 94 mapStack.pop_front(); 95 } // if 72 void closeLevel( Type * type ) { 73 if ( !type->forall.empty() ) { 74 nameMap.endScope(); 75 } 96 76 } 97 } // namespace98 77 99 const ast::Type * renameTyVars( const ast::Type * t ) { 100 #warning unimplemented; make sure resetTyVarRenaming() updated when implemented 101 (void)t; 102 assert(false); 103 return t; 104 } 78 const ast::TypeInstType * rename( const ast::TypeInstType * type ) { 79 mapConstIterator it = nameMap.find( type->name ); 80 if ( it != nameMap.end() ) { 81 ast::TypeInstType * mutType = ast::mutate( type ); 82 mutType->name = it->second; 83 type = mutType; 84 } 85 return type; 86 } 87 88 template<typename NodeT> 89 const NodeT * openLevel( const NodeT * type ) { 90 if ( !type->forall.empty() ) { 91 nameMap.beginScope(); 92 // Load new names from this forall clause and perform renaming. 93 NodeT * mutType = ast::mutate( type ); 94 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) { 95 std::ostringstream output; 96 output << "_" << resetCount << "_" << level << "_" << td->name; 97 std::string newname( output.str() ); 98 nameMap[ td->name ] = newname; 99 ++level; 100 101 ast::TypeDecl * decl = ast::mutate( td.get() ); 102 decl->name = newname; 103 td = decl; 104 } 105 } 106 return type; 107 } 108 109 template<typename NodeT> 110 const NodeT * closeLevel( const NodeT * type ) { 111 if ( !type->forall.empty() ) { 112 nameMap.endScope(); 113 } 114 return type; 115 } 116 }; 117 118 // Global State: 119 RenamingData renaming; 120 121 struct RenameVars { 122 void previsit( TypeInstType * instType ) { 123 renaming.openLevel( (Type*)instType ); 124 renaming.rename( instType ); 125 } 126 void previsit( Type * type ) { 127 renaming.openLevel( type ); 128 } 129 void postvisit( Type * type ) { 130 renaming.closeLevel( type ); 131 } 132 133 const ast::FunctionType * previsit( const ast::FunctionType * type ) { 134 return renaming.openLevel( type ); 135 } 136 const ast::StructInstType * previsit( const ast::StructInstType * type ) { 137 return renaming.openLevel( type ); 138 } 139 const ast::UnionInstType * previsit( const ast::UnionInstType * type ) { 140 return renaming.openLevel( type ); 141 } 142 const ast::TraitInstType * previsit( const ast::TraitInstType * type ) { 143 return renaming.openLevel( type ); 144 } 145 const ast::TypeInstType * previsit( const ast::TypeInstType * type ) { 146 return renaming.rename( renaming.openLevel( type ) ); 147 } 148 const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) { 149 return renaming.closeLevel( type ); 150 } 151 }; 152 153 } // namespace 154 155 void renameTyVars( Type * t ) { 156 PassVisitor<RenameVars> renamer; 157 t->accept( renamer ); 158 } 159 160 const ast::Type * renameTyVars( const ast::Type * t ) { 161 ast::Pass<RenameVars> renamer; 162 return t->accept( renamer ); 163 } 164 165 void resetTyVarRenaming() { 166 renaming.reset(); 167 } 168 105 169 } // namespace ResolvExpr 106 170 -
src/ResolvExpr/Resolver.cc
r3c6e417 r54dd994 1109 1109 1110 1110 // set up and resolve expression cast to void 1111 ast::CastExpr * untyped = new ast::CastExpr{ expr ->location, expr};1111 ast::CastExpr * untyped = new ast::CastExpr{ expr }; 1112 1112 CandidateRef choice = findUnfinishedKindExpression( 1113 1113 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); … … 1161 1161 ) { 1162 1162 assert( untyped && type ); 1163 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped ->location, untyped, type };1163 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type }; 1164 1164 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab ); 1165 1165 removeExtraneousCast( newExpr, symtab ); … … 1251 1251 ast::Pass< Resolver_new > resolver; 1252 1252 accept_all( translationUnit, resolver ); 1253 } 1254 1255 ast::ptr< ast::Init > resolveCtorInit( 1256 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab 1257 ) { 1258 assert( ctorInit ); 1259 ast::Pass< Resolver_new > resolver{ symtab }; 1260 return ctorInit->accept( resolver ); 1253 1261 } 1254 1262 -
src/ResolvExpr/Resolver.h
r3c6e417 r54dd994 29 29 30 30 namespace ast { 31 class ConstructorInit; 31 32 class Decl; 32 33 class DeletedExpr; 34 class Init; 33 35 class StmtExpr; 34 36 class SymbolTable; … … 59 61 ast::ptr< ast::Expr > resolveInVoidContext( 60 62 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env ); 63 /// Resolves a constructor init expression 64 ast::ptr< ast::Init > resolveCtorInit( 65 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab ); 61 66 /// Resolves a statement expression 62 67 ast::ptr< ast::Expr > resolveStmtExpr( -
src/SymTab/Autogen.cc
r3c6e417 r54dd994 24 24 #include <vector> // for vector 25 25 26 #include "AST/Decl.hpp" 26 27 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 27 28 #include "Common/PassVisitor.h" // for PassVisitor … … 209 210 } 210 211 212 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) { 213 return obj && obj->name.empty() && obj->bitfieldWidth; 214 } 215 211 216 /// inserts a forward declaration for functionDecl into declsToAdd 212 217 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { … … 388 393 389 394 void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) { 390 InitTweak::InitExpander srcParam( src );395 InitTweak::InitExpander_old srcParam( src ); 391 396 392 397 // assign to destination -
src/SymTab/Autogen.h
r3c6e417 r54dd994 17 17 18 18 #include <cassert> // for assert 19 #include <iterator> // for back_inserter 19 20 #include <string> // for string 20 21 22 #include "AST/Decl.hpp" 23 #include "AST/Expr.hpp" 24 #include "AST/Init.hpp" 25 #include "AST/Node.hpp" 26 #include "AST/Stmt.hpp" 27 #include "AST/Type.hpp" 21 28 #include "CodeGen/OperatorTable.h" 22 29 #include "Common/UniqueName.h" // for UniqueName 30 #include "Common/utility.h" // for splice 23 31 #include "InitTweak/InitTweak.h" // for InitExpander 24 32 #include "SynTree/Constant.h" // for Constant … … 36 44 /// returns true if obj's name is the empty string and it has a bitfield width 37 45 bool isUnnamedBitfield( ObjectDecl * obj ); 46 bool isUnnamedBitfield( const ast::ObjectDecl * obj ); 38 47 39 48 /// generate the type of an assignment function for paramType. … … 49 58 FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true ); 50 59 60 /// Enum for loop direction 61 enum LoopDirection { LoopBackward, LoopForward }; 62 51 63 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 52 64 template< typename OutputIterator > 53 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true ); 65 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true ); 66 67 template< typename OutIter > 68 ast::ptr< ast::Stmt > genCall( 69 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 70 const CodeLocation & loc, const std::string & fname, OutIter && out, 71 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward ); 54 72 55 73 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. 56 74 /// optionally returns a statement which must be inserted prior to the containing loop, if there is one 57 75 template< typename OutputIterator > 58 Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {76 Statement * genScalarCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) { 59 77 bool isReferenceCtorDtor = false; 60 78 if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) { … … 106 124 } 107 125 126 /// inserts into out a generated call expression to function fname with arguments dstParam and 127 /// srcParam. Should only be called with non-array types. 128 /// optionally returns a statement which must be inserted prior to the containing loop, if 129 /// there is one 130 template< typename OutIter > 131 ast::ptr< ast::Stmt > genScalarCall( 132 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 133 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type, 134 const ast::Type * addCast = nullptr 135 ) { 136 bool isReferenceCtorDtor = false; 137 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) { 138 // reference constructors are essentially application of the rebind operator. 139 // apply & to both arguments, do not need a cast 140 fname = "?=?"; 141 dstParam = new ast::AddressExpr{ dstParam }; 142 addCast = nullptr; 143 isReferenceCtorDtor = true; 144 } 145 146 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of 147 // "?=?", "?{}", or "^?{}" 148 ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } }; 149 150 if ( addCast ) { 151 // cast to T& with qualifiers removed, so that qualified objects can be constructed and 152 // destructed with the same functions as non-qualified objects. Unfortunately, lvalue 153 // is considered a qualifier - for AddressExpr to resolve, its argument must have an 154 // lvalue-qualified type, so remove all qualifiers except lvalue. 155 // xxx -- old code actually removed lvalue too... 156 ast::ptr< ast::Type > guard = addCast; // prevent castType from mutating addCast 157 ast::ptr< ast::Type > castType = addCast; 158 ast::remove_qualifiers( 159 castType, 160 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic ); 161 dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } }; 162 } 163 fExpr->args.emplace_back( dstParam ); 164 165 const ast::Stmt * listInit = srcParam.buildListInit( fExpr ); 166 167 // fetch next set of arguments 168 ++srcParam; 169 170 // return if adding reference fails -- will happen on default ctor and dtor 171 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit; 172 173 std::vector< ast::ptr< ast::Expr > > args = *srcParam; 174 splice( fExpr->args, args ); 175 176 *out++ = new ast::ExprStmt{ loc, fExpr }; 177 178 srcParam.clearArrayIndices(); 179 180 return listInit; 181 } 182 108 183 /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments. 109 184 /// If forward is true, loop goes from 0 to N-1, else N-1 to 0 110 185 template< typename OutputIterator > 111 void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {186 void genArrayCall( InitTweak::InitExpander_old & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) { 112 187 static UniqueName indexName( "_index" ); 113 188 … … 170 245 } 171 246 247 /// Store in out a loop which calls fname on each element of the array with srcParam and 248 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0 249 template< typename OutIter > 250 void genArrayCall( 251 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 252 const CodeLocation & loc, const std::string & fname, OutIter && out, 253 const ast::ArrayType * array, const ast::Type * addCast = nullptr, 254 LoopDirection forward = LoopForward 255 ) { 256 static UniqueName indexName( "_index" ); 257 258 // for a flexible array member nothing is done -- user must define own assignment 259 if ( ! array->dimension ) return; 260 261 if ( addCast ) { 262 // peel off array layer from cast 263 addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base; 264 } 265 266 ast::ptr< ast::Expr > begin, end, cmp, update; 267 268 if ( forward ) { 269 // generate: for ( int i = 0; i < N; ++i ) 270 begin = ast::ConstantExpr::from_int( loc, 0 ); 271 end = array->dimension; 272 cmp = new ast::NameExpr{ loc, "?<?" }; 273 update = new ast::NameExpr{ loc, "++?" }; 274 } else { 275 // generate: for ( int i = N-1; i >= 0; --i ) 276 begin = new ast::UntypedExpr{ 277 loc, new ast::NameExpr{ loc, "?-?" }, 278 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } }; 279 end = ast::ConstantExpr::from_int( loc, 0 ); 280 cmp = new ast::NameExpr{ loc, "?>=?" }; 281 update = new ast::NameExpr{ loc, "--?" }; 282 } 283 284 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{ 285 loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt }, 286 new ast::SingleInit{ loc, begin } }; 287 288 ast::ptr< ast::Expr > cond = new ast::UntypedExpr{ 289 loc, cmp, { new ast::VariableExpr{ loc, index }, end } }; 290 291 ast::ptr< ast::Expr > inc = new ast::UntypedExpr{ 292 loc, update, { new ast::VariableExpr{ loc, index } } }; 293 294 ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{ 295 loc, new ast::NameExpr{ loc, "?[?]" }, 296 { dstParam, new ast::VariableExpr{ loc, index } } }; 297 298 // srcParam must keep track of the array indices to build the source parameter and/or 299 // array list initializer 300 srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension ); 301 302 // for stmt's body, eventually containing call 303 ast::CompoundStmt * body = new ast::CompoundStmt{ loc }; 304 ast::ptr< ast::Stmt > listInit = genCall( 305 srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast, 306 forward ); 307 308 // block containing the stmt and index variable 309 ast::CompoundStmt * block = new ast::CompoundStmt{ loc }; 310 block->push_back( new ast::DeclStmt{ loc, index } ); 311 if ( listInit ) { block->push_back( listInit ); } 312 block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } ); 313 314 *out++ = block; 315 } 316 172 317 template< typename OutputIterator > 173 Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {318 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) { 174 319 if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 175 320 genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward ); … … 180 325 } 181 326 327 template< typename OutIter > 328 ast::ptr< ast::Stmt > genCall( 329 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 330 const CodeLocation & loc, const std::string & fname, OutIter && out, 331 const ast::Type * type, const ast::Type * addCast, LoopDirection forward 332 ) { 333 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) { 334 genArrayCall( 335 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast, 336 forward ); 337 return {}; 338 } else { 339 return genScalarCall( 340 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast ); 341 } 342 } 343 182 344 /// inserts into out a generated call expression to function fname with arguments dstParam 183 345 /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the … … 185 347 /// ImplicitCtorDtorStmt node. 186 348 template< typename OutputIterator > 187 void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {349 void genImplicitCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) { 188 350 ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl ); 189 351 assert( obj ); … … 213 375 } 214 376 } 377 378 static inline ast::ptr< ast::Stmt > genImplicitCall( 379 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, 380 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj, 381 LoopDirection forward = LoopForward 382 ) { 383 // unnamed bit fields are not copied as they cannot be accessed 384 if ( isUnnamedBitfield( obj ) ) return {}; 385 386 ast::ptr< ast::Type > addCast = nullptr; 387 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) { 388 assert( dstParam->result ); 389 addCast = dstParam->result; 390 } 391 392 std::vector< ast::ptr< ast::Stmt > > stmts; 393 genCall( 394 srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward ); 395 396 if ( stmts.empty() ) { 397 return {}; 398 } else if ( stmts.size() == 1 ) { 399 const ast::Stmt * callStmt = stmts.front(); 400 if ( addCast ) { 401 // implicitly generated ctor/dtor calls should be wrapped so that later passes are 402 // aware they were generated. 403 callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt }; 404 } 405 return callStmt; 406 } else { 407 assert( false ); 408 return {}; 409 } 410 } 215 411 } // namespace SymTab 216 412 -
src/SymTab/FixFunction.cc
r3c6e417 r54dd994 18 18 #include <list> // for list 19 19 20 #include "Common/utility.h" // for maybeClone 20 #include "AST/Decl.hpp" 21 #include "AST/Pass.hpp" 22 #include "AST/Type.hpp" 23 #include "Common/utility.h" // for maybeClone, copy 21 24 #include "SynTree/Declaration.h" // for FunctionDecl, ObjectDecl, Declarati... 22 25 #include "SynTree/Expression.h" // for Expression … … 24 27 25 28 namespace SymTab { 26 FixFunction::FixFunction() : isVoid( false ) {} 29 class FixFunction_old : public WithShortCircuiting { 30 typedef Mutator Parent; 31 public: 32 FixFunction_old() : isVoid( false ) {} 27 33 34 void premutate(FunctionDecl *functionDecl); 35 DeclarationWithType* postmutate(FunctionDecl *functionDecl); 28 36 29 DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) { 37 Type * postmutate(ArrayType * arrayType); 38 39 void premutate(ArrayType * arrayType); 40 void premutate(VoidType * voidType); 41 void premutate(BasicType * basicType); 42 void premutate(PointerType * pointerType); 43 void premutate(StructInstType * aggregateUseType); 44 void premutate(UnionInstType * aggregateUseType); 45 void premutate(EnumInstType * aggregateUseType); 46 void premutate(TraitInstType * aggregateUseType); 47 void premutate(TypeInstType * aggregateUseType); 48 void premutate(TupleType * tupleType); 49 void premutate(VarArgsType * varArgsType); 50 void premutate(ZeroType * zeroType); 51 void premutate(OneType * oneType); 52 53 bool isVoid; 54 }; 55 56 DeclarationWithType * FixFunction_old::postmutate(FunctionDecl *functionDecl) { 30 57 // can't delete function type because it may contain assertions, so transfer ownership to new object 31 58 ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes ); … … 41 68 // does not cause an error 42 69 43 Type * FixFunction ::postmutate(ArrayType *arrayType) {70 Type * FixFunction_old::postmutate(ArrayType *arrayType) { 44 71 // need to recursively mutate the base type in order for multi-dimensional arrays to work. 45 72 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic ); … … 51 78 } 52 79 53 void FixFunction ::premutate(VoidType *) {80 void FixFunction_old::premutate(VoidType *) { 54 81 isVoid = true; 55 82 } 56 83 57 void FixFunction ::premutate(FunctionDecl *) { visit_children = false; }58 void FixFunction ::premutate(ArrayType *) { visit_children = false; }59 void FixFunction ::premutate(BasicType *) { visit_children = false; }60 void FixFunction ::premutate(PointerType *) { visit_children = false; }61 void FixFunction ::premutate(StructInstType *) { visit_children = false; }62 void FixFunction ::premutate(UnionInstType *) { visit_children = false; }63 void FixFunction ::premutate(EnumInstType *) { visit_children = false; }64 void FixFunction ::premutate(TraitInstType *) { visit_children = false; }65 void FixFunction ::premutate(TypeInstType *) { visit_children = false; }66 void FixFunction ::premutate(TupleType *) { visit_children = false; }67 void FixFunction ::premutate(VarArgsType *) { visit_children = false; }68 void FixFunction ::premutate(ZeroType *) { visit_children = false; }69 void FixFunction ::premutate(OneType *) { visit_children = false; }84 void FixFunction_old::premutate(FunctionDecl *) { visit_children = false; } 85 void FixFunction_old::premutate(ArrayType *) { visit_children = false; } 86 void FixFunction_old::premutate(BasicType *) { visit_children = false; } 87 void FixFunction_old::premutate(PointerType *) { visit_children = false; } 88 void FixFunction_old::premutate(StructInstType *) { visit_children = false; } 89 void FixFunction_old::premutate(UnionInstType *) { visit_children = false; } 90 void FixFunction_old::premutate(EnumInstType *) { visit_children = false; } 91 void FixFunction_old::premutate(TraitInstType *) { visit_children = false; } 92 void FixFunction_old::premutate(TypeInstType *) { visit_children = false; } 93 void FixFunction_old::premutate(TupleType *) { visit_children = false; } 94 void FixFunction_old::premutate(VarArgsType *) { visit_children = false; } 95 void FixFunction_old::premutate(ZeroType *) { visit_children = false; } 96 void FixFunction_old::premutate(OneType *) { visit_children = false; } 70 97 71 98 bool fixFunction( DeclarationWithType *& dwt ) { 72 PassVisitor<FixFunction > fixer;99 PassVisitor<FixFunction_old> fixer; 73 100 dwt = dwt->acceptMutator( fixer ); 74 101 return fixer.pass.isVoid; 75 102 } 103 104 namespace { 105 struct FixFunction_new final : public ast::WithShortCircuiting { 106 bool isVoid = false; 107 108 void premutate( const ast::FunctionDecl * ) { visit_children = false; } 109 110 const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) { 111 return new ast::ObjectDecl{ 112 func->location, func->name, new ast::PointerType{ func->type }, nullptr, 113 func->storage, func->linkage, nullptr, copy( func->attributes ) }; 114 } 115 116 void premutate( const ast::ArrayType * ) { visit_children = false; } 117 118 const ast::Type * postmutate( const ast::ArrayType * array ) { 119 return new ast::PointerType{ 120 array->base, array->dimension, array->isVarLen, array->isStatic, 121 array->qualifiers }; 122 } 123 124 void premutate( const ast::VoidType * ) { isVoid = true; } 125 126 void premutate( const ast::BasicType * ) { visit_children = false; } 127 void premutate( const ast::PointerType * ) { visit_children = false; } 128 void premutate( const ast::StructInstType * ) { visit_children = false; } 129 void premutate( const ast::UnionInstType * ) { visit_children = false; } 130 void premutate( const ast::EnumInstType * ) { visit_children = false; } 131 void premutate( const ast::TraitInstType * ) { visit_children = false; } 132 void premutate( const ast::TypeInstType * ) { visit_children = false; } 133 void premutate( const ast::TupleType * ) { visit_children = false; } 134 void premutate( const ast::VarArgsType * ) { visit_children = false; } 135 void premutate( const ast::ZeroType * ) { visit_children = false; } 136 void premutate( const ast::OneType * ) { visit_children = false; } 137 }; 138 } // anonymous namespace 139 140 const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ) { 141 ast::Pass< FixFunction_new > fixer; 142 dwt = dwt->accept( fixer ); 143 isVoid |= fixer.pass.isVoid; 144 return dwt; 145 } 146 76 147 } // namespace SymTab 77 148 -
src/SymTab/FixFunction.h
r3c6e417 r54dd994 19 19 #include "SynTree/SynTree.h" // for Types 20 20 21 namespace ast { 22 class DeclWithType; 23 } 24 21 25 namespace SymTab { 22 /// Replaces function and array types by equivalent pointer types. 23 class FixFunction : public WithShortCircuiting { 24 typedef Mutator Parent; 25 public: 26 FixFunction(); 26 /// Replaces function and array types by equivalent pointer types. Returns true if type is 27 /// void 28 bool fixFunction( DeclarationWithType *& ); 27 29 28 void premutate(FunctionDecl *functionDecl); 29 DeclarationWithType* postmutate(FunctionDecl *functionDecl); 30 31 Type * postmutate(ArrayType * arrayType); 32 33 void premutate(ArrayType * arrayType); 34 void premutate(VoidType * voidType); 35 void premutate(BasicType * basicType); 36 void premutate(PointerType * pointerType); 37 void premutate(StructInstType * aggregateUseType); 38 void premutate(UnionInstType * aggregateUseType); 39 void premutate(EnumInstType * aggregateUseType); 40 void premutate(TraitInstType * aggregateUseType); 41 void premutate(TypeInstType * aggregateUseType); 42 void premutate(TupleType * tupleType); 43 void premutate(VarArgsType * varArgsType); 44 void premutate(ZeroType * zeroType); 45 void premutate(OneType * oneType); 46 47 bool isVoid; 48 }; 49 50 bool fixFunction( DeclarationWithType *& ); 30 /// Returns declaration with function and array types replaced by equivalent pointer types. 31 /// Sets isVoid to true if type is void 32 const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ); 51 33 } // namespace SymTab 52 34 -
src/SymTab/Validate.cc
r3c6e417 r54dd994 46 46 #include <utility> // for pair 47 47 48 #include "AST/Decl.hpp" 49 #include "AST/Node.hpp" 50 #include "AST/Pass.hpp" 51 #include "AST/SymbolTable.hpp" 52 #include "AST/Type.hpp" 48 53 #include "CodeGen/CodeGenerator.h" // for genName 49 54 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign … … 124 129 125 130 /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers. 126 struct EnumAndPointerDecay {131 struct EnumAndPointerDecay_old { 127 132 void previsit( EnumDecl *aggregateDecl ); 128 133 void previsit( FunctionType *func ); … … 130 135 131 136 /// Associates forward declarations of aggregates with their definitions 132 struct LinkReferenceToTypes final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes>, public WithShortCircuiting {133 LinkReferenceToTypes ( const Indexer *indexer );137 struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting { 138 LinkReferenceToTypes_old( const Indexer *indexer ); 134 139 void postvisit( TypeInstType *typeInst ); 135 140 … … 165 170 166 171 /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID. 167 struct ForallPointerDecay final {172 struct ForallPointerDecay_old final { 168 173 void previsit( ObjectDecl * object ); 169 174 void previsit( FunctionDecl * func ); … … 290 295 291 296 void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) { 292 PassVisitor<EnumAndPointerDecay > epc;293 PassVisitor<LinkReferenceToTypes > lrt( nullptr );294 PassVisitor<ForallPointerDecay > fpd;297 PassVisitor<EnumAndPointerDecay_old> epc; 298 PassVisitor<LinkReferenceToTypes_old> lrt( nullptr ); 299 PassVisitor<ForallPointerDecay_old> fpd; 295 300 PassVisitor<CompoundLiteral> compoundliteral; 296 301 PassVisitor<ValidateGenericParameters> genericParams; … … 305 310 ReplaceTypedef::replaceTypedef( translationUnit ); 306 311 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 307 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes because it is an indexer and needs correct types for mangling312 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling 308 313 } 309 314 { … … 314 319 }); 315 320 Stats::Time::TimeBlock("Fix Qualified Types", [&]() { 316 mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes , because aggregate members are accessed321 mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed 317 322 }); 318 323 Stats::Time::TimeBlock("Hoist Structs", [&]() { … … 326 331 Stats::Heap::newPass("validate-C"); 327 332 Stats::Time::BlockGuard guard("validate-C"); 328 acceptAll( translationUnit, genericParams ); // check as early as possible - can't happen before LinkReferenceToTypes 333 acceptAll( translationUnit, genericParams ); // check as early as possible - can't happen before LinkReferenceToTypes_old 329 334 VerifyCtorDtorAssign::verify( translationUnit ); // must happen before autogen, because autogen examines existing ctor/dtors 330 335 ReturnChecker::checkFunctionReturns( translationUnit ); … … 344 349 }); 345 350 Stats::Time::TimeBlock("Generate Autogen routines", [&]() { 346 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay 351 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay_old 347 352 }); 348 353 } … … 385 390 386 391 void validateType( Type *type, const Indexer *indexer ) { 387 PassVisitor<EnumAndPointerDecay > epc;388 PassVisitor<LinkReferenceToTypes > lrt( indexer );389 PassVisitor<ForallPointerDecay > fpd;392 PassVisitor<EnumAndPointerDecay_old> epc; 393 PassVisitor<LinkReferenceToTypes_old> lrt( indexer ); 394 PassVisitor<ForallPointerDecay_old> fpd; 390 395 type->accept( epc ); 391 396 type->accept( lrt ); … … 586 591 } 587 592 588 void EnumAndPointerDecay ::previsit( EnumDecl *enumDecl ) {593 void EnumAndPointerDecay_old::previsit( EnumDecl *enumDecl ) { 589 594 // Set the type of each member of the enumeration to be EnumConstant 590 595 for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) { … … 618 623 } 619 624 620 void EnumAndPointerDecay ::previsit( FunctionType *func ) {625 void EnumAndPointerDecay_old::previsit( FunctionType *func ) { 621 626 // Fix up parameters and return types 622 627 fixFunctionList( func->parameters, func->isVarArgs, func ); … … 624 629 } 625 630 626 LinkReferenceToTypes ::LinkReferenceToTypes( const Indexer *other_indexer ) {631 LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer *other_indexer ) { 627 632 if ( other_indexer ) { 628 633 local_indexer = other_indexer; … … 632 637 } 633 638 634 void LinkReferenceToTypes ::postvisit( EnumInstType *enumInst ) {639 void LinkReferenceToTypes_old::postvisit( EnumInstType *enumInst ) { 635 640 EnumDecl *st = local_indexer->lookupEnum( enumInst->name ); 636 641 // it's not a semantic error if the enum is not found, just an implicit forward declaration … … 652 657 } 653 658 654 void LinkReferenceToTypes ::postvisit( StructInstType *structInst ) {659 void LinkReferenceToTypes_old::postvisit( StructInstType *structInst ) { 655 660 StructDecl *st = local_indexer->lookupStruct( structInst->name ); 656 661 // it's not a semantic error if the struct is not found, just an implicit forward declaration … … 665 670 } 666 671 667 void LinkReferenceToTypes ::postvisit( UnionInstType *unionInst ) {672 void LinkReferenceToTypes_old::postvisit( UnionInstType *unionInst ) { 668 673 UnionDecl *un = local_indexer->lookupUnion( unionInst->name ); 669 674 // it's not a semantic error if the union is not found, just an implicit forward declaration … … 678 683 } 679 684 680 void LinkReferenceToTypes ::previsit( QualifiedType * ) {685 void LinkReferenceToTypes_old::previsit( QualifiedType * ) { 681 686 visit_children = false; 682 687 } 683 688 684 void LinkReferenceToTypes ::postvisit( QualifiedType * qualType ) {689 void LinkReferenceToTypes_old::postvisit( QualifiedType * qualType ) { 685 690 // linking only makes sense for the 'oldest ancestor' of the qualified type 686 691 qualType->parent->accept( *visitor ); … … 729 734 } 730 735 731 void LinkReferenceToTypes ::postvisit( TraitDecl * traitDecl ) {736 void LinkReferenceToTypes_old::postvisit( TraitDecl * traitDecl ) { 732 737 if ( traitDecl->name == "sized" ) { 733 738 // "sized" is a special trait - flick the sized status on for the type variable … … 751 756 } 752 757 753 void LinkReferenceToTypes ::postvisit( TraitInstType * traitInst ) {758 void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) { 754 759 // handle other traits 755 760 TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name ); … … 777 782 } 778 783 779 void LinkReferenceToTypes ::postvisit( EnumDecl *enumDecl ) {784 void LinkReferenceToTypes_old::postvisit( EnumDecl *enumDecl ) { 780 785 // visit enum members first so that the types of self-referencing members are updated properly 781 786 if ( enumDecl->body ) { … … 799 804 } 800 805 801 void LinkReferenceToTypes ::renameGenericParams( std::list< TypeDecl * > & params ) {806 void LinkReferenceToTypes_old::renameGenericParams( std::list< TypeDecl * > & params ) { 802 807 // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g. 803 808 // forall(otype T) … … 817 822 } 818 823 819 void LinkReferenceToTypes ::previsit( StructDecl * structDecl ) {824 void LinkReferenceToTypes_old::previsit( StructDecl * structDecl ) { 820 825 renameGenericParams( structDecl->parameters ); 821 826 } 822 827 823 void LinkReferenceToTypes ::previsit( UnionDecl * unionDecl ) {828 void LinkReferenceToTypes_old::previsit( UnionDecl * unionDecl ) { 824 829 renameGenericParams( unionDecl->parameters ); 825 830 } 826 831 827 void LinkReferenceToTypes ::postvisit( StructDecl *structDecl ) {832 void LinkReferenceToTypes_old::postvisit( StructDecl *structDecl ) { 828 833 // visit struct members first so that the types of self-referencing members are updated properly 829 834 // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults) … … 839 844 } 840 845 841 void LinkReferenceToTypes ::postvisit( UnionDecl *unionDecl ) {846 void LinkReferenceToTypes_old::postvisit( UnionDecl *unionDecl ) { 842 847 if ( unionDecl->body ) { 843 848 ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name ); … … 851 856 } 852 857 853 void LinkReferenceToTypes ::postvisit( TypeInstType *typeInst ) {858 void LinkReferenceToTypes_old::postvisit( TypeInstType *typeInst ) { 854 859 // ensure generic parameter instances are renamed like the base type 855 860 if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name; … … 888 893 } 889 894 890 void ForallPointerDecay ::previsit( ObjectDecl *object ) {895 void ForallPointerDecay_old::previsit( ObjectDecl *object ) { 891 896 // ensure that operator names only apply to functions or function pointers 892 897 if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) { … … 896 901 } 897 902 898 void ForallPointerDecay ::previsit( FunctionDecl *func ) {903 void ForallPointerDecay_old::previsit( FunctionDecl *func ) { 899 904 func->fixUniqueId(); 900 905 } 901 906 902 void ForallPointerDecay ::previsit( FunctionType * ftype ) {907 void ForallPointerDecay_old::previsit( FunctionType * ftype ) { 903 908 forallFixer( ftype->forall, ftype ); 904 909 } 905 910 906 void ForallPointerDecay ::previsit( StructDecl * aggrDecl ) {911 void ForallPointerDecay_old::previsit( StructDecl * aggrDecl ) { 907 912 forallFixer( aggrDecl->parameters, aggrDecl ); 908 913 } 909 914 910 void ForallPointerDecay ::previsit( UnionDecl * aggrDecl ) {915 void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) { 911 916 forallFixer( aggrDecl->parameters, aggrDecl ); 912 917 } … … 1368 1373 } 1369 1374 1370 const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ) { 1371 #warning unimplemented 1372 (void)type; (void)symtab; 1373 assert(false); 1374 return nullptr; 1375 } 1375 namespace { 1376 /// Replaces enum types by int, and function/array types in function parameter and return 1377 /// lists by appropriate pointers 1378 struct EnumAndPointerDecay_new { 1379 const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) { 1380 // set the type of each member of the enumeration to be EnumConstant 1381 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) { 1382 // build new version of object with EnumConstant 1383 ast::ptr< ast::ObjectDecl > obj = 1384 enumDecl->members[i].strict_as< ast::ObjectDecl >(); 1385 obj.get_and_mutate()->type = 1386 new ast::EnumInstType{ enumDecl->name, ast::CV::Const }; 1387 1388 // set into decl 1389 ast::EnumDecl * mut = mutate( enumDecl ); 1390 mut->members[i] = obj.get(); 1391 enumDecl = mut; 1392 } 1393 return enumDecl; 1394 } 1395 1396 static const ast::FunctionType * fixFunctionList( 1397 const ast::FunctionType * func, 1398 std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field, 1399 ast::ArgumentFlag isVarArgs = ast::FixedArgs 1400 ) { 1401 const auto & dwts = func->*field; 1402 unsigned nvals = dwts.size(); 1403 bool hasVoid = false; 1404 for ( unsigned i = 0; i < nvals; ++i ) { 1405 func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) ); 1406 } 1407 1408 // the only case in which "void" is valid is where it is the only one in the list 1409 if ( hasVoid && ( nvals > 1 || isVarArgs ) ) { 1410 SemanticError( 1411 dwts.front()->location, func, "invalid type void in function type" ); 1412 } 1413 1414 // one void is the only thing in the list, remove it 1415 if ( hasVoid ) { 1416 func = ast::mutate_field( 1417 func, field, std::vector< ast::ptr< ast::DeclWithType > >{} ); 1418 } 1419 1420 return func; 1421 } 1422 1423 const ast::FunctionType * previsit( const ast::FunctionType * func ) { 1424 func = fixFunctionList( func, &ast::FunctionType::params, func->isVarArgs ); 1425 return fixFunctionList( func, &ast::FunctionType::returns ); 1426 } 1427 }; 1428 1429 /// Associates forward declarations of aggregates with their definitions 1430 struct LinkReferenceToTypes_new final 1431 : public ast::WithSymbolTable, public ast::WithGuards, public 1432 ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting { 1433 1434 const ast::SymbolTable * localSyms; 1435 1436 LinkReferenceToTypes_new( const ast::SymbolTable & syms ) : localSyms( &syms ) {} 1437 1438 #warning incomplete 1439 }; 1440 1441 /// Replaces array and function types in forall lists by appropriate pointer type and assigns 1442 /// each object and function declaration a unique ID 1443 struct ForallPointerDecay_new { 1444 #warning incomplete 1445 }; 1446 } // anonymous namespace 1447 1448 const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ) { 1449 ast::Pass< EnumAndPointerDecay_new > epc; 1450 ast::Pass< LinkReferenceToTypes_new > lrt{ symtab }; 1451 ast::Pass< ForallPointerDecay_new > fpd; 1452 1453 return type->accept( epc )->accept( lrt )->accept( fpd ); 1454 } 1455 1376 1456 } // namespace SymTab 1377 1457 -
src/Tuples/Explode.cc
r3c6e417 r54dd994 133 133 if ( first ) { 134 134 castAdded = true; 135 const ast::Expr * tuple = new ast::TupleExpr( 136 tupleExpr->location, std::move( exprs ) ); 137 return new ast::CastExpr( tuple->location, 138 tuple, new ast::ReferenceType( tuple->result.get(), ast::CV::Qualifiers() ) ); 135 const ast::Expr * tuple = new ast::TupleExpr{ 136 tupleExpr->location, std::move( exprs ) }; 137 return new ast::CastExpr{ tuple, new ast::ReferenceType{ tuple->result } }; 139 138 } else { 140 139 return new ast::TupleExpr( tupleExpr->location, std::move( exprs ) ); … … 145 144 } else { 146 145 castAdded = true; 147 return new ast::CastExpr( expr->location, expr, 148 new ast::ReferenceType( expr->result, ast::CV::Qualifiers() ) ); 146 return new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } }; 149 147 } 150 148 } … … 164 162 castAdded = false; 165 163 const ast::Type * newType = getReferenceBase( newNode->result ); 166 return new ast::CastExpr ( newNode->location, node, newType );164 return new ast::CastExpr{ newNode->location, node, newType }; 167 165 } 168 166 return newNode; … … 183 181 expr = expr->accept( exploder ); 184 182 if ( ! exploder.pass.foundUniqueExpr ) { 185 expr = new ast::CastExpr( expr->location, expr, 186 new ast::ReferenceType( expr->result, ast::CV::Qualifiers() ) ); 183 expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } }; 187 184 } 188 185 return expr; -
src/Tuples/Explode.h
r3c6e417 r54dd994 211 211 // Cast a reference away to a value-type to allow further explosion. 212 212 if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) { 213 local = new ast::CastExpr ( local->location, local, tupleType );213 local = new ast::CastExpr{ local, tupleType }; 214 214 } 215 215 // Now we have to go across the tuple via indexing. … … 238 238 } 239 239 240 /// explode list of candidates into flattened list of candidates 241 template< typename Output > 242 void explode( 243 const ResolvExpr::CandidateList & cands, const ast::SymbolTable & symtab, Output && out, 244 bool isTupleAssign = false 245 ) { 246 for ( const ResolvExpr::CandidateRef & cand : cands ) { 247 explode( *cand, symtab, std::forward< Output >( out ), isTupleAssign ); 248 } 249 } 250 240 251 } // namespace Tuples 241 252 -
src/Tuples/TupleAssignment.cc
r3c6e417 r54dd994 22 22 #include <vector> 23 23 24 #include "AST/Decl.hpp" 25 #include "AST/Init.hpp" 26 #include "AST/Pass.hpp" 27 #include "AST/Stmt.hpp" 28 #include "AST/TypeEnvironment.hpp" 24 29 #include "CodeGen/OperatorTable.h" 25 30 #include "Common/PassVisitor.h" 26 31 #include "Common/UniqueName.h" // for UniqueName 27 #include "Common/utility.h" // for zipWith32 #include "Common/utility.h" // for splice, zipWith 28 33 #include "Explode.h" // for explode 29 34 #include "InitTweak/GenInit.h" // for genCtorInit … … 51 56 52 57 namespace Tuples { 53 class TupleAssignSpotter {58 class TupleAssignSpotter_old { 54 59 public: 55 60 // dispatcher for Tuple (multiple and mass) assignment operations 56 TupleAssignSpotter ( ResolvExpr::AlternativeFinder & );61 TupleAssignSpotter_old( ResolvExpr::AlternativeFinder & ); 57 62 void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args ); 58 63 … … 62 67 struct Matcher { 63 68 public: 64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,69 Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 65 70 const ResolvExpr::AltList& rhs ); 66 71 virtual ~Matcher() {} … … 80 85 81 86 ResolvExpr::AltList lhs, rhs; 82 TupleAssignSpotter &spotter;87 TupleAssignSpotter_old &spotter; 83 88 ResolvExpr::Cost baseCost; 84 89 std::list< ObjectDecl * > tmpDecls; … … 90 95 struct MassAssignMatcher : public Matcher { 91 96 public: 92 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,97 MassAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 93 98 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 94 99 virtual void match( std::list< Expression * > &out ); … … 97 102 struct MultipleAssignMatcher : public Matcher { 98 103 public: 99 MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,104 MultipleAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 100 105 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 101 106 virtual void match( std::list< Expression * > &out ); … … 136 141 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, 137 142 std::vector<ResolvExpr::AlternativeFinder> &args ) { 138 TupleAssignSpotter spotter( currentFinder );143 TupleAssignSpotter_old spotter( currentFinder ); 139 144 spotter.spot( expr, args ); 140 145 } 141 146 142 TupleAssignSpotter ::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )147 TupleAssignSpotter_old::TupleAssignSpotter_old( ResolvExpr::AlternativeFinder &f ) 143 148 : currentFinder(f) {} 144 149 145 void TupleAssignSpotter ::spot( UntypedExpr * expr,150 void TupleAssignSpotter_old::spot( UntypedExpr * expr, 146 151 std::vector<ResolvExpr::AlternativeFinder> &args ) { 147 152 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { … … 224 229 } 225 230 226 void TupleAssignSpotter ::match() {231 void TupleAssignSpotter_old::match() { 227 232 assert ( matcher != 0 ); 228 233 … … 275 280 } 276 281 277 TupleAssignSpotter ::Matcher::Matcher( TupleAssignSpotter&spotter,282 TupleAssignSpotter_old::Matcher::Matcher( TupleAssignSpotter_old &spotter, 278 283 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs ) 279 284 : lhs(lhs), rhs(rhs), spotter(spotter), … … 313 318 }; 314 319 315 ObjectDecl * TupleAssignSpotter ::Matcher::newObject( UniqueName & namer, Expression * expr ) {320 ObjectDecl * TupleAssignSpotter_old::Matcher::newObject( UniqueName & namer, Expression * expr ) { 316 321 assert( expr->result && ! expr->get_result()->isVoid() ); 317 322 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->result->clone(), new SingleInit( expr->clone() ) ); … … 329 334 } 330 335 331 void TupleAssignSpotter ::MassAssignMatcher::match( std::list< Expression * > &out ) {336 void TupleAssignSpotter_old::MassAssignMatcher::match( std::list< Expression * > &out ) { 332 337 static UniqueName lhsNamer( "__massassign_L" ); 333 338 static UniqueName rhsNamer( "__massassign_R" ); … … 347 352 } 348 353 349 void TupleAssignSpotter ::MultipleAssignMatcher::match( std::list< Expression * > &out ) {354 void TupleAssignSpotter_old::MultipleAssignMatcher::match( std::list< Expression * > &out ) { 350 355 static UniqueName lhsNamer( "__multassign_L" ); 351 356 static UniqueName rhsNamer( "__multassign_R" ); … … 378 383 } 379 384 380 void handleTupleAssignment( 381 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 382 std::vector< ResolvExpr::CandidateFinder > & args 383 ) { 384 #warning unimplmented 385 (void)finder; (void)assign; (void)args; 386 assert(false); 387 } 385 namespace { 386 /// true if `expr` is of tuple type 387 bool isTuple( const ast::Expr * expr ) { 388 if ( ! expr ) return false; 389 assert( expr->result ); 390 return dynamic_cast< const ast::TupleType * >( expr->result->stripReferences() ); 391 } 392 393 /// true if `expr` is of tuple type or a reference to one 394 bool refToTuple( const ast::Expr * expr ) { 395 assert( expr->result ); 396 // check for function returning tuple of reference types 397 if ( auto castExpr = dynamic_cast< const ast::CastExpr * >( expr ) ) { 398 return refToTuple( castExpr->arg ); 399 } else { 400 return isTuple( expr ); 401 } 402 } 403 404 /// Dispatcher for tuple (multiple and mass) assignment operations 405 class TupleAssignSpotter_new final { 406 /// Actually finds tuple assignment operations, by subclass 407 struct Matcher { 408 ResolvExpr::CandidateList lhs, rhs; 409 TupleAssignSpotter_new & spotter; 410 CodeLocation location; 411 ResolvExpr::Cost baseCost; 412 std::vector< ast::ptr< ast::ObjectDecl > > tmpDecls; 413 ast::TypeEnvironment env; 414 ast::OpenVarSet open; 415 ast::AssertionSet need; 416 417 void combineState( const ResolvExpr::Candidate & cand ) { 418 env.simpleCombine( cand.env ); 419 ast::mergeOpenVars( open, cand.open ); 420 need.insert( cand.need.begin(), cand.need.end() ); 421 } 422 423 Matcher( 424 TupleAssignSpotter_new & s, const CodeLocation & loc, 425 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r ) 426 : lhs( l ), rhs( r ), spotter( s ), location( loc ), 427 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(), 428 env(), open(), need() { 429 for ( auto & cand : lhs ) combineState( *cand ); 430 for ( auto & cand : rhs ) combineState( *cand ); 431 } 432 433 virtual std::vector< ast::ptr< ast::Expr > > match() = 0; 434 435 /// removes environments from subexpressions within statement expressions, which could 436 /// throw off later passes like those in Box which rely on PolyMutator, and adds the 437 /// bindings to the env 438 struct EnvRemover { 439 /// environment to hoist ExprStmt environments to 440 ast::TypeEnvironment & tenv; 441 442 EnvRemover( ast::TypeEnvironment & e ) : tenv( e ) {} 443 444 const ast::ExprStmt * previsit( const ast::ExprStmt * stmt ) { 445 if ( stmt->expr->env ) { 446 tenv.add( *stmt->expr->env ); 447 ast::ExprStmt * mut = mutate( stmt ); 448 mut->expr.get_and_mutate()->env = nullptr; 449 return mut; 450 } 451 return stmt; 452 } 453 }; 454 455 ast::ObjectDecl * newObject( UniqueName & namer, const ast::Expr * expr ) { 456 assert( expr->result && ! expr->result->isVoid() ); 457 458 ast::ObjectDecl * ret = new ast::ObjectDecl{ 459 location, namer.newName(), expr->result, new ast::SingleInit{ location, expr }, 460 ast::Storage::Classes{}, ast::Linkage::Cforall }; 461 462 // if expression type is a reference, just need an initializer, otherwise construct 463 if ( ! expr->result.as< ast::ReferenceType >() ) { 464 // resolve ctor/dtor for the new object 465 ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 466 InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab ); 467 // remove environments from subexpressions of stmtExpr 468 ast::Pass< EnvRemover > rm{ env }; 469 ret->init = ctorInit->accept( rm ); 470 } 471 472 PRINT( std::cerr << "new object: " << ret << std::endl; ) 473 return ret; 474 } 475 476 ast::UntypedExpr * createFunc( 477 const std::string & fname, const ast::ObjectDecl * left, 478 const ast::ObjectDecl * right 479 ) { 480 assert( left ); 481 std::vector< ast::ptr< ast::Expr > > args; 482 args.emplace_back( new ast::VariableExpr{ location, left } ); 483 if ( right ) { args.emplace_back( new ast::VariableExpr{ location, right } ); } 484 485 if ( left->type->referenceDepth() > 1 && CodeGen::isConstructor( fname ) ) { 486 args.front() = new ast::AddressExpr{ location, args.front() }; 487 if ( right ) { args.back() = new ast::AddressExpr{ location, args.back() }; } 488 return new ast::UntypedExpr{ 489 location, new ast::NameExpr{ location, "?=?" }, std::move(args) }; 490 } else { 491 return new ast::UntypedExpr{ 492 location, new ast::NameExpr{ location, fname }, std::move(args) }; 493 } 494 } 495 }; 496 497 /// Finds mass-assignment operations 498 struct MassAssignMatcher final : public Matcher { 499 MassAssignMatcher( 500 TupleAssignSpotter_new & s, const CodeLocation & loc, 501 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r ) 502 : Matcher( s, loc, l, r ) {} 503 504 std::vector< ast::ptr< ast::Expr > > match() override { 505 static UniqueName lhsNamer( "__massassign_L" ); 506 static UniqueName rhsNamer( "__massassign_R" ); 507 // empty tuple case falls into this matcher 508 assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 ); 509 510 ast::ptr< ast::ObjectDecl > rtmp = 511 rhs.size() == 1 ? newObject( rhsNamer, rhs.front()->expr ) : nullptr; 512 513 std::vector< ast::ptr< ast::Expr > > out; 514 for ( ResolvExpr::CandidateRef & lhsCand : lhs ) { 515 // create a temporary object for each value in the LHS and create a call 516 // involving the RHS 517 ast::ptr< ast::ObjectDecl > ltmp = newObject( lhsNamer, lhsCand->expr ); 518 out.emplace_back( createFunc( spotter.fname, ltmp, rtmp ) ); 519 tmpDecls.emplace_back( std::move( ltmp ) ); 520 } 521 if ( rtmp ) tmpDecls.emplace_back( std::move( rtmp ) ); 522 523 return out; 524 } 525 }; 526 527 /// Finds multiple-assignment operations 528 struct MultipleAssignMatcher final : public Matcher { 529 MultipleAssignMatcher( 530 TupleAssignSpotter_new & s, const CodeLocation & loc, 531 const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r ) 532 : Matcher( s, loc, l, r ) {} 533 534 std::vector< ast::ptr< ast::Expr > > match() override { 535 static UniqueName lhsNamer( "__multassign_L" ); 536 static UniqueName rhsNamer( "__multassign_R" ); 537 538 if ( lhs.size() != rhs.size() ) return {}; 539 540 // produce a new temporary object for each value in the LHS and RHS and pairwise 541 // create the calls 542 std::vector< ast::ptr< ast::ObjectDecl > > ltmp, rtmp; 543 544 std::vector< ast::ptr< ast::Expr > > out; 545 for ( unsigned i = 0; i < lhs.size(); ++i ) { 546 ResolvExpr::CandidateRef & lhsCand = lhs[i]; 547 ResolvExpr::CandidateRef & rhsCand = rhs[i]; 548 549 // convert RHS to LHS type minus one reference -- important for case where LHS 550 // is && and RHS is lvalue 551 auto lhsType = lhsCand->expr->result.strict_as< ast::ReferenceType >(); 552 rhsCand->expr = new ast::CastExpr{ rhsCand->expr, lhsType->base }; 553 ast::ptr< ast::ObjectDecl > lobj = newObject( lhsNamer, lhsCand->expr ); 554 ast::ptr< ast::ObjectDecl > robj = newObject( rhsNamer, rhsCand->expr ); 555 out.emplace_back( createFunc( spotter.fname, lobj, robj ) ); 556 ltmp.emplace_back( std::move( lobj ) ); 557 rtmp.emplace_back( std::move( robj ) ); 558 559 // resolve the cast expression so that rhsCand return type is bound by the cast 560 // type as needed, and transfer the resulting environment 561 ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env }; 562 finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() ); 563 assert( finder.candidates.size() == 1 ); 564 env = std::move( finder.candidates.front()->env ); 565 } 566 567 splice( tmpDecls, ltmp ); 568 splice( tmpDecls, rtmp ); 569 570 return out; 571 } 572 }; 573 574 ResolvExpr::CandidateFinder & crntFinder; 575 std::string fname; 576 std::unique_ptr< Matcher > matcher; 577 578 public: 579 TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f ) 580 : crntFinder( f ), fname(), matcher() {} 581 582 // find left- and right-hand-sides for mass or multiple assignment 583 void spot( 584 const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args 585 ) { 586 if ( auto op = expr->func.as< ast::NameExpr >() ) { 587 // skip non-assignment functions 588 if ( ! CodeGen::isCtorDtorAssign( op->name ) ) return; 589 fname = op->name; 590 591 // handled by CandidateFinder if applicable (both odd cases) 592 if ( args.empty() || ( args.size() == 1 && CodeGen::isAssignment( fname ) ) ) { 593 return; 594 } 595 596 // look over all possible left-hand-side 597 for ( ResolvExpr::CandidateRef & lhsCand : args[0] ) { 598 // skip non-tuple LHS 599 if ( ! refToTuple( lhsCand->expr ) ) continue; 600 601 // explode is aware of casts - ensure every LHS is sent into explode with a 602 // reference cast 603 if ( ! lhsCand->expr.as< ast::CastExpr >() ) { 604 lhsCand->expr = new ast::CastExpr{ 605 lhsCand->expr, new ast::ReferenceType{ lhsCand->expr->result } }; 606 } 607 608 // explode the LHS so that each field of a tuple-valued expr is assigned 609 ResolvExpr::CandidateList lhs; 610 explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true ); 611 for ( ResolvExpr::CandidateRef & cand : lhs ) { 612 // each LHS value must be a reference - some come in with a cast, if not 613 // just cast to reference here 614 if ( ! cand->expr->result.as< ast::ReferenceType >() ) { 615 cand->expr = new ast::CastExpr{ 616 cand->expr, new ast::ReferenceType{ cand->expr->result } }; 617 } 618 } 619 620 if ( args.size() == 1 ) { 621 // mass default-initialization/destruction 622 ResolvExpr::CandidateList rhs{}; 623 matcher.reset( new MassAssignMatcher{ *this, expr->location, lhs, rhs } ); 624 match(); 625 } else if ( args.size() == 2 ) { 626 for ( const ResolvExpr::CandidateRef & rhsCand : args[1] ) { 627 ResolvExpr::CandidateList rhs; 628 if ( isTuple( rhsCand->expr ) ) { 629 // multiple assignment 630 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 631 matcher.reset( 632 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); 633 } else { 634 // mass assignment 635 rhs.emplace_back( rhsCand ); 636 matcher.reset( 637 new MassAssignMatcher{ *this, expr->location, lhs, rhs } ); 638 } 639 match(); 640 } 641 } else { 642 // expand all possible RHS possibilities 643 std::vector< ResolvExpr::CandidateList > rhsCands; 644 combos( 645 std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) ); 646 for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) { 647 // multiple assignment 648 ResolvExpr::CandidateList rhs; 649 explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true ); 650 matcher.reset( 651 new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } ); 652 match(); 653 } 654 } 655 } 656 } 657 } 658 659 void match() { 660 assert( matcher ); 661 662 std::vector< ast::ptr< ast::Expr > > newAssigns = matcher->match(); 663 664 if ( ! ( matcher->lhs.empty() && matcher->rhs.empty() ) ) { 665 // if both LHS and RHS are empty than this is the empty tuple case, wherein it's 666 // okay for newAssigns to be empty. Otherwise, return early so that no new 667 // candidates are generated 668 if ( newAssigns.empty() ) return; 669 } 670 671 ResolvExpr::CandidateList crnt; 672 // now resolve new assignments 673 for ( const ast::Expr * expr : newAssigns ) { 674 PRINT( 675 std::cerr << "== resolving tuple assign ==" << std::endl; 676 std::cerr << expr << std::endl; 677 ) 678 679 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env }; 680 681 try { 682 finder.find( expr, ResolvExpr::ResolvMode::withAdjustment() ); 683 } catch (...) { 684 // no match is not failure, just that this tuple assignment is invalid 685 return; 686 } 687 688 ResolvExpr::CandidateList & cands = finder.candidates; 689 assert( cands.size() == 1 ); 690 assert( cands.front()->expr ); 691 crnt.emplace_back( std::move( cands.front() ) ); 692 } 693 694 // extract expressions from the assignment candidates to produce a list of assignments 695 // that together form a sigle candidate 696 std::vector< ast::ptr< ast::Expr > > solved; 697 for ( ResolvExpr::CandidateRef & cand : crnt ) { 698 solved.emplace_back( cand->expr ); 699 matcher->combineState( *cand ); 700 } 701 702 crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >( 703 new ast::TupleAssignExpr{ 704 matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) }, 705 std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ), 706 ResolvExpr::sumCost( crnt ) + matcher->baseCost ) ); 707 } 708 }; 709 } // anonymous namespace 710 711 void handleTupleAssignment( 712 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 713 std::vector< ResolvExpr::CandidateFinder > & args 714 ) { 715 TupleAssignSpotter_new spotter{ finder }; 716 spotter.spot( assign, args ); 717 } 718 388 719 } // namespace Tuples 389 720
Note:
See TracChangeset
for help on using the changeset viewer.