Ignore:
Timestamp:
Jan 7, 2021, 2:55:57 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
58fe85a
Parents:
bdfc032 (diff), 44e37ef (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into dkobets-vector

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Keywords.cc

    rbdfc032 reef8dfb  
    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 "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
     18#include <cassert>                        // for assert
     19#include <string>                         // for string, operator==
     20
     21#include <iostream>
     22
     23#include "Common/Examine.h"               // for isMainFor
     24#include "Common/PassVisitor.h"           // for PassVisitor
     25#include "Common/SemanticError.h"         // for SemanticError
     26#include "Common/utility.h"               // for deleteAll, map_range
     27#include "CodeGen/OperatorTable.h"        // for isConstructor
     28#include "ControlStruct/LabelGenerator.h" // for LebelGenerator
     29#include "InitTweak/InitTweak.h"          // for getPointerBase
     30#include "SynTree/LinkageSpec.h"          // for Cforall
     31#include "SynTree/Constant.h"             // for Constant
     32#include "SynTree/Declaration.h"          // for StructDecl, FunctionDecl, ObjectDecl
     33#include "SynTree/Expression.h"           // for VariableExpr, ConstantExpr, Untype...
     34#include "SynTree/Initializer.h"          // for SingleInit, ListInit, Initializer ...
     35#include "SynTree/Label.h"                // for Label
     36#include "SynTree/Statement.h"            // for CompoundStmt, DeclStmt, ExprStmt
     37#include "SynTree/Type.h"                 // for StructInstType, Type, PointerType
     38#include "SynTree/Visitor.h"              // for Visitor, acceptAll
     39#include "Virtual/Tables.h"
    3540
    3641class Attribute;
    3742
    3843namespace Concurrency {
     44        inline static std::string getVTableName( std::string const & exception_name ) {
     45                return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name);
     46        }
     47
     48        // Only detects threads constructed with the keyword thread.
     49        inline static bool isThread( DeclarationWithType * decl ) {
     50                Type * baseType = decl->get_type()->stripDeclarator();
     51                StructInstType * instType = dynamic_cast<StructInstType *>( baseType );
     52                if ( nullptr == instType ) { return false; }
     53                return instType->baseStruct->is_thread();
     54        }
     55
    3956        //=============================================================================================
    4057        // Pass declarations
     
    5370          public:
    5471
    55                 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, AggregateDecl::Aggregate cast_target ) :
    56                   type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ), cast_target( cast_target ) {}
     72                ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name,
     73                        std::string&& getter_name, std::string&& context_error, std::string&& exception_name,
     74                        bool needs_main, AggregateDecl::Aggregate cast_target ) :
     75                  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
     76                  context_error( context_error ), exception_name( exception_name ),
     77                  vtable_name( getVTableName( exception_name ) ),
     78                  needs_main( needs_main ), cast_target( cast_target ) {}
    5779
    5880                virtual ~ConcurrentSueKeyword() {}
     
    6284
    6385                void handle( StructDecl * );
     86                void addVtableForward( StructDecl * );
    6487                FunctionDecl * forwardDeclare( StructDecl * );
    6588                ObjectDecl * addField( StructDecl * );
     
    7598                const std::string getter_name;
    7699                const std::string context_error;
     100                const std::string exception_name;
     101                const std::string vtable_name;
    77102                bool needs_main;
    78103                AggregateDecl::Aggregate cast_target;
     
    80105                StructDecl   * type_decl = nullptr;
    81106                FunctionDecl * dtor_decl = nullptr;
     107                StructDecl * except_decl = nullptr;
     108                StructDecl * vtable_decl = nullptr;
    82109        };
    83110
     
    88115        //      int data;                                  int data;
    89116        //      a_struct_t more_data;                      a_struct_t more_data;
    90         //                                =>             thread_desc __thrd_d;
     117        //                                =>             $thread __thrd_d;
    91118        // };                                        };
    92         //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
     119        //                                           static inline $thread * get_thread( MyThread * this ) { return &this->__thrd_d; }
    93120        //
    94121        class ThreadKeyword final : public ConcurrentSueKeyword {
     
    96123
    97124                ThreadKeyword() : ConcurrentSueKeyword(
    98                         "thread_desc",
     125                        "$thread",
    99126                        "__thrd",
    100127                        "get_thread",
    101128                        "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
     129                        "ThreadCancelled",
    102130                        true,
    103131                        AggregateDecl::Thread
     
    120148        //      int data;                                  int data;
    121149        //      a_struct_t more_data;                      a_struct_t more_data;
    122         //                                =>             coroutine_desc __cor_d;
     150        //                                =>             $coroutine __cor_d;
    123151        // };                                        };
    124         //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
     152        //                                           static inline $coroutine * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
    125153        //
    126154        class CoroutineKeyword final : public ConcurrentSueKeyword {
     
    128156
    129157                CoroutineKeyword() : ConcurrentSueKeyword(
    130                         "coroutine_desc",
     158                        "$coroutine",
    131159                        "__cor",
    132160                        "get_coroutine",
    133161                        "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
     162                        "CoroutineCancelled",
    134163                        true,
    135164                        AggregateDecl::Coroutine
     
    146175                }
    147176        };
     177
     178
    148179
    149180        //-----------------------------------------------------------------------------
     
    152183        //      int data;                                  int data;
    153184        //      a_struct_t more_data;                      a_struct_t more_data;
    154         //                                =>             monitor_desc __mon_d;
     185        //                                =>             $monitor __mon_d;
    155186        // };                                        };
    156         //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
     187        //                                           static inline $monitor * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
    157188        //
    158189        class MonitorKeyword final : public ConcurrentSueKeyword {
     
    160191
    161192                MonitorKeyword() : ConcurrentSueKeyword(
    162                         "monitor_desc",
     193                        "$monitor",
    163194                        "__mon",
    164195                        "get_monitor",
    165196                        "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
     197                        "",
    166198                        false,
    167199                        AggregateDecl::Monitor
     
    180212
    181213        //-----------------------------------------------------------------------------
     214        //Handles generator type declarations :
     215        // generator MyGenerator {                   struct MyGenerator {
     216        //      int data;                                  int data;
     217        //      a_struct_t more_data;                      a_struct_t more_data;
     218        //                                =>             int __gen_next;
     219        // };                                        };
     220        //
     221        class GeneratorKeyword final : public ConcurrentSueKeyword {
     222          public:
     223
     224                GeneratorKeyword() : ConcurrentSueKeyword(
     225                        "$generator",
     226                        "__generator_state",
     227                        "get_generator",
     228                        "Unable to find builtin type $generator\n",
     229                        "",
     230                        true,
     231                        AggregateDecl::Generator
     232                )
     233                {}
     234
     235                virtual ~GeneratorKeyword() {}
     236
     237                virtual bool is_target( StructDecl * decl ) override final { return decl->is_generator(); }
     238
     239                static void implement( std::list< Declaration * > & translationUnit ) {
     240                        PassVisitor< GeneratorKeyword > impl;
     241                        mutateAll( translationUnit, impl );
     242                }
     243        };
     244
     245
     246        //-----------------------------------------------------------------------------
     247        class SuspendKeyword final : public WithStmtsToAdd, public WithGuards {
     248        public:
     249                SuspendKeyword() = default;
     250                virtual ~SuspendKeyword() = default;
     251
     252                void  premutate( FunctionDecl * );
     253                DeclarationWithType * postmutate( FunctionDecl * );
     254
     255                Statement * postmutate( SuspendStmt * );
     256
     257                static void implement( std::list< Declaration * > & translationUnit ) {
     258                        PassVisitor< SuspendKeyword > impl;
     259                        mutateAll( translationUnit, impl );
     260                }
     261
     262        private:
     263                bool is_real_suspend( FunctionDecl * );
     264
     265                Statement * make_generator_suspend( SuspendStmt * );
     266                Statement * make_coroutine_suspend( SuspendStmt * );
     267
     268                struct LabelPair {
     269                        Label obj;
     270                        int   idx;
     271                };
     272
     273                LabelPair make_label() {
     274                        labels.push_back( gen.newLabel("generator") );
     275                        return { labels.back(), int(labels.size()) };
     276                }
     277
     278                DeclarationWithType * in_generator = nullptr;
     279                FunctionDecl * decl_suspend = nullptr;
     280                std::vector<Label> labels;
     281                ControlStruct::LabelGenerator & gen = *ControlStruct::LabelGenerator::getGenerator();
     282        };
     283
     284        //-----------------------------------------------------------------------------
    182285        //Handles mutex routines definitions :
    183286        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
    184         //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     287        //                                                                       $monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    185288        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
    186289        //    /*Some code*/                                       =>           /*Some code*/
     
    195298                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
    196299                void validate( DeclarationWithType * );
    197                 void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    198                 void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     300                void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     301                void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     302                void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
    199303
    200304                static void implement( std::list< Declaration * > & translationUnit ) {
     
    207311                StructDecl* guard_decl = nullptr;
    208312                StructDecl* dtor_guard_decl = nullptr;
     313                StructDecl* thread_guard_decl = nullptr;
    209314
    210315                static std::unique_ptr< Type > generic_func;
     
    221326        //Handles mutex routines definitions :
    222327        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
    223         //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     328        //                                                                       $monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    224329        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
    225330        //    /*Some code*/                                       =>           /*Some code*/
     
    251356                CoroutineKeyword        ::implement( translationUnit );
    252357                MonitorKeyword  ::implement( translationUnit );
     358                GeneratorKeyword  ::implement( translationUnit );
     359                SuspendKeyword    ::implement( translationUnit );
    253360        }
    254361
     
    283390                        handle( decl );
    284391                }
     392                else if ( !except_decl && exception_name == decl->name && decl->body ) {
     393                        except_decl = decl;
     394                }
     395                else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
     396                        vtable_decl = decl;
     397                }
     398                // Might be able to get ride of is target.
     399                assert( is_target(decl) == (cast_target == decl->kind) );
    285400                return decl;
    286401        }
    287402
    288403        DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) {
    289                 if( !type_decl ) return decl;
    290                 if( !CodeGen::isDestructor( decl->name ) ) return decl;
    291 
    292                 auto params = decl->type->parameters;
    293                 if( params.size() != 1 ) return decl;
    294 
    295                 auto type = dynamic_cast<ReferenceType*>( params.front()->get_type() );
    296                 if( !type ) return decl;
    297 
    298                 auto stype = dynamic_cast<StructInstType*>( type->base );
    299                 if( !stype ) return decl;
    300                 if( stype->baseStruct != type_decl ) return decl;
    301 
    302                 if( !dtor_decl ) dtor_decl = decl;
     404                if ( type_decl && isDestructorFor( decl, type_decl ) )
     405                        dtor_decl = decl;
     406                else if ( vtable_name.empty() )
     407                        ;
     408                else if( !decl->has_body() )
     409                        ;
     410                else if ( auto param = isMainFor( decl, cast_target ) ) {
     411                        // This should never trigger.
     412                        assert( vtable_decl );
     413                        // Should be safe because of isMainFor.
     414                        StructInstType * struct_type = static_cast<StructInstType *>(
     415                                static_cast<ReferenceType *>( param->get_type() )->base );
     416                        assert( struct_type );
     417
     418                        std::list< Expression * > poly_args = { new TypeExpr( struct_type->clone() ) };
     419                        ObjectDecl * vtable_object = Virtual::makeVtableInstance(
     420                                vtable_decl->makeInst( poly_args ), struct_type, nullptr );
     421                        declsToAddAfter.push_back( vtable_object );
     422                        declsToAddAfter.push_back( Virtual::makeGetExceptionFunction(
     423                                vtable_object, except_decl->makeInst( std::move( poly_args ) )
     424                        ) );
     425                }
     426
    303427                return decl;
    304428        }
     
    306430        Expression * ConcurrentSueKeyword::postmutate( KeywordCastExpr * cast ) {
    307431                if ( cast_target == cast->target ) {
    308                         // convert (thread &)t to (thread_desc &)*get_thread(t), etc.
     432                        // convert (thread &)t to ($thread &)*get_thread(t), etc.
    309433                        if( !type_decl ) SemanticError( cast, context_error );
    310434                        if( !dtor_decl ) SemanticError( cast, context_error );
     
    324448                if( !dtor_decl ) SemanticError( decl, context_error );
    325449
     450                addVtableForward( decl );
    326451                FunctionDecl * func = forwardDeclare( decl );
    327452                ObjectDecl * field = addField( decl );
    328453                addRoutines( field, func );
     454        }
     455
     456        void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
     457                if ( vtable_decl ) {
     458                        std::list< Expression * > poly_args = {
     459                                new TypeExpr( new StructInstType( noQualifiers, decl ) ),
     460                        };
     461                        declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
     462                                vtable_decl->makeInst( poly_args ),
     463                                except_decl->makeInst( poly_args )
     464                        ) );
     465                        declsToAddBefore.push_back( Virtual::makeVtableForward(
     466                                vtable_decl->makeInst( move( poly_args ) ) ) );
     467                // Its only an error if we want a vtable and don't have one.
     468                } else if ( ! vtable_name.empty() ) {
     469                        SemanticError( decl, context_error );
     470                }
    329471        }
    330472
     
    377519                        get_type,
    378520                        nullptr,
    379                         noAttributes,
     521                        { new Attribute("const") },
    380522                        Type::Inline
    381523                );
     
    434576                                                new CastExpr(
    435577                                                        new VariableExpr( func->get_functionType()->get_parameters().front() ),
    436                                                         func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone()
     578                                                        func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone(),
     579                                                        false
    437580                                                )
    438581                                        )
     
    446589
    447590                declsToAddAfter.push_back( get_decl );
    448 
    449                 // get_decl->fixUniqueId();
    450         }
     591        }
     592
     593        //=============================================================================================
     594        // Suspend keyword implementation
     595        //=============================================================================================
     596        bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) {
     597                if(isMangled(func->linkage)) return false; // the real suspend isn't mangled
     598                if(func->name != "__cfactx_suspend") return false; // the real suspend has a specific name
     599                if(func->type->parameters.size() != 0) return false; // Too many parameters
     600                if(func->type->returnVals.size() != 0) return false; // Too many return values
     601
     602                return true;
     603        }
     604
     605        void SuspendKeyword::premutate( FunctionDecl * func ) {
     606                GuardValue(in_generator);
     607                in_generator = nullptr;
     608
     609                // Is this the real suspend?
     610                if(is_real_suspend(func)) {
     611                        decl_suspend = decl_suspend ? decl_suspend : func;
     612                        return;
     613                }
     614
     615                // Is this the main of a generator?
     616                auto param = isMainFor( func, AggregateDecl::Aggregate::Generator );
     617                if(!param) return;
     618
     619                if(func->type->returnVals.size() != 0) SemanticError(func->location, "Generator main must return void");
     620
     621                in_generator = param;
     622                GuardValue(labels);
     623                labels.clear();
     624        }
     625
     626        DeclarationWithType * SuspendKeyword::postmutate( FunctionDecl * func ) {
     627                if( !func->statements ) return func; // Not the actual definition, don't do anything
     628                if( !in_generator     ) return func; // Not in a generator, don't do anything
     629                if( labels.empty()    ) return func; // Generator has no states, nothing to do, could throw a warning
     630
     631                // This is a generator main, we need to add the following code to the top
     632                // static void * __generator_labels[] = {&&s0, &&s1, ...};
     633                // goto * __generator_labels[gen.__generator_state];
     634                const auto & loc = func->location;
     635
     636                const auto first_label = gen.newLabel("generator");
     637
     638                // for each label add to declaration
     639                std::list<Initializer*> inits = { new SingleInit( new LabelAddressExpr( first_label ) ) };
     640                for(const auto & label : labels) {
     641                        inits.push_back(
     642                                new SingleInit(
     643                                        new LabelAddressExpr( label )
     644                                )
     645                        );
     646                }
     647                auto init = new ListInit(std::move(inits), noDesignators, true);
     648                labels.clear();
     649
     650                // create decl
     651                auto decl = new ObjectDecl(
     652                        "__generator_labels",
     653                        Type::StorageClasses( Type::Static ),
     654                        LinkageSpec::AutoGen,
     655                        nullptr,
     656                        new ArrayType(
     657                                Type::Qualifiers(),
     658                                new PointerType(
     659                                        Type::Qualifiers(),
     660                                        new VoidType( Type::Qualifiers() )
     661                                ),
     662                                nullptr,
     663                                false, false
     664                        ),
     665                        init
     666                );
     667
     668                // create the goto
     669                assert(in_generator);
     670
     671                auto go_decl = new ObjectDecl(
     672                        "__generator_label",
     673                        noStorageClasses,
     674                        LinkageSpec::AutoGen,
     675                        nullptr,
     676                        new PointerType(
     677                                Type::Qualifiers(),
     678                                new VoidType( Type::Qualifiers() )
     679                        ),
     680                        new SingleInit(
     681                                new UntypedExpr(
     682                                        new NameExpr("?[?]"),
     683                                        {
     684                                                new NameExpr("__generator_labels"),
     685                                                new UntypedMemberExpr(
     686                                                        new NameExpr("__generator_state"),
     687                                                        new VariableExpr( in_generator )
     688                                                )
     689                                        }
     690                                )
     691                        )
     692                );
     693                go_decl->location = loc;
     694
     695                auto go = new BranchStmt(
     696                        new VariableExpr( go_decl ),
     697                        BranchStmt::Goto
     698                );
     699                go->location = loc;
     700                go->computedTarget->location = loc;
     701
     702                auto noop = new NullStmt({ first_label });
     703                noop->location = loc;
     704
     705                // wrap everything in a nice compound
     706                auto body = new CompoundStmt({
     707                        new DeclStmt( decl ),
     708                        new DeclStmt( go_decl ),
     709                        go,
     710                        noop,
     711                        func->statements
     712                });
     713                body->location   = loc;
     714                func->statements = body;
     715
     716                return func;
     717        }
     718
     719        Statement * SuspendKeyword::postmutate( SuspendStmt * stmt ) {
     720                SuspendStmt::Type type = stmt->type;
     721                if(type == SuspendStmt::None) {
     722                        // This suspend has a implicit target, find it
     723                        type = in_generator ? SuspendStmt::Generator : SuspendStmt::Coroutine;
     724                }
     725
     726                // Check that the target makes sense
     727                if(!in_generator && type == SuspendStmt::Generator) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type.");
     728
     729                // Act appropriately
     730                switch(type) {
     731                        case SuspendStmt::Generator: return make_generator_suspend(stmt);
     732                        case SuspendStmt::Coroutine: return make_coroutine_suspend(stmt);
     733                        default: abort();
     734                }
     735        }
     736
     737        Statement * SuspendKeyword::make_generator_suspend( SuspendStmt * stmt ) {
     738                assert(in_generator);
     739                // Target code is :
     740                //   gen.__generator_state = X;
     741                //   { THEN }
     742                //   return;
     743                //   __gen_X:;
     744
     745                // Save the location and delete the old statement, we only need the location from this point on
     746                auto loc = stmt->location;
     747
     748                // Build the label and get its index
     749                auto label = make_label();
     750
     751                // Create the context saving statement
     752                auto save = new ExprStmt( new UntypedExpr(
     753                        new NameExpr( "?=?" ),
     754                        {
     755                                new UntypedMemberExpr(
     756                                        new NameExpr("__generator_state"),
     757                                        new VariableExpr( in_generator )
     758                                ),
     759                                new ConstantExpr(
     760                                        Constant::from_int( label.idx )
     761                                )
     762                        }
     763                ));
     764                assert(save->expr);
     765                save->location = loc;
     766                stmtsToAddBefore.push_back( save );
     767
     768                // if we have a then add it here
     769                auto then = stmt->then;
     770                stmt->then = nullptr;
     771                delete stmt;
     772                if(then) stmtsToAddBefore.push_back( then );
     773
     774                // Create the return statement
     775                auto ret = new ReturnStmt( nullptr );
     776                ret->location = loc;
     777                stmtsToAddBefore.push_back( ret );
     778
     779                // Create the null statement with the created label
     780                auto noop = new NullStmt({ label.obj });
     781                noop->location = loc;
     782
     783                // Return the null statement to take the place of the previous statement
     784                return noop;
     785        }
     786
     787        Statement * SuspendKeyword::make_coroutine_suspend( SuspendStmt * stmt ) {
     788                if(stmt->then) SemanticError( stmt->location, "Compound statement following coroutines is not implemented.");
     789
     790                // Save the location and delete the old statement, we only need the location from this point on
     791                auto loc = stmt->location;
     792                delete stmt;
     793
     794                // Create the call expression
     795                if(!decl_suspend) SemanticError( loc, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n");
     796                auto expr = new UntypedExpr( VariableExpr::functionPointer( decl_suspend ) );
     797                expr->location = loc;
     798
     799                // Change this statement into a regular expr
     800                assert(expr);
     801                auto nstmt = new ExprStmt( expr );
     802                nstmt->location = loc;
     803                return nstmt;
     804        }
     805
    451806
    452807        //=============================================================================================
     
    458813                bool first = false;
    459814                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
    460                 bool isDtor = CodeGen::isDestructor( decl->name );
     815                bool const isDtor = CodeGen::isDestructor( decl->name );
    461816
    462817                // Is this function relevant to monitors
     
    506861
    507862                // Instrument the body
    508                 if( isDtor ) {
    509                         addDtorStatments( decl, body, mutexArgs );
     863                if ( isDtor && isThread( mutexArgs.front() ) ) {
     864                        if( !thread_guard_decl ) {
     865                                SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" );
     866                        }
     867                        addThreadDtorStatements( decl, body, mutexArgs );
     868                }
     869                else if ( isDtor ) {
     870                        addDtorStatements( decl, body, mutexArgs );
    510871                }
    511872                else {
    512                         addStatments( decl, body, mutexArgs );
     873                        addStatements( decl, body, mutexArgs );
    513874                }
    514875        }
     
    516877        void MutexKeyword::postvisit(StructDecl* decl) {
    517878
    518                 if( decl->name == "monitor_desc" && decl->body ) {
     879                if( decl->name == "$monitor" && decl->body ) {
    519880                        assert( !monitor_decl );
    520881                        monitor_decl = decl;
     
    527888                        assert( !dtor_guard_decl );
    528889                        dtor_guard_decl = decl;
     890                }
     891                else if( decl->name == "thread_dtor_guard_t" && decl->body ) {
     892                        assert( !thread_guard_decl );
     893                        thread_guard_decl = decl;
    529894                }
    530895        }
     
    565930        }
    566931
    567         void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     932        void MutexKeyword::addDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
    568933                Type * arg_type = args.front()->get_type()->clone();
    569934                arg_type->set_mutex( false );
     
    583948                        new SingleInit( new UntypedExpr(
    584949                                new NameExpr( "get_monitor" ),
    585                                 {  new CastExpr( new VariableExpr( args.front() ), arg_type ) }
     950                                {  new CastExpr( new VariableExpr( args.front() ), arg_type, false ) }
    586951                        ))
    587952                );
     
    604969                                        {
    605970                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
    606                                                 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
     971                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ),
     972                                                new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) )
    607973                                        },
    608974                                        noDesignators,
     
    612978                );
    613979
    614                 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
    615                 body->push_front( new DeclStmt( monitors) );
    616         }
    617 
    618         void MutexKeyword::addStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     980                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
     981                body->push_front( new DeclStmt( monitors ) );
     982        }
     983
     984        void MutexKeyword::addThreadDtorStatements(
     985                        FunctionDecl*, CompoundStmt * body,
     986                        const std::list<DeclarationWithType * > & args ) {
     987                assert( args.size() == 1 );
     988                DeclarationWithType * arg = args.front();
     989                Type * arg_type = arg->get_type()->clone();
     990                assert( arg_type->get_mutex() );
     991                arg_type->set_mutex( false );
     992
     993                // thread_dtor_guard_t __guard = { this, intptr( 0 ) };
     994                body->push_front(
     995                        new DeclStmt( new ObjectDecl(
     996                                "__guard",
     997                                noStorageClasses,
     998                                LinkageSpec::Cforall,
     999                                nullptr,
     1000                                new StructInstType(
     1001                                        noQualifiers,
     1002                                        thread_guard_decl
     1003                                ),
     1004                                new ListInit(
     1005                                        {
     1006                                                new SingleInit( new CastExpr( new VariableExpr( arg ), arg_type ) ),
     1007                                                new SingleInit( new UntypedExpr(
     1008                                                        new NameExpr( "intptr" ), {
     1009                                                                new ConstantExpr( Constant::from_int( 0 ) ),
     1010                                                        }
     1011                                                ) ),
     1012                                        },
     1013                                        noDesignators,
     1014                                        true
     1015                                )
     1016                        ))
     1017                );
     1018        }
     1019
     1020        void MutexKeyword::addStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
    6191021                ObjectDecl * monitors = new ObjectDecl(
    6201022                        "__monitors",
     
    6411043                                        return new SingleInit( new UntypedExpr(
    6421044                                                new NameExpr( "get_monitor" ),
    643                                                 {  new CastExpr( new VariableExpr( var ), type ) }
     1045                                                {  new CastExpr( new VariableExpr( var ), type, false ) }
    6441046                                        ) );
    6451047                                })
     
    6651067                                                new SingleInit( new VariableExpr( monitors ) ),
    6661068                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ),
    667                                                 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
     1069                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
    6681070                                        },
    6691071                                        noDesignators,
     
    6731075                );
    6741076
    675                 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     1077                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    6761078                body->push_front( new DeclStmt( monitors) );
    6771079        }
     
    6811083        //=============================================================================================
    6821084        void ThreadStarter::previsit( StructDecl * decl ) {
    683                 if( decl->name == "thread_desc" && decl->body ) {
     1085                if( decl->name == "$thread" && decl->body ) {
    6841086                        assert( !thread_decl );
    6851087                        thread_decl = decl;
     
    7271129// tab-width: 4 //
    7281130// End: //
     1131
Note: See TracChangeset for help on using the changeset viewer.