Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Keywords.cc

    re6cfa8ff r09f357ec  
    1616#include "Concurrency/Keywords.h"
    1717
    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
     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 "SynTree/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
    3635
    3736class Attribute;
     
    8988        //      int data;                                  int data;
    9089        //      a_struct_t more_data;                      a_struct_t more_data;
    91         //                                =>             $thread __thrd_d;
     90        //                                =>             thread_desc __thrd_d;
    9291        // };                                        };
    93         //                                           static inline $thread * get_thread( MyThread * this ) { return &this->__thrd_d; }
     92        //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
    9493        //
    9594        class ThreadKeyword final : public ConcurrentSueKeyword {
     
    9796
    9897                ThreadKeyword() : ConcurrentSueKeyword(
    99                         "$thread",
     98                        "thread_desc",
    10099                        "__thrd",
    101100                        "get_thread",
     
    121120        //      int data;                                  int data;
    122121        //      a_struct_t more_data;                      a_struct_t more_data;
    123         //                                =>             $coroutine __cor_d;
     122        //                                =>             coroutine_desc __cor_d;
    124123        // };                                        };
    125         //                                           static inline $coroutine * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
     124        //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
    126125        //
    127126        class CoroutineKeyword final : public ConcurrentSueKeyword {
     
    129128
    130129                CoroutineKeyword() : ConcurrentSueKeyword(
    131                         "$coroutine",
     130                        "coroutine_desc",
    132131                        "__cor",
    133132                        "get_coroutine",
     
    148147        };
    149148
    150 
    151 
    152149        //-----------------------------------------------------------------------------
    153150        //Handles monitor type declarations :
     
    155152        //      int data;                                  int data;
    156153        //      a_struct_t more_data;                      a_struct_t more_data;
    157         //                                =>             $monitor __mon_d;
     154        //                                =>             monitor_desc __mon_d;
    158155        // };                                        };
    159         //                                           static inline $monitor * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
     156        //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
    160157        //
    161158        class MonitorKeyword final : public ConcurrentSueKeyword {
     
    163160
    164161                MonitorKeyword() : ConcurrentSueKeyword(
    165                         "$monitor",
     162                        "monitor_desc",
    166163                        "__mon",
    167164                        "get_monitor",
     
    183180
    184181        //-----------------------------------------------------------------------------
    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         //-----------------------------------------------------------------------------
    256182        //Handles mutex routines definitions :
    257183        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
    258         //                                                                       $monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
     184        //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    259185        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
    260186        //    /*Some code*/                                       =>           /*Some code*/
     
    295221        //Handles mutex routines definitions :
    296222        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
    297         //                                                                       $monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
     223        //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    298224        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
    299225        //    /*Some code*/                                       =>           /*Some code*/
     
    325251                CoroutineKeyword        ::implement( translationUnit );
    326252                MonitorKeyword  ::implement( translationUnit );
    327                 GeneratorKeyword  ::implement( translationUnit );
    328                 SuspendKeyword    ::implement( translationUnit );
    329253        }
    330254
     
    382306        Expression * ConcurrentSueKeyword::postmutate( KeywordCastExpr * cast ) {
    383307                if ( cast_target == cast->target ) {
    384                         // convert (thread &)t to ($thread &)*get_thread(t), etc.
     308                        // convert (thread &)t to (thread_desc &)*get_thread(t), etc.
    385309                        if( !type_decl ) SemanticError( cast, context_error );
    386310                        if( !dtor_decl ) SemanticError( cast, context_error );
     
    453377                        get_type,
    454378                        nullptr,
    455                         { new Attribute("const") },
     379                        noAttributes,
    456380                        Type::Inline
    457381                );
     
    522446
    523447                declsToAddAfter.push_back( get_decl );
    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 
     448
     449                // get_decl->fixUniqueId();
     450        }
    756451
    757452        //=============================================================================================
     
    821516        void MutexKeyword::postvisit(StructDecl* decl) {
    822517
    823                 if( decl->name == "$monitor" && decl->body ) {
     518                if( decl->name == "monitor_desc" && decl->body ) {
    824519                        assert( !monitor_decl );
    825520                        monitor_decl = decl;
     
    917612                );
    918613
    919                 //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
     614                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    920615                body->push_front( new DeclStmt( monitors) );
    921616        }
     
    978673                );
    979674
    980                 //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
     675                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    981676                body->push_front( new DeclStmt( monitors) );
    982677        }
     
    986681        //=============================================================================================
    987682        void ThreadStarter::previsit( StructDecl * decl ) {
    988                 if( decl->name == "$thread" && decl->body ) {
     683                if( decl->name == "thread_desc" && decl->body ) {
    989684                        assert( !thread_decl );
    990685                        thread_decl = decl;
Note: See TracChangeset for help on using the changeset viewer.