Changeset 7030dab for src/Concurrency/Keywords.cc
- Timestamp:
- Apr 6, 2020, 4:46:28 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- e3bc51c
- Parents:
- 71d6bd8 (diff), 057298e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Concurrency/Keywords.cc
r71d6bd8 r7030dab 11 11 // Last Modified By : 12 12 // Last Modified On : 13 // Update Count : 513 // Update Count : 10 14 14 // 15 15 16 16 #include "Concurrency/Keywords.h" 17 17 18 #include <cassert> // for assert 19 #include <string> // for string, operator== 20 21 #include "Common/PassVisitor.h" // for PassVisitor 22 #include "Common/SemanticError.h" // for SemanticError 23 #include "Common/utility.h" // for deleteAll, map_range 24 #include "CodeGen/OperatorTable.h" // for isConstructor 25 #include "InitTweak/InitTweak.h" // for getPointerBase 26 #include "Parser/LinkageSpec.h" // for Cforall 27 #include "SynTree/Constant.h" // for Constant 28 #include "SynTree/Declaration.h" // for StructDecl, FunctionDecl, ObjectDecl 29 #include "SynTree/Expression.h" // for VariableExpr, ConstantExpr, Untype... 30 #include "SynTree/Initializer.h" // for SingleInit, ListInit, Initializer ... 31 #include "SynTree/Label.h" // for Label 32 #include "SynTree/Statement.h" // for CompoundStmt, DeclStmt, ExprStmt 33 #include "SynTree/Type.h" // for StructInstType, Type, PointerType 34 #include "SynTree/Visitor.h" // for Visitor, acceptAll 18 #include <cassert> // for assert 19 #include <string> // for string, operator== 20 21 #include "Common/PassVisitor.h" // for PassVisitor 22 #include "Common/SemanticError.h" // for SemanticError 23 #include "Common/utility.h" // for deleteAll, map_range 24 #include "CodeGen/OperatorTable.h" // for isConstructor 25 #include "ControlStruct/LabelGenerator.h" // for LebelGenerator 26 #include "InitTweak/InitTweak.h" // for getPointerBase 27 #include "SynTree/LinkageSpec.h" // for Cforall 28 #include "SynTree/Constant.h" // for Constant 29 #include "SynTree/Declaration.h" // for StructDecl, FunctionDecl, ObjectDecl 30 #include "SynTree/Expression.h" // for VariableExpr, ConstantExpr, Untype... 31 #include "SynTree/Initializer.h" // for SingleInit, ListInit, Initializer ... 32 #include "SynTree/Label.h" // for Label 33 #include "SynTree/Statement.h" // for CompoundStmt, DeclStmt, ExprStmt 34 #include "SynTree/Type.h" // for StructInstType, Type, PointerType 35 #include "SynTree/Visitor.h" // for Visitor, acceptAll 35 36 36 37 class Attribute; … … 53 54 public: 54 55 55 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, KeywordCastExpr::Targetcast_target ) :56 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, AggregateDecl::Aggregate cast_target ) : 56 57 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ), cast_target( cast_target ) {} 57 58 … … 59 60 60 61 Declaration * postmutate( StructDecl * decl ); 62 DeclarationWithType * postmutate( FunctionDecl * decl ); 61 63 62 64 void handle( StructDecl * ); … … 75 77 const std::string context_error; 76 78 bool needs_main; 77 KeywordCastExpr::Target cast_target; 78 79 StructDecl* type_decl = nullptr; 79 AggregateDecl::Aggregate cast_target; 80 81 StructDecl * type_decl = nullptr; 82 FunctionDecl * dtor_decl = nullptr; 80 83 }; 81 84 … … 86 89 // int data; int data; 87 90 // a_struct_t more_data; a_struct_t more_data; 88 // => thread_desc__thrd_d;91 // => $thread __thrd_d; 89 92 // }; }; 90 // static inline thread_desc* get_thread( MyThread * this ) { return &this->__thrd_d; }93 // static inline $thread * get_thread( MyThread * this ) { return &this->__thrd_d; } 91 94 // 92 95 class ThreadKeyword final : public ConcurrentSueKeyword { … … 94 97 95 98 ThreadKeyword() : ConcurrentSueKeyword( 96 " thread_desc",99 "$thread", 97 100 "__thrd", 98 101 "get_thread", 99 "thread keyword requires threads to be in scope, add #include <thread.hfa> ",102 "thread keyword requires threads to be in scope, add #include <thread.hfa>\n", 100 103 true, 101 KeywordCastExpr::Thread104 AggregateDecl::Thread 102 105 ) 103 106 {} … … 118 121 // int data; int data; 119 122 // a_struct_t more_data; a_struct_t more_data; 120 // => coroutine_desc__cor_d;123 // => $coroutine __cor_d; 121 124 // }; }; 122 // static inline coroutine_desc* get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }125 // static inline $coroutine * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; } 123 126 // 124 127 class CoroutineKeyword final : public ConcurrentSueKeyword { … … 126 129 127 130 CoroutineKeyword() : ConcurrentSueKeyword( 128 " coroutine_desc",131 "$coroutine", 129 132 "__cor", 130 133 "get_coroutine", 131 "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa> ",134 "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n", 132 135 true, 133 KeywordCastExpr::Coroutine136 AggregateDecl::Coroutine 134 137 ) 135 138 {} … … 144 147 } 145 148 }; 149 150 146 151 147 152 //----------------------------------------------------------------------------- … … 150 155 // int data; int data; 151 156 // a_struct_t more_data; a_struct_t more_data; 152 // => monitor_desc__mon_d;157 // => $monitor __mon_d; 153 158 // }; }; 154 // static inline monitor_desc* get_coroutine( MyMonitor * this ) { return &this->__cor_d; }159 // static inline $monitor * get_coroutine( MyMonitor * this ) { return &this->__cor_d; } 155 160 // 156 161 class MonitorKeyword final : public ConcurrentSueKeyword { … … 158 163 159 164 MonitorKeyword() : ConcurrentSueKeyword( 160 " monitor_desc",165 "$monitor", 161 166 "__mon", 162 167 "get_monitor", 163 "monitor keyword requires monitors to be in scope, add #include <monitor.hfa> ",168 "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n", 164 169 false, 165 KeywordCastExpr::Monitor170 AggregateDecl::Monitor 166 171 ) 167 172 {} … … 178 183 179 184 //----------------------------------------------------------------------------- 185 //Handles generator type declarations : 186 // generator MyGenerator { struct MyGenerator { 187 // int data; int data; 188 // a_struct_t more_data; a_struct_t more_data; 189 // => int __gen_next; 190 // }; }; 191 // 192 class GeneratorKeyword final : public ConcurrentSueKeyword { 193 public: 194 195 GeneratorKeyword() : ConcurrentSueKeyword( 196 "$generator", 197 "__generator_state", 198 "get_generator", 199 "Unable to find builtin type $generator\n", 200 true, 201 AggregateDecl::Generator 202 ) 203 {} 204 205 virtual ~GeneratorKeyword() {} 206 207 virtual bool is_target( StructDecl * decl ) override final { return decl->is_generator(); } 208 209 static void implement( std::list< Declaration * > & translationUnit ) { 210 PassVisitor< GeneratorKeyword > impl; 211 mutateAll( translationUnit, impl ); 212 } 213 }; 214 215 216 //----------------------------------------------------------------------------- 217 class SuspendKeyword final : public WithStmtsToAdd, public WithGuards { 218 public: 219 SuspendKeyword() = default; 220 virtual ~SuspendKeyword() = default; 221 222 void premutate( FunctionDecl * ); 223 DeclarationWithType * postmutate( FunctionDecl * ); 224 225 Statement * postmutate( SuspendStmt * ); 226 227 static void implement( std::list< Declaration * > & translationUnit ) { 228 PassVisitor< SuspendKeyword > impl; 229 mutateAll( translationUnit, impl ); 230 } 231 232 private: 233 DeclarationWithType * is_main( FunctionDecl * ); 234 bool is_real_suspend( FunctionDecl * ); 235 236 Statement * make_generator_suspend( SuspendStmt * ); 237 Statement * make_coroutine_suspend( SuspendStmt * ); 238 239 struct LabelPair { 240 Label obj; 241 int idx; 242 }; 243 244 LabelPair make_label() { 245 labels.push_back( gen.newLabel("generator") ); 246 return { labels.back(), int(labels.size()) }; 247 } 248 249 DeclarationWithType * in_generator = nullptr; 250 FunctionDecl * decl_suspend = nullptr; 251 std::vector<Label> labels; 252 ControlStruct::LabelGenerator & gen = *ControlStruct::LabelGenerator::getGenerator(); 253 }; 254 255 //----------------------------------------------------------------------------- 180 256 //Handles mutex routines definitions : 181 257 // void foo( A * mutex a, B * mutex b, int i ) { void foo( A * a, B * b, int i ) { 182 // monitor_desc* __monitors[] = { get_monitor(a), get_monitor(b) };258 // $monitor * __monitors[] = { get_monitor(a), get_monitor(b) }; 183 259 // monitor_guard_t __guard = { __monitors, 2 }; 184 260 // /*Some code*/ => /*Some code*/ … … 219 295 //Handles mutex routines definitions : 220 296 // void foo( A * mutex a, B * mutex b, int i ) { void foo( A * a, B * b, int i ) { 221 // monitor_desc* __monitors[] = { get_monitor(a), get_monitor(b) };297 // $monitor * __monitors[] = { get_monitor(a), get_monitor(b) }; 222 298 // monitor_guard_t __guard = { __monitors, 2 }; 223 299 // /*Some code*/ => /*Some code*/ … … 249 325 CoroutineKeyword ::implement( translationUnit ); 250 326 MonitorKeyword ::implement( translationUnit ); 327 GeneratorKeyword ::implement( translationUnit ); 328 SuspendKeyword ::implement( translationUnit ); 251 329 } 252 330 … … 284 362 } 285 363 364 DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) { 365 if( !type_decl ) return decl; 366 if( !CodeGen::isDestructor( decl->name ) ) return decl; 367 368 auto params = decl->type->parameters; 369 if( params.size() != 1 ) return decl; 370 371 auto type = dynamic_cast<ReferenceType*>( params.front()->get_type() ); 372 if( !type ) return decl; 373 374 auto stype = dynamic_cast<StructInstType*>( type->base ); 375 if( !stype ) return decl; 376 if( stype->baseStruct != type_decl ) return decl; 377 378 if( !dtor_decl ) dtor_decl = decl; 379 return decl; 380 } 381 286 382 Expression * ConcurrentSueKeyword::postmutate( KeywordCastExpr * cast ) { 287 383 if ( cast_target == cast->target ) { 288 // convert (thread &)t to ( thread_desc&)*get_thread(t), etc.384 // convert (thread &)t to ($thread &)*get_thread(t), etc. 289 385 if( !type_decl ) SemanticError( cast, context_error ); 290 Expression * arg = cast->arg; 291 cast->arg = nullptr; 292 delete cast; 293 return new CastExpr( 294 UntypedExpr::createDeref( 295 new UntypedExpr( new NameExpr( getter_name ), { arg } ) 296 ), 297 new ReferenceType( 298 noQualifiers, 299 new StructInstType( noQualifiers, type_decl ) ) 300 ); 386 if( !dtor_decl ) SemanticError( cast, context_error ); 387 assert( cast->result == nullptr ); 388 cast->set_result( new ReferenceType( noQualifiers, new StructInstType( noQualifiers, type_decl ) ) ); 389 cast->concrete_target.field = field_name; 390 cast->concrete_target.getter = getter_name; 301 391 } 302 392 return cast; … … 308 398 309 399 if( !type_decl ) SemanticError( decl, context_error ); 400 if( !dtor_decl ) SemanticError( decl, context_error ); 310 401 311 402 FunctionDecl * func = forwardDeclare( decl ); … … 362 453 get_type, 363 454 nullptr, 364 noAttributes,455 { new Attribute("const") }, 365 456 Type::Inline 366 457 ); … … 431 522 432 523 declsToAddAfter.push_back( get_decl ); 433 434 // get_decl->fixUniqueId(); 435 } 524 } 525 526 //============================================================================================= 527 // Suspend keyword implementation 528 //============================================================================================= 529 DeclarationWithType * SuspendKeyword::is_main( FunctionDecl * func) { 530 if(func->name != "main") return nullptr; 531 if(func->type->parameters.size() != 1) return nullptr; 532 533 auto param = func->type->parameters.front(); 534 535 auto type = dynamic_cast<ReferenceType * >(param->get_type()); 536 if(!type) return nullptr; 537 538 auto obj = dynamic_cast<StructInstType *>(type->base); 539 if(!obj) return nullptr; 540 541 if(!obj->baseStruct->is_generator()) return nullptr; 542 543 return param; 544 } 545 546 bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) { 547 if(isMangled(func->linkage)) return false; // the real suspend isn't mangled 548 if(func->name != "__cfactx_suspend") return false; // the real suspend has a specific name 549 if(func->type->parameters.size() != 0) return false; // Too many parameters 550 if(func->type->returnVals.size() != 0) return false; // Too many return values 551 552 return true; 553 } 554 555 void SuspendKeyword::premutate( FunctionDecl * func ) { 556 GuardValue(in_generator); 557 in_generator = nullptr; 558 559 // Is this the real suspend? 560 if(is_real_suspend(func)) { 561 decl_suspend = decl_suspend ? decl_suspend : func; 562 return; 563 } 564 565 // Is this the main of a generator? 566 auto param = is_main( func ); 567 if(!param) return; 568 569 if(func->type->returnVals.size() != 0) SemanticError(func->location, "Generator main must return void"); 570 571 in_generator = param; 572 GuardValue(labels); 573 labels.clear(); 574 } 575 576 DeclarationWithType * SuspendKeyword::postmutate( FunctionDecl * func ) { 577 if( !func->statements ) return func; // Not the actual definition, don't do anything 578 if( !in_generator ) return func; // Not in a generator, don't do anything 579 if( labels.empty() ) return func; // Generator has no states, nothing to do, could throw a warning 580 581 // This is a generator main, we need to add the following code to the top 582 // static void * __generator_labels[] = {&&s0, &&s1, ...}; 583 // goto * __generator_labels[gen.__generator_state]; 584 const auto & loc = func->location; 585 586 const auto first_label = gen.newLabel("generator"); 587 588 // for each label add to declaration 589 std::list<Initializer*> inits = { new SingleInit( new LabelAddressExpr( first_label ) ) }; 590 for(const auto & label : labels) { 591 inits.push_back( 592 new SingleInit( 593 new LabelAddressExpr( label ) 594 ) 595 ); 596 } 597 auto init = new ListInit(std::move(inits), noDesignators, true); 598 labels.clear(); 599 600 // create decl 601 auto decl = new ObjectDecl( 602 "__generator_labels", 603 Type::StorageClasses( Type::Static ), 604 LinkageSpec::AutoGen, 605 nullptr, 606 new ArrayType( 607 Type::Qualifiers(), 608 new PointerType( 609 Type::Qualifiers(), 610 new VoidType( Type::Qualifiers() ) 611 ), 612 nullptr, 613 false, false 614 ), 615 init 616 ); 617 618 // create the goto 619 assert(in_generator); 620 621 auto go_decl = new ObjectDecl( 622 "__generator_label", 623 noStorageClasses, 624 LinkageSpec::AutoGen, 625 nullptr, 626 new PointerType( 627 Type::Qualifiers(), 628 new VoidType( Type::Qualifiers() ) 629 ), 630 new SingleInit( 631 new UntypedExpr( 632 new NameExpr("?[?]"), 633 { 634 new NameExpr("__generator_labels"), 635 new UntypedMemberExpr( 636 new NameExpr("__generator_state"), 637 new VariableExpr( in_generator ) 638 ) 639 } 640 ) 641 ) 642 ); 643 go_decl->location = loc; 644 645 auto go = new BranchStmt( 646 new VariableExpr( go_decl ), 647 BranchStmt::Goto 648 ); 649 go->location = loc; 650 go->computedTarget->location = loc; 651 652 auto noop = new NullStmt({ first_label }); 653 noop->location = loc; 654 655 // wrap everything in a nice compound 656 auto body = new CompoundStmt({ 657 new DeclStmt( decl ), 658 new DeclStmt( go_decl ), 659 go, 660 noop, 661 func->statements 662 }); 663 body->location = loc; 664 func->statements = body; 665 666 return func; 667 } 668 669 Statement * SuspendKeyword::postmutate( SuspendStmt * stmt ) { 670 SuspendStmt::Type type = stmt->type; 671 if(type == SuspendStmt::None) { 672 // This suspend has a implicit target, find it 673 type = in_generator ? SuspendStmt::Generator : SuspendStmt::Coroutine; 674 } 675 676 // Check that the target makes sense 677 if(!in_generator && type == SuspendStmt::Generator) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type."); 678 679 // Act appropriately 680 switch(type) { 681 case SuspendStmt::Generator: return make_generator_suspend(stmt); 682 case SuspendStmt::Coroutine: return make_coroutine_suspend(stmt); 683 default: abort(); 684 } 685 } 686 687 Statement * SuspendKeyword::make_generator_suspend( SuspendStmt * stmt ) { 688 assert(in_generator); 689 // Target code is : 690 // gen.__generator_state = X; 691 // { THEN } 692 // return; 693 // __gen_X:; 694 695 // Save the location and delete the old statement, we only need the location from this point on 696 auto loc = stmt->location; 697 698 // Build the label and get its index 699 auto label = make_label(); 700 701 // Create the context saving statement 702 auto save = new ExprStmt( new UntypedExpr( 703 new NameExpr( "?=?" ), 704 { 705 new UntypedMemberExpr( 706 new NameExpr("__generator_state"), 707 new VariableExpr( in_generator ) 708 ), 709 new ConstantExpr( 710 Constant::from_int( label.idx ) 711 ) 712 } 713 )); 714 assert(save->expr); 715 save->location = loc; 716 stmtsToAddBefore.push_back( save ); 717 718 // if we have a then add it here 719 auto then = stmt->then; 720 stmt->then = nullptr; 721 delete stmt; 722 if(then) stmtsToAddBefore.push_back( then ); 723 724 // Create the return statement 725 auto ret = new ReturnStmt( nullptr ); 726 ret->location = loc; 727 stmtsToAddBefore.push_back( ret ); 728 729 // Create the null statement with the created label 730 auto noop = new NullStmt({ label.obj }); 731 noop->location = loc; 732 733 // Return the null statement to take the place of the previous statement 734 return noop; 735 } 736 737 Statement * SuspendKeyword::make_coroutine_suspend( SuspendStmt * stmt ) { 738 if(stmt->then) SemanticError( stmt->location, "Compound statement following coroutines is not implemented."); 739 740 // Save the location and delete the old statement, we only need the location from this point on 741 auto loc = stmt->location; 742 delete stmt; 743 744 // Create the call expression 745 if(!decl_suspend) SemanticError( loc, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n"); 746 auto expr = new UntypedExpr( VariableExpr::functionPointer( decl_suspend ) ); 747 expr->location = loc; 748 749 // Change this statement into a regular expr 750 assert(expr); 751 auto nstmt = new ExprStmt( expr ); 752 nstmt->location = loc; 753 return nstmt; 754 } 755 436 756 437 757 //============================================================================================= … … 501 821 void MutexKeyword::postvisit(StructDecl* decl) { 502 822 503 if( decl->name == " monitor_desc" && decl->body ) {823 if( decl->name == "$monitor" && decl->body ) { 504 824 assert( !monitor_decl ); 505 825 monitor_decl = decl; … … 597 917 ); 598 918 599 // monitor_desc* __monitors[] = { get_monitor(a), get_monitor(b) };919 //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) }; 600 920 body->push_front( new DeclStmt( monitors) ); 601 921 } … … 658 978 ); 659 979 660 // monitor_desc* __monitors[] = { get_monitor(a), get_monitor(b) };980 //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) }; 661 981 body->push_front( new DeclStmt( monitors) ); 662 982 } … … 666 986 //============================================================================================= 667 987 void ThreadStarter::previsit( StructDecl * decl ) { 668 if( decl->name == " thread_desc" && decl->body ) {988 if( decl->name == "$thread" && decl->body ) { 669 989 assert( !thread_decl ); 670 990 thread_decl = decl; … … 701 1021 new UntypedExpr( 702 1022 new NameExpr( "__thrd_start" ), 703 { new VariableExpr( param ) }1023 { new VariableExpr( param ), new NameExpr("main") } 704 1024 ) 705 1025 )
Note:
See TracChangeset
for help on using the changeset viewer.