Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Keywords.cc

    re6cfa8ff r2bf7ef6  
    1111// Last Modified By :
    1212// Last Modified On :
    13 // Update Count     : 10
     13// Update Count     : 5
    1414//
    1515
    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 "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
    3635
    3736class Attribute;
     
    5453          public:
    5554
    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 ) :
     55                ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, KeywordCastExpr::Target cast_target ) :
    5756                  type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ), cast_target( cast_target ) {}
    5857
     
    6059
    6160                Declaration * postmutate( StructDecl * decl );
    62                 DeclarationWithType * postmutate( FunctionDecl * decl );
    6361
    6462                void handle( StructDecl * );
     
    7775                const std::string context_error;
    7876                bool needs_main;
    79                 AggregateDecl::Aggregate cast_target;
    80 
    81                 StructDecl   * type_decl = nullptr;
    82                 FunctionDecl * dtor_decl = nullptr;
     77                KeywordCastExpr::Target cast_target;
     78
     79                StructDecl* type_decl = nullptr;
    8380        };
    8481
     
    8986        //      int data;                                  int data;
    9087        //      a_struct_t more_data;                      a_struct_t more_data;
    91         //                                =>             $thread __thrd_d;
     88        //                                =>             thread_desc __thrd_d;
    9289        // };                                        };
    93         //                                           static inline $thread * get_thread( MyThread * this ) { return &this->__thrd_d; }
     90        //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
    9491        //
    9592        class ThreadKeyword final : public ConcurrentSueKeyword {
     
    9794
    9895                ThreadKeyword() : ConcurrentSueKeyword(
    99                         "$thread",
     96                        "thread_desc",
    10097                        "__thrd",
    10198                        "get_thread",
    102                         "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
     99                        "thread keyword requires threads to be in scope, add #include <thread.hfa>",
    103100                        true,
    104                         AggregateDecl::Thread
     101                        KeywordCastExpr::Thread
    105102                )
    106103                {}
     
    121118        //      int data;                                  int data;
    122119        //      a_struct_t more_data;                      a_struct_t more_data;
    123         //                                =>             $coroutine __cor_d;
     120        //                                =>             coroutine_desc __cor_d;
    124121        // };                                        };
    125         //                                           static inline $coroutine * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
     122        //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
    126123        //
    127124        class CoroutineKeyword final : public ConcurrentSueKeyword {
     
    129126
    130127                CoroutineKeyword() : ConcurrentSueKeyword(
    131                         "$coroutine",
     128                        "coroutine_desc",
    132129                        "__cor",
    133130                        "get_coroutine",
    134                         "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
     131                        "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>",
    135132                        true,
    136                         AggregateDecl::Coroutine
     133                        KeywordCastExpr::Coroutine
    137134                )
    138135                {}
     
    147144                }
    148145        };
    149 
    150 
    151146
    152147        //-----------------------------------------------------------------------------
     
    155150        //      int data;                                  int data;
    156151        //      a_struct_t more_data;                      a_struct_t more_data;
    157         //                                =>             $monitor __mon_d;
     152        //                                =>             monitor_desc __mon_d;
    158153        // };                                        };
    159         //                                           static inline $monitor * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
     154        //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
    160155        //
    161156        class MonitorKeyword final : public ConcurrentSueKeyword {
     
    163158
    164159                MonitorKeyword() : ConcurrentSueKeyword(
    165                         "$monitor",
     160                        "monitor_desc",
    166161                        "__mon",
    167162                        "get_monitor",
    168                         "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
     163                        "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>",
    169164                        false,
    170                         AggregateDecl::Monitor
     165                        KeywordCastExpr::Monitor
    171166                )
    172167                {}
     
    183178
    184179        //-----------------------------------------------------------------------------
    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         //-----------------------------------------------------------------------------
    256180        //Handles mutex routines definitions :
    257181        // 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) };
     182        //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    259183        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
    260184        //    /*Some code*/                                       =>           /*Some code*/
     
    295219        //Handles mutex routines definitions :
    296220        // 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) };
     221        //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    298222        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
    299223        //    /*Some code*/                                       =>           /*Some code*/
     
    325249                CoroutineKeyword        ::implement( translationUnit );
    326250                MonitorKeyword  ::implement( translationUnit );
    327                 GeneratorKeyword  ::implement( translationUnit );
    328                 SuspendKeyword    ::implement( translationUnit );
    329251        }
    330252
     
    362284        }
    363285
    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 
    382286        Expression * ConcurrentSueKeyword::postmutate( KeywordCastExpr * cast ) {
    383287                if ( cast_target == cast->target ) {
    384                         // convert (thread &)t to ($thread &)*get_thread(t), etc.
     288                        // convert (thread &)t to (thread_desc &)*get_thread(t), etc.
    385289                        if( !type_decl ) SemanticError( cast, context_error );
    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;
     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                                );
    391301                }
    392302                return cast;
     
    398308
    399309                if( !type_decl ) SemanticError( decl, context_error );
    400                 if( !dtor_decl ) SemanticError( decl, context_error );
    401310
    402311                FunctionDecl * func = forwardDeclare( decl );
     
    453362                        get_type,
    454363                        nullptr,
    455                         { new Attribute("const") },
     364                        noAttributes,
    456365                        Type::Inline
    457366                );
     
    522431
    523432                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 
     433
     434                // get_decl->fixUniqueId();
     435        }
    756436
    757437        //=============================================================================================
     
    821501        void MutexKeyword::postvisit(StructDecl* decl) {
    822502
    823                 if( decl->name == "$monitor" && decl->body ) {
     503                if( decl->name == "monitor_desc" && decl->body ) {
    824504                        assert( !monitor_decl );
    825505                        monitor_decl = decl;
     
    917597                );
    918598
    919                 //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
     599                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    920600                body->push_front( new DeclStmt( monitors) );
    921601        }
     
    978658                );
    979659
    980                 //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
     660                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    981661                body->push_front( new DeclStmt( monitors) );
    982662        }
     
    986666        //=============================================================================================
    987667        void ThreadStarter::previsit( StructDecl * decl ) {
    988                 if( decl->name == "$thread" && decl->body ) {
     668                if( decl->name == "thread_desc" && decl->body ) {
    989669                        assert( !thread_decl );
    990670                        thread_decl = decl;
     
    1021701                                new UntypedExpr(
    1022702                                        new NameExpr( "__thrd_start" ),
    1023                                         { new VariableExpr( param ), new NameExpr("main") }
     703                                        { new VariableExpr( param ) }
    1024704                                )
    1025705                        )
Note: See TracChangeset for help on using the changeset viewer.