Changes in / [ff489bf:9867cdb]


Ignore:
Files:
1 added
10 deleted
41 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    rff489bf r9867cdb  
    126126                        }
    127127
    128                         sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} AR=gcc-ar RANLIB=gcc-ranlib CXXFLAGS='-flto=auto' CFAFLAGS='-flto=auto' ${targets} --quiet"
     128                        sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
    129129
    130130                        // Configure libcfa
  • benchmark/ctxswitch/cfa_cor.cfa

    rff489bf r9867cdb  
    77void main( __attribute__((unused)) C & ) {
    88        while () {
    9                 suspend;
     9                suspend();
    1010        }
    1111}
  • configure

    rff489bf r9867cdb  
    25572557# don't use the default CFLAGS as they unconditonnaly add -O2
    25582558: ${CFLAGS=""}
    2559 : ${CXXFLAGS=""}
    25602559
    25612560am__api_version='1.15'
  • configure.ac

    rff489bf r9867cdb  
    1414# don't use the default CFLAGS as they unconditonnaly add -O2
    1515: ${CFLAGS=""}
    16 : ${CXXFLAGS=""}
    1716
    1817AM_INIT_AUTOMAKE([subdir-objects])
  • libcfa/prelude/builtins.c

    rff489bf r9867cdb  
    4848void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    4949void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
    50 
    51 forall(dtype T)
    52 static inline T & identity(T & i) {
    53         return i;
    54 }
    55 
    56 // generator support
    57 struct $generator {
    58         inline int;
    59 };
    60 
    61 static inline void  ?{}($generator & this) { ((int&)this) = 0; }
    62 static inline void ^?{}($generator &) {}
    63 
    64 trait is_generator(dtype T) {
    65       void main(T & this);
    66       $generator * get_generator(T & this);
    67 };
    68 
    69 forall(dtype T | is_generator(T))
    70 static inline T & resume(T & gen) {
    71         main(gen);
    72         return gen;
    73 }
    7450
    7551// implicit increment, decrement if += defined, and implicit not if != defined
  • libcfa/src/concurrency/coroutine.cfa

    rff489bf r9867cdb  
    208208
    209209                if(cor->state == Primed) {
    210                         __cfactx_suspend();
     210                        suspend();
    211211                }
    212212
  • libcfa/src/concurrency/coroutine.hfa

    rff489bf r9867cdb  
    4646//-----------------------------------------------------------------------------
    4747// Public coroutine API
     48static inline void suspend(void);
     49
     50forall(dtype T | is_coroutine(T))
     51static inline T & resume(T & cor);
     52
    4853forall(dtype T | is_coroutine(T))
    4954void prime(T & cor);
     
    9196
    9297// Suspend implementation inlined for performance
    93 extern "C" {
    94         static inline void __cfactx_suspend(void) {
    95                 // optimization : read TLS once and reuse it
    96                 // Safety note: this is preemption safe since if
    97                 // preemption occurs after this line, the pointer
    98                 // will also migrate which means this value will
    99                 // stay in syn with the TLS
    100                 $coroutine * src = TL_GET( this_thread )->curr_cor;
     98static inline void suspend(void) {
     99        // optimization : read TLS once and reuse it
     100        // Safety note: this is preemption safe since if
     101        // preemption occurs after this line, the pointer
     102        // will also migrate which means this value will
     103        // stay in syn with the TLS
     104        $coroutine * src = TL_GET( this_thread )->curr_cor;
    101105
    102                 assertf( src->last != 0,
    103                         "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n"
    104                         "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
    105                         src->name, src );
    106                 assertf( src->last->state != Halted,
    107                         "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"
    108                         "Possible cause is terminated coroutine's main routine has already returned.",
    109                         src->name, src, src->last->name, src->last );
     106        assertf( src->last != 0,
     107                "Attempt to suspend coroutine \"%.256s\" (%p) that has never been resumed.\n"
     108                "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.",
     109                src->name, src );
     110        assertf( src->last->state != Halted,
     111                "Attempt by coroutine \"%.256s\" (%p) to suspend back to terminated coroutine \"%.256s\" (%p).\n"
     112                "Possible cause is terminated coroutine's main routine has already returned.",
     113                src->name, src, src->last->name, src->last );
    110114
    111                 $ctx_switch( src, src->last );
    112         }
     115        $ctx_switch( src, src->last );
    113116}
    114117
  • src/AST/Convert.cpp

    rff489bf r9867cdb  
    493493        }
    494494
    495         const ast::Stmt * visit(const ast::SuspendStmt * node ) override final {
    496                 if ( inCache( node ) ) return nullptr;
    497                 auto stmt = new SuspendStmt();
    498                 stmt->then   = get<CompoundStmt>().accept1( node->then   );
    499                 switch(node->type) {
    500                         case ast::SuspendStmt::None     : stmt->type = SuspendStmt::None     ; break;
    501                         case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break;
    502                         case ast::SuspendStmt::Generator: stmt->type = SuspendStmt::Generator; break;
    503                 }
    504                 return stmtPostamble( stmt, node );
    505         }
    506 
    507495        const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
    508496                if ( inCache( node ) ) return nullptr;
     
    18711859        }
    18721860
    1873         virtual void visit( const SuspendStmt * old ) override final {
    1874                 if ( inCache( old ) ) return;
    1875                 ast::SuspendStmt::Type type;
    1876                 switch (old->type) {
    1877                         case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
    1878                         case SuspendStmt::Generator: type = ast::SuspendStmt::Generator; break;
    1879                         case SuspendStmt::None     : type = ast::SuspendStmt::None     ; break;
    1880                         default: abort();
    1881                 }
    1882                 this->node = new ast::SuspendStmt(
    1883                         old->location,
    1884                         GET_ACCEPT_1(then  , CompoundStmt),
    1885                         type,
    1886                         GET_LABELS_V(old->labels)
    1887                 );
    1888                 cache.emplace( old, this->node );
    1889         }
    1890 
    18911861        virtual void visit( const WaitForStmt * old ) override final {
    18921862                if ( inCache( old ) ) return;
  • src/AST/Decl.hpp

    rff489bf r9867cdb  
    259259
    260260        bool is_coroutine() { return kind == Coroutine; }
    261         bool is_generator() { return kind == Generator; }
    262         bool is_monitor  () { return kind == Monitor  ; }
    263         bool is_thread   () { return kind == Thread   ; }
     261        bool is_monitor() { return kind == Monitor; }
     262        bool is_thread() { return kind == Thread; }
    264263
    265264        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Fwd.hpp

    rff489bf r9867cdb  
    5353class CatchStmt;
    5454class FinallyStmt;
    55 class SuspendStmt;
    5655class WaitForStmt;
    5756class WithStmt;
  • src/AST/Pass.hpp

    rff489bf r9867cdb  
    111111        const ast::Stmt *             visit( const ast::CatchStmt            * ) override final;
    112112        const ast::Stmt *             visit( const ast::FinallyStmt          * ) override final;
    113         const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
    114113        const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
    115114        const ast::Decl *             visit( const ast::WithStmt             * ) override final;
  • src/AST/Pass.impl.hpp

    rff489bf r9867cdb  
    823823
    824824//--------------------------------------------------------------------------
    825 // FinallyStmt
    826 template< typename pass_t >
    827 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SuspendStmt * node ) {
    828         VISIT_START( node );
    829 
    830         VISIT(
    831                 maybe_accept( node, &SuspendStmt::then   );
    832         )
    833 
    834         VISIT_END( Stmt, node );
    835 }
    836 
    837 //--------------------------------------------------------------------------
    838825// WaitForStmt
    839826template< typename pass_t >
  • src/AST/Print.cpp

    rff489bf r9867cdb  
    674674                safe_print( node->body );
    675675                --indent;
    676 
    677                 return node;
    678         }
    679 
    680         virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final {
    681                 os << "Suspend Statement";
    682                 switch (node->type) {
    683                         case ast::SuspendStmt::None     : os << " with implicit target"; break;
    684                         case ast::SuspendStmt::Generator: os << " for generator"; break;
    685                         case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;
    686                 }
    687                 os << endl;
    688 
    689                 ++indent;
    690                 if(node->then) {
    691                         os << indent << " with post statement :" << endl;
    692                         safe_print( node->then );
    693                 }
    694                 ++indent;
    695676
    696677                return node;
  • src/AST/Stmt.hpp

    rff489bf r9867cdb  
    342342};
    343343
    344 /// Suspend statement
    345 class SuspendStmt final : public Stmt {
    346 public:
    347         ptr<CompoundStmt> then;
    348         enum Type { None, Coroutine, Generator } type = None;
    349 
    350         SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, std::vector<Label> && labels = {} )
    351         : Stmt(loc, std::move(labels)), then(then), type(type) {}
    352 
    353         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    354 private:
    355         SuspendStmt * clone() const override { return new SuspendStmt{ *this }; }
    356         MUTATE_FRIEND
    357 };
    358 
    359344/// Wait for concurrency statement `when (...) waitfor (... , ...) ... timeout(...) ... else ...`
    360345class WaitForStmt final : public Stmt {
  • src/AST/Visitor.hpp

    rff489bf r9867cdb  
    4747    virtual const ast::Stmt *             visit( const ast::CatchStmt            * ) = 0;
    4848    virtual const ast::Stmt *             visit( const ast::FinallyStmt          * ) = 0;
    49     virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
    5049    virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
    5150    virtual const ast::Decl *             visit( const ast::WithStmt             * ) = 0;
  • src/Common/PassVisitor.h

    rff489bf r9867cdb  
    110110        virtual void visit( FinallyStmt * finallyStmt ) override final;
    111111        virtual void visit( const FinallyStmt * finallyStmt ) override final;
    112         virtual void visit( SuspendStmt * suspendStmt ) override final;
    113         virtual void visit( const SuspendStmt * suspendStmt ) override final;
    114112        virtual void visit( WaitForStmt * waitforStmt ) override final;
    115113        virtual void visit( const WaitForStmt * waitforStmt ) override final;
     
    278276        virtual Statement * mutate( CatchStmt * catchStmt ) override final;
    279277        virtual Statement * mutate( FinallyStmt * finallyStmt ) override final;
    280         virtual Statement * mutate( SuspendStmt * suspendStmt ) override final;
    281278        virtual Statement * mutate( WaitForStmt * waitforStmt ) override final;
    282279        virtual Declaration * mutate( WithStmt * withStmt ) override final;
  • src/Common/PassVisitor.impl.h

    rff489bf r9867cdb  
    15221522
    15231523//--------------------------------------------------------------------------
    1524 // SuspendStmt
    1525 template< typename pass_type >
    1526 void PassVisitor< pass_type >::visit( SuspendStmt * node ) {
    1527         VISIT_START( node );
    1528 
    1529         maybeAccept_impl( node->then  , *this );
    1530 
    1531         VISIT_END( node );
    1532 }
    1533 
    1534 template< typename pass_type >
    1535 void PassVisitor< pass_type >::visit( const SuspendStmt * node ) {
    1536         VISIT_START( node );
    1537 
    1538         maybeAccept_impl( node->then  , *this );
    1539 
    1540         VISIT_END( node );
    1541 }
    1542 
    1543 template< typename pass_type >
    1544 Statement * PassVisitor< pass_type >::mutate( SuspendStmt * node ) {
    1545         MUTATE_START( node );
    1546 
    1547         maybeMutate_impl( node->then  , *this );
    1548 
    1549         MUTATE_END( Statement, node );
    1550 }
    1551 
    1552 //--------------------------------------------------------------------------
    15531524// WaitForStmt
    15541525template< typename pass_type >
  • src/Concurrency/Keywords.cc

    rff489bf r9867cdb  
    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;
     
    148147        };
    149148
    150 
    151 
    152149        //-----------------------------------------------------------------------------
    153150        //Handles monitor type declarations :
     
    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 ) {
     
    325251                CoroutineKeyword        ::implement( translationUnit );
    326252                MonitorKeyword  ::implement( translationUnit );
    327                 GeneratorKeyword  ::implement( translationUnit );
    328                 SuspendKeyword    ::implement( translationUnit );
    329253        }
    330254
     
    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        //=============================================================================================
  • src/Parser/ParseNode.h

    rff489bf r9867cdb  
    428428Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );
    429429Statement * build_directive( std::string * directive );
    430 SuspendStmt * build_suspend( StatementNode *, SuspendStmt::Type = SuspendStmt::None);
    431430WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when );
    432431WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when, WaitForStmt * existing );
  • src/Parser/StatementNode.cc

    rff489bf r9867cdb  
    249249} // build_finally
    250250
    251 SuspendStmt * build_suspend( StatementNode * then, SuspendStmt::Type type ) {
    252         auto node = new SuspendStmt();
    253 
    254         node->type = type;
    255 
    256         std::list< Statement * > stmts;
    257         buildMoveList< Statement, StatementNode >( then, stmts );
    258         if(!stmts.empty()) {
    259                 assert( stmts.size() == 1 );
    260                 node->then = dynamic_cast< CompoundStmt * >( stmts.front() );
    261         }
    262 
    263         return node;
    264 }
    265 
    266251WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) {
    267252        auto node = new WaitForStmt();
  • src/Parser/TypeData.cc

    rff489bf r9867cdb  
    769769          case AggregateDecl::Struct:
    770770          case AggregateDecl::Coroutine:
    771           case AggregateDecl::Generator:
    772771          case AggregateDecl::Monitor:
    773772          case AggregateDecl::Thread:
  • src/Parser/lex.ll

    rff489bf r9867cdb  
    6565#define FLOATXX(v) KEYWORD_RETURN(v);
    6666#else
    67 #define FLOATXX(v) IDENTIFIER_RETURN();
     67#define FLOATXX(v) IDENTIFIER_RETURN(); 
    6868#endif // HAVE_KEYWORDS_FLOATXX
    6969
     
    301301_Static_assert  { KEYWORD_RETURN(STATICASSERT); }               // C11
    302302struct                  { KEYWORD_RETURN(STRUCT); }
    303 suspend                 { KEYWORD_RETURN(SUSPEND); }                    // CFA
     303        /* suspend                      { KEYWORD_RETURN(SUSPEND); }                    // CFA */
    304304switch                  { KEYWORD_RETURN(SWITCH); }
    305305thread                  { KEYWORD_RETURN(THREAD); }                             // C11
  • src/Parser/parser.yy

    rff489bf r9867cdb  
    278278%token OTYPE FTYPE DTYPE TTYPE TRAIT                                    // CFA
    279279%token SIZEOF OFFSETOF
    280 // %token RESUME                                                                        // CFA
    281 %token SUSPEND                                                                  // CFA
     280// %token SUSPEND RESUME                                                                        // CFA
    282281%token ATTRIBUTE EXTENSION                                                              // GCC
    283282%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
     
    12661265        | RETURN '{' initializer_list_opt comma_opt '}' ';'
    12671266                { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; }
    1268         | SUSPEND ';'
    1269                 { $$ = new StatementNode( build_suspend( nullptr ) ); }
    1270         | SUSPEND compound_statement
    1271                 { $$ = new StatementNode( build_suspend( $2 ) ); }
    1272         | SUSPEND COROUTINE ';'
    1273                 { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Coroutine ) ); }
    1274         | SUSPEND COROUTINE compound_statement
    1275                 { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Coroutine ) ); }
    1276         | SUSPEND GENERATOR ';'
    1277                 { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Generator ) ); }
    1278         | SUSPEND GENERATOR compound_statement
    1279                 { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Generator ) ); }
     1267        // | SUSPEND ';'
     1268        //      { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
     1269        // | SUSPEND compound_statement ';'
     1270        //      { SemanticError( yylloc, "Suspend expression is currently unimplemented." ); $$ = nullptr; }
    12801271        | THROW assignment_expression_opt ';'                           // handles rethrow
    12811272                { $$ = new StatementNode( build_throw( $2 ) ); }
     
    20922083aggregate_control:                                                                              // CFA
    20932084        GENERATOR
    2094                 { yyy = true; $$ = AggregateDecl::Generator; }
     2085                { SemanticError( yylloc, "generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    20952086        | MONITOR GENERATOR
    20962087                { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
  • src/SynTree/Declaration.h

    rff489bf r9867cdb  
    302302
    303303        bool is_coroutine() { return kind == Coroutine; }
    304         bool is_generator() { return kind == Generator; }
    305         bool is_monitor  () { return kind == Monitor  ; }
    306         bool is_thread   () { return kind == Thread   ; }
     304        bool is_monitor() { return kind == Monitor; }
     305        bool is_thread() { return kind == Thread; }
    307306
    308307        virtual StructDecl * clone() const override { return new StructDecl( *this ); }
  • src/SynTree/Mutator.h

    rff489bf r9867cdb  
    5151        virtual Statement * mutate( CatchStmt * catchStmt ) = 0;
    5252        virtual Statement * mutate( FinallyStmt * catchStmt ) = 0;
    53         virtual Statement * mutate( SuspendStmt * suspendStmt ) = 0;
    5453        virtual Statement * mutate( WaitForStmt * waitforStmt ) = 0;
    5554        virtual Declaration * mutate( WithStmt * withStmt ) = 0;
  • src/SynTree/Statement.cc

    rff489bf r9867cdb  
    420420}
    421421
    422 SuspendStmt::SuspendStmt( const SuspendStmt & other )
    423         : Statement( other )
    424         , then( maybeClone(other.then) )
    425 {}
    426 
    427 SuspendStmt::~SuspendStmt() {
    428         delete then;
    429 }
    430 
    431 void SuspendStmt::print( std::ostream & os, Indenter indent ) const {
    432         os << "Suspend Statement";
    433         switch (type) {
    434                 case None     : os << " with implicit target"; break;
    435                 case Generator: os << " for generator"       ; break;
    436                 case Coroutine: os << " for coroutine"       ; break;
    437         }
    438         os << endl;
    439         indent += 1;
    440 
    441         if(then) {
    442                 os << indent << " with post statement :" << endl;
    443                 then->print( os, indent + 1);
    444         }
    445 }
    446 
    447422WaitForStmt::WaitForStmt() : Statement() {
    448423        timeout.time      = nullptr;
  • src/SynTree/Statement.h

    rff489bf r9867cdb  
    422422};
    423423
    424 class SuspendStmt : public Statement {
    425   public:
    426         CompoundStmt * then = nullptr;
    427         enum Type { None, Coroutine, Generator } type = None;
    428 
    429         SuspendStmt() = default;
    430         SuspendStmt( const SuspendStmt & );
    431         virtual ~SuspendStmt();
    432 
    433         virtual SuspendStmt * clone() const override { return new SuspendStmt( *this ); }
    434         virtual void accept( Visitor & v ) override { v.visit( this ); }
    435         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    436         virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    437         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    438 };
    439 
    440424class WaitForStmt : public Statement {
    441425  public:
  • src/SynTree/SynTree.h

    rff489bf r9867cdb  
    5454class CatchStmt;
    5555class FinallyStmt;
    56 class SuspendStmt;
    5756class WaitForStmt;
    5857class WithStmt;
  • src/SynTree/Visitor.h

    rff489bf r9867cdb  
    7878        virtual void visit( FinallyStmt * node ) { visit( const_cast<const FinallyStmt *>(node) ); }
    7979        virtual void visit( const FinallyStmt * finallyStmt ) = 0;
    80         virtual void visit( SuspendStmt * node ) { visit( const_cast<const SuspendStmt *>(node) ); }
    81         virtual void visit( const SuspendStmt * suspendStmt ) = 0;
    8280        virtual void visit( WaitForStmt * node ) { visit( const_cast<const WaitForStmt *>(node) ); }
    8381        virtual void visit( const WaitForStmt * waitforStmt ) = 0;
  • tests/concurrent/coroutineYield.cfa

    rff489bf r9867cdb  
    3333                        sout | "Coroutine 2";
    3434                #endif
    35                 suspend;
     35                suspend();
    3636        }
    3737}
  • tests/coroutine/.expect/fmtLines.txt

    rff489bf r9867cdb  
    4848{                                                         // f  or n  ewli 
    4949ne c  hara  cter  s                                     su 
    50 spen  d;                                        i  f (   fmt. 
    51 ch !  = '\  n' )   bre  ak;      
    52         //   igno  re n  ewli  ne                
    53                 }   // f  or                            so  ut | 
    54  fmt  .ch;                                                      /  / pr 
    55 int   char  acte  r                       } // 
    56  for                    s  out   | "    ";       
    57                                                         /  / pr  int   bloc 
    58 k se  para  tor         } /  / fo 
    59 r               s  out   | nl  ;                                                         
    60                 //   pri  nt g  roup   sep 
    61 arat  or        }   //   for}   //  
    62 main  void   prt  ( Fo  rmat 
    63  & f  mt,   char   ch   ) {   
    64    f  mt.c  h =   ch;      r 
    65 esum  e( f  mt )  ;} /  / pr 
    66 tint   mai  n()   {     Fo  rmat 
    67  fmt  ; ch  ar c  h;    f  or ( 
    68  ;;   ) {               sin   | c  h;            
    69                                                                   // r  ead   one  
    70 char  acte  r       if (   eof 
    71 ( si  n )   ) br  eak;                                   
    72                         /  / eo  f ?            prt  ( fm 
    73 t, c  h );      } /  / fo  r} / 
    74 / ma  in//   Loc  al V  aria 
    75 bles  : //  // t  ab-w  idth 
    76 : 4   ////   com  pile  -com 
    77 mand  : "c  fa f  mtLi  nes. 
    78 cfa"   ///  / En  d: /  /
     50spen  d();                                      if   ( fm 
     51t.ch   !=   '\n'   ) b  reak 
     52;               /  / ig  nore   new  line 
     53                                  } //   for                              sout 
     54 | f  mt.c  h;                                                  //  
     55prin  t ch  arac  ter                   }  
     56// f  or                        sou  t |   "  " 
     57;                                                               //   prin  t bl 
     58ock   sepa  rato  r             }   //  
     59for             sou  t |   nl;                                   
     60                                  // p  rint   gro  up s 
     61epar  ator      } /  / fo  r} / 
     62/ ma  invo  id p  rt(   Form 
     63at &   fmt  , ch  ar c  h )   
     64{      fmt  .ch   = ch  ;    
     65 res  ume(   fmt   );}   //  
     66prti  nt m  ain(  ) {     Form 
     67at f  mt;         char   ch;    for 
     68 ( ;  ; )   {           s  in |   ch; 
     69                                                                                //   rea  d on 
     70e ch  arac  ter     if   ( e 
     71of(   sin   ) )   brea  k;               
     72                                        //   eof   ?            p  rt(  
     73fmt,   ch   );  }   //   for} 
     74 //   main  // L  ocal   Var 
     75iabl  es:   ////   tab  -wid 
     76th:   4 //  // c  ompi  le-c 
     77omma  nd:   "cfa   fmt  Line 
     78s.cf  a" /  ///   End:   //
  • tests/coroutine/.in/fmtLines.txt

    rff489bf r9867cdb  
    3535                        for ( fmt.b = 0; fmt.b < 4; fmt.b += 1 ) {      // blocks of 4 characters
    3636                                for ( ;; ) {                                                    // for newline characters
    37                                         suspend;
     37                                        suspend();
    3838                                        if ( fmt.ch != '\n' ) break;            // ignore newline
    3939                                } // for
  • tests/coroutine/cntparens.cfa

    rff489bf r9867cdb  
    1 //
     1// 
    22// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 //
     6// 
    77// cntparens.cfa -- match left/right parenthesis
    8 //
     8// 
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Apr 20 11:04:45 2019
     
    1212// Last Modified On : Sat Apr 20 11:06:21 2019
    1313// Update Count     : 1
    14 //
     14// 
    1515
    1616#include <fstream.hfa>
     
    2626void main( CntParens & cpns ) with( cpns ) {
    2727        for ( ; ch == '('; cnt += 1 ) {                                         // left parenthesis
    28                 suspend;
     28                suspend();
    2929        }
    3030        for ( ; ch == ')' && cnt > 1; cnt -= 1 ) {                      // right parenthesis
    31                 suspend;
     31                suspend();
    3232        }
    3333        status = ch == ')' ? Match : Error;
    3434} // main
    35 
     35       
    3636void ?{}( CntParens & cpns ) with( cpns ) { status = Cont; cnt = 0; }
    3737
  • tests/coroutine/devicedriver.cfa

    rff489bf r9867cdb  
    1 //
     1// 
    22// Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 //
    7 // devicedriver.cfa --
    8 //
     6// 
     7// devicedriver.cfa -- 
     8// 
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Mar 16 15:30:34 2019
     
    1212// Last Modified On : Sat Apr 20 09:07:19 2019
    1313// Update Count     : 90
    14 //
     14// 
    1515
    1616#include <fstream.hfa>
     
    2929
    3030void checkCRC( Driver & d, unsigned int sum ) with( d ) {
    31         suspend;
     31        suspend();
    3232        unsigned short int crc = byte << 8;                                     // sign extension over written
    33         suspend;
     33        suspend();
    3434        // prevent sign extension for signed char
    3535        status = (crc | (unsigned char)byte) == sum ? MSG : ECRC;
     
    4141                status = CONT;
    4242                unsigned int lnth = 0, sum = 0;
    43                 while ( byte != STX ) suspend;
     43                while ( byte != STX ) suspend();
    4444          emsg: for () {
    45                         suspend;
     45                        suspend();
    4646                        choose ( byte ) {                                                       // process byte
    4747                          case STX:
    48                                 status = ESTX; suspend; continue msg;
     48                                status = ESTX; suspend(); continue msg;
    4949                          case ETX:
    5050                                break emsg;
    5151                          case ESC:
    52                                 suspend;
     52                                suspend();
    5353                        } // choose
    5454                        if ( lnth >= MaxMsg ) {                                         // buffer full ?
    55                                 status = ELNTH; suspend; continue msg;
     55                                status = ELNTH; suspend(); continue msg;
    5656                        } // if
    5757                        msg[lnth++] = byte;
     
    6060                msg[lnth] = '\0';                                                               // terminate string
    6161                checkCRC( d, sum );                                                             // refactor CRC check
    62                 suspend;
     62                suspend();
    6363        } // for
    6464} // main
  • tests/coroutine/fibonacci.cfa

    rff489bf r9867cdb  
    2222        int fn1, fn2;                                                                           // retained between resumes
    2323        fn = 0;  fn1 = fn;                                                                      // 1st case
    24         suspend;                                                                                        // restart last resume
     24        suspend();                                                                                      // restart last resume
    2525        fn = 1;  fn2 = fn1;  fn1 = fn;                                          // 2nd case
    26         suspend;                                                                                        // restart last resume
     26        suspend();                                                                                      // restart last resume
    2727        for () {
    2828                fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn;                  // general case
    29                 suspend;                                                                                // restart last resume
     29                suspend();                                                                              // restart last resume
    3030        } // for
    3131}
  • tests/coroutine/fibonacci_1.cfa

    rff489bf r9867cdb  
    1212// Last Modified On : Thu Mar 21 08:10:45 2019
    1313// Update Count     : 25
    14 //
     14// 
    1515
    1616#include <fstream.hfa>
     
    2323        [fn1, fn] = [0, 1];                                                                     // precompute first two states
    2424        for () {
    25                 suspend;                                                                                // restart last resume
     25                suspend();                                                                              // restart last resume
    2626                [fn1, fn] = [fn, fn1 + fn];                                             // general case
    2727        } // for
  • tests/coroutine/fmtLines.cfa

    rff489bf r9867cdb  
    2727                        for ( b = 0; b < 4; b += 1 ) {                          // blocks of 4 characters
    2828                                for () {                                                                // for newline characters
    29                                         suspend;
     29                                        suspend();
    3030                                  if ( ch != '\n' ) break;                              // ignore newline
    3131                                } // for
  • tests/coroutine/raii.cfa

    rff489bf r9867cdb  
    3939        Raii raii = { "Coroutine" };
    4040        sout | "Before Suspend";
    41         suspend;
     41        suspend();
    4242        sout | "After Suspend";
    4343}
  • tests/coroutine/runningTotal.cfa

    rff489bf r9867cdb  
    2525void update( RunTotal & rntl, int input ) with( rntl ) { // helper
    2626        total += input;                                                                         // remember between activations
    27         suspend;                                                                                        // inactivate on stack
     27        suspend();                                                                                      // inactivate on stack
    2828}
    2929
  • tests/coroutine/suspend_then.cfa

    rff489bf r9867cdb  
    1515
    1616#include <fstream.hfa>
     17#include <coroutine.hfa>
    1718
    18 generator Fibonacci {
    19         int fn;                                                                         // used for communication
    20         int fn1, fn2;                                                           // retained between resumes
    21 };
     19void then() {
     20        sout | "Then!";
     21}
     22
     23coroutine Fibonacci { int fn; };                                                // used for communication
    2224
    2325void main( Fibonacci & fib ) with( fib ) {                              // called on first resume
     26        int fn1, fn2;                                                           // retained between resumes
    2427        fn = 0;  fn1 = fn;                                                      // 1st case
    25         suspend { sout | "Then!"; }                                             // restart last resume
     28        suspend_then(then);                                                     // restart last resume
    2629        fn = 1;  fn2 = fn1;  fn1 = fn;                                  // 2nd case
    27         suspend { sout | "Then!"; }                                             // restart last resume
     30        suspend_then(then);                                                     // restart last resume
    2831        for () {
    2932                fn = fn1 + fn2;  fn2 = fn1;  fn1 = fn;                  // general case
    30                 suspend { sout | "Then!"; }                                     // restart last resume
     33                suspend_then(then);                                             // restart last resume
    3134        } // for
    3235}
  • tests/errors/.expect/completeType.txt

    rff489bf r9867cdb  
    2727    void
    2828  )
    29   Environment:( _85_4_DT ) -> instance of struct A with body 0 (no widening)
     29  Environment:( _83_4_DT ) -> instance of struct A with body 0 (no widening)
    3030
    3131
     
    5050    void
    5151  )
    52   Environment:( _85_4_DT ) -> instance of struct B with body 1 (no widening)
     52  Environment:( _83_4_DT ) -> instance of struct B with body 1 (no widening)
    5353
    5454
     
    127127          void
    128128        )
    129         Environment:( _104_0_T ) -> instance of type T (not function type) (no widening)
     129        Environment:( _102_0_T ) -> instance of type T (not function type) (no widening)
    130130
    131131      Could not satisfy assertion:
    132132?=?: pointer to function
    133133        ... with parameters
    134           reference to instance of type _104_0_T (not function type)
    135           instance of type _104_0_T (not function type)
     134          reference to instance of type _102_0_T (not function type)
     135          instance of type _102_0_T (not function type)
    136136        ... returning
    137           _retval__operator_assign: instance of type _104_0_T (not function type)
     137          _retval__operator_assign: instance of type _102_0_T (not function type)
    138138          ... with attributes:
    139139            Attribute with name: unused
Note: See TracChangeset for help on using the changeset viewer.