Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Waitfor.cc

    re3e16bc r08da53d  
    2727#include "InitTweak/InitTweak.h"   // for getPointerBase
    2828#include "Parser/LinkageSpec.h"    // for Cforall
    29 #include "SymTab/AddVisit.h"       // for acceptAndAdd
     29#include "ResolvExpr/Resolver.h"   // for findVoidExpression
    3030#include "SynTree/Constant.h"      // for Constant
    3131#include "SynTree/Declaration.h"   // for StructDecl, FunctionDecl, ObjectDecl
     
    112112        //=============================================================================================
    113113
    114         class GenerateWaitForPass final : public WithStmtsToAdd {
     114        class GenerateWaitForPass final : public WithIndexer {
    115115          public:
    116116
     
    126126
    127127                ObjectDecl * declare( unsigned long count, CompoundStmt * stmt );
     128                ObjectDecl * declareFlag( CompoundStmt * stmt );
     129                Statement  * makeSetter( ObjectDecl * flag );
    128130                ObjectDecl * declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt );
    129                 void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt );
    130                 Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, CompoundStmt * stmt );
    131                 Expression * call();
    132                 void choose();
     131                void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * settter, CompoundStmt * stmt );
     132                Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, Statement * settter, CompoundStmt * stmt );
     133                Expression * call(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
     134                void         choose( WaitForStmt * waitfor, Expression  * result, CompoundStmt * stmt );
    133135
    134136                static void implement( std::list< Declaration * > & translationUnit ) {
     
    140142          private:
    141143                FunctionDecl        * decl_waitfor    = nullptr;
     144                StructDecl          * decl_mask       = nullptr;
    142145                StructDecl          * decl_acceptable = nullptr;
    143146                StructDecl          * decl_monitor    = nullptr;
    144                 DeclarationWithType * decl_m_func     = nullptr;
    145                 DeclarationWithType * decl_m_count    = nullptr;
    146                 DeclarationWithType * decl_m_monitors = nullptr;
    147                 DeclarationWithType * decl_m_isdtor   = nullptr;
    148147
    149148                static std::unique_ptr< Type > generic_func;
    150149
     150                UniqueName namer_acc = "__acceptables_"s;
     151                UniqueName namer_idx = "__index_"s;
     152                UniqueName namer_flg = "__do_run_"s;
     153                UniqueName namer_msk = "__mask_"s;
    151154                UniqueName namer_mon = "__monitors_"s;
    152                 UniqueName namer_acc = "__acceptables_"s;
    153155                UniqueName namer_tim = "__timeout_"s;
    154156        };
     
    167169        namespace {
    168170                Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
    169                         return new ApplicationExpr(
     171                        return new UntypedExpr(
    170172                                new NameExpr( "?[?]" ),
    171173                                {
     
    177179
    178180                Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
    179                         return new ApplicationExpr(
     181                        return new UntypedExpr(
    180182                                        new NameExpr( "?=?" ),
    181183                                        { lhs, rhs }
     
    183185                }
    184186
    185                 Expression * makeOpMember( Expression * sue, DeclarationWithType * mem ) {
    186                         return new MemberExpr( mem, sue );
    187                 }
    188 
    189                 Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, DeclarationWithType * member, Expression * value ) {
    190                         return new ExprStmt(
    191                                 noLabels,
    192                                 makeOpAssign(
    193                                         makeOpMember(
    194                                                 makeOpIndex(
    195                                                         object,
    196                                                         index
    197                                                 ),
    198                                                 member
     187                Expression * makeOpMember( Expression * sue, const std::string & mem ) {
     188                        return new UntypedMemberExpr( new NameExpr( mem ), sue );
     189                }
     190
     191                Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
     192                        Expression * expr = makeOpAssign(
     193                                makeOpMember(
     194                                        makeOpIndex(
     195                                                object,
     196                                                index
    199197                                        ),
    200                                         value
    201                                 )
     198                                        member
     199                                ),
     200                                value
    202201                        );
     202
     203                        ResolvExpr::findVoidExpression( expr, indexer );
     204
     205                        return new ExprStmt( noLabels, expr );
    203206                }
    204207
     
    208211                        return new ConstantExpr( Constant::from_bool( ifnull ) );
    209212                }
     213
     214                VariableExpr * extractVariable( Expression * func ) {
     215                        if( VariableExpr * var = dynamic_cast< VariableExpr * >( func ) ) {
     216                                return var;
     217                        }
     218
     219                        CastExpr * cast = strict_dynamic_cast< CastExpr * >( func );
     220                        return strict_dynamic_cast< VariableExpr * >( cast->arg );
     221                }
     222
     223                Expression * detectIsDtor( Expression * func ) {
     224                        VariableExpr * typed_func = extractVariable( func );
     225                        bool is_dtor = InitTweak::isDestructor( typed_func->var );
     226                        return new ConstantExpr( Constant::from_bool( is_dtor ) );
     227                }
    210228        };
    211229
     
    216234
    217235        void GenerateWaitForPass::premutate( FunctionDecl * decl) {
    218                 if( decl->name != "__accept_internal" ) return;
     236                if( decl->name != "__waitfor_internal" ) return;
    219237
    220238                decl_waitfor = decl;
     
    227245                        assert( !decl_acceptable );
    228246                        decl_acceptable = decl;
    229                         for( Declaration * field : decl_acceptable->members ) {
    230                                      if( field->name == "func"    ) decl_m_func     = strict_dynamic_cast< DeclarationWithType * >( field );
    231                                 else if( field->name == "count"   ) decl_m_count    = strict_dynamic_cast< DeclarationWithType * >( field );
    232                                 else if( field->name == "monitor" ) decl_m_monitors = strict_dynamic_cast< DeclarationWithType * >( field );
    233                                 else if( field->name == "is_dtor" ) decl_m_isdtor   = strict_dynamic_cast< DeclarationWithType * >( field );
    234                         }
    235 
     247                }
     248                else if( decl->name == "__waitfor_mask_t" ) {
     249                        assert( !decl_mask );
     250                        decl_mask = decl;
    236251                }
    237252                else if( decl->name == "monitor_desc" ) {
     
    242257
    243258        Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
    244                 return waitfor;
    245 
    246                 if( !decl_monitor || !decl_acceptable ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
     259                if( !decl_monitor || !decl_acceptable || !decl_mask ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
    247260
    248261                CompoundStmt * stmt = new CompoundStmt( noLabels );
    249262
    250263                ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
     264                ObjectDecl * flag        = declareFlag( stmt );
     265                Statement  * setter      = makeSetter( flag );
    251266
    252267                int index = 0;
    253268                for( auto & clause : waitfor->clauses ) {
    254                         init( acceptables, index, clause, stmt );
     269                        init( acceptables, index, clause, setter, stmt );
    255270
    256271                        index++;
     
    262277                        waitfor->orelse .statement,
    263278                        waitfor->orelse .condition,
     279                        setter,
    264280                        stmt
    265281                );
    266282
    267                 // Expression * result  = call( acceptables, timeout, orelse, stmt );
    268 
    269                 // choose( waitfor, result );
     283                CompoundStmt * compound = new CompoundStmt( noLabels );
     284                stmt->push_back( new IfStmt(
     285                        noLabels,
     286                        safeCond( new VariableExpr( flag ) ),
     287                        compound,
     288                        nullptr
     289                ));
     290
     291                Expression * result = call( waitfor->clauses.size(), acceptables, timeout, compound );
     292
     293                choose( waitfor, result, compound );
    270294
    271295                return stmt;
     
    274298        ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
    275299        {
    276                 ObjectDecl * acceptables = new ObjectDecl(
     300                ObjectDecl * acceptables = ObjectDecl::newObject(
    277301                        namer_acc.newName(),
    278                         noStorage,
    279                         LinkageSpec::Cforall,
    280                         nullptr,
    281302                        new ArrayType(
    282303                                noQualifiers,
     
    294315                stmt->push_back( new DeclStmt( noLabels, acceptables) );
    295316
     317                Expression * set = new UntypedExpr(
     318                        new NameExpr( "__builtin_memset" ),
     319                        {
     320                                new VariableExpr( acceptables ),
     321                                new ConstantExpr( Constant::from_int( 0 ) ),
     322                                new SizeofExpr( new VariableExpr( acceptables ) )
     323                        }
     324                );
     325
     326                ResolvExpr::findVoidExpression( set, indexer );
     327
     328                stmt->push_back( new ExprStmt( noLabels, set ) );
     329
    296330                return acceptables;
    297331        }
    298332
     333        ObjectDecl * GenerateWaitForPass::declareFlag( CompoundStmt * stmt ) {
     334                ObjectDecl * flag = ObjectDecl::newObject(
     335                        namer_flg.newName(),
     336                        new BasicType(
     337                                noQualifiers,
     338                                BasicType::Bool
     339                        ),
     340                        new SingleInit( new ConstantExpr( Constant::from_ulong( 0 ) ) )
     341                );
     342
     343                stmt->push_back( new DeclStmt( noLabels, flag) );
     344
     345                return flag;
     346        }
     347
     348        Statement * GenerateWaitForPass::makeSetter( ObjectDecl * flag ) {
     349                Expression * expr = new UntypedExpr(
     350                        new NameExpr( "?=?" ),
     351                        {
     352                                new VariableExpr( flag ),
     353                                new ConstantExpr( Constant::from_ulong( 1 ) )
     354                        }
     355                );
     356
     357                ResolvExpr::findVoidExpression( expr, indexer );
     358
     359                return new ExprStmt( noLabels, expr );
     360        }
     361
    299362        ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
    300363
    301                 ObjectDecl * mon = new ObjectDecl(
     364                ObjectDecl * mon = ObjectDecl::newObject(
    302365                        namer_mon.newName(),
    303                         noStorage,
    304                         LinkageSpec::Cforall,
    305                         nullptr,
    306366                        new ArrayType(
    307367                                noQualifiers,
    308                                 new StructInstType(
     368                                new PointerType(
    309369                                        noQualifiers,
    310                                         decl_monitor
     370                                        new StructInstType(
     371                                                noQualifiers,
     372                                                decl_monitor
     373                                        )
    311374                                ),
    312375                                new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
     
    316379                        new ListInit(
    317380                                map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
    318                                         return new SingleInit( expr );
     381                                        Expression * init = new CastExpr(
     382                                                new UntypedExpr(
     383                                                        new NameExpr( "get_monitor" ),
     384                                                        { expr }
     385                                                ),
     386                                                new PointerType(
     387                                                        noQualifiers,
     388                                                        new StructInstType(
     389                                                                noQualifiers,
     390                                                                decl_monitor
     391                                                        )
     392                                                )
     393                                        );
     394
     395                                        ResolvExpr::findSingleExpression( init, indexer );
     396                                        return new SingleInit( init );
    319397                                })
    320398                        )
     
    326404        }
    327405
    328         void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
     406        void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * setter, CompoundStmt * stmt ) {
    329407
    330408                ObjectDecl * monitors = declMon( clause, stmt );
    331409
    332                 CompoundStmt * compound = new CompoundStmt( noLabels );
    333                 compound->push_back( makeAccStatement( acceptables, index, decl_m_func    , clause.target.function ) );
    334                 compound->push_back( makeAccStatement( acceptables, index, decl_m_count   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ) ) );
    335                 compound->push_back( makeAccStatement( acceptables, index, decl_m_monitors, new VariableExpr( monitors ) ) );
    336                 compound->push_back( makeAccStatement( acceptables, index, decl_m_isdtor  , new ConstantExpr( Constant::from_bool( true ) ) ) );
     410                Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
    337411
    338412                stmt->push_back( new IfStmt(
    339413                        noLabels,
    340414                        safeCond( clause.condition ),
    341                         compound,
     415                        new CompoundStmt({
     416                                makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
     417                                makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t )                            , indexer ),
     418                                makeAccStatement( acceptables, index, "list"   , new VariableExpr( monitors )                                              , indexer ),
     419                                makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
     420                                setter->clone()
     421                        }),
    342422                        nullptr
    343423                ));
     
    353433                bool has_else,
    354434                Expression *& else_cond,
     435                Statement * setter,
    355436                CompoundStmt * stmt
    356437        ) {
    357                 ObjectDecl * timeout = new ObjectDecl(
     438                ObjectDecl * timeout = ObjectDecl::newObject(
    358439                        namer_tim.newName(),
    359                         noStorage,
    360                         LinkageSpec::Cforall,
    361                         nullptr,
    362440                        new BasicType(
    363441                                noQualifiers,
     
    374452                        stmt->push_back( new IfStmt(
    375453                                noLabels,
    376                                 safeCond( else_cond ),
    377                                 new ExprStmt(
    378                                         noLabels,
    379                                         makeOpAssign(
    380                                                 new VariableExpr( timeout ),
    381                                                 time
    382                                         )
    383                                 ),
     454                                safeCond( time_cond ),
     455                                new CompoundStmt({
     456                                        new ExprStmt(
     457                                                noLabels,
     458                                                makeOpAssign(
     459                                                        new VariableExpr( timeout ),
     460                                                        time
     461                                                )
     462                                        ),
     463                                        setter->clone()
     464                                }),
    384465                                nullptr
    385466                        ));
     
    392473                                noLabels,
    393474                                safeCond( else_cond ),
    394                                 new ExprStmt(
    395                                         noLabels,
    396                                         makeOpAssign(
    397                                                 new VariableExpr( timeout ),
    398                                                 new ConstantExpr( Constant::from_ulong( 0 ) )
    399                                         )
    400                                 ),
     475                                new CompoundStmt({
     476                                        new ExprStmt(
     477                                                noLabels,
     478                                                makeOpAssign(
     479                                                        new VariableExpr( timeout ),
     480                                                        new ConstantExpr( Constant::from_ulong( 0 ) )
     481                                                )
     482                                        ),
     483                                        setter->clone()
     484                                }),
    401485                                nullptr
    402486                        ));
     
    405489                }
    406490
     491                delete setter;
     492
    407493                return new VariableExpr( timeout );
     494        }
     495
     496        Expression * GenerateWaitForPass::call(
     497                size_t count,
     498                ObjectDecl * acceptables,
     499                Expression * timeout,
     500                CompoundStmt * stmt
     501        ) {
     502                ObjectDecl * index = ObjectDecl::newObject(
     503                        namer_idx.newName(),
     504                        new BasicType(
     505                                noQualifiers,
     506                                BasicType::ShortSignedInt
     507                        ),
     508                        new SingleInit(
     509                                new ConstantExpr( Constant::from_int( -1 ) )
     510                        )
     511                );
     512
     513                stmt->push_back( new DeclStmt( noLabels, index ) );
     514
     515                ObjectDecl * mask = ObjectDecl::newObject(
     516                        namer_msk.newName(),
     517                        new StructInstType(
     518                                noQualifiers,
     519                                decl_mask
     520                        ),
     521                        new ListInit({
     522                                new SingleInit( new AddressExpr( new VariableExpr( index ) ) ),
     523                                new SingleInit( new VariableExpr( acceptables ) ),
     524                                new SingleInit( new ConstantExpr( Constant::from_ulong( count ) ) )
     525                        })
     526                );
     527
     528                stmt->push_back( new DeclStmt( noLabels, mask ) );
     529
     530                stmt->push_back( new ExprStmt(
     531                        noLabels,
     532                        new ApplicationExpr(
     533                                VariableExpr::functionPointer( decl_waitfor ),
     534                                {
     535                                        new CastExpr(
     536                                                new VariableExpr( mask ),
     537                                                new ReferenceType(
     538                                                        noQualifiers,
     539                                                        new StructInstType(
     540                                                                noQualifiers,
     541                                                                decl_mask
     542                                                        )
     543                                                )
     544                                        ),
     545                                        timeout
     546                                }
     547                        )
     548                ));
     549
     550                return new VariableExpr( index );
     551        }
     552
     553        void GenerateWaitForPass::choose(
     554                WaitForStmt * waitfor,
     555                Expression  * result,
     556                CompoundStmt * stmt
     557        ) {
     558                SwitchStmt * swtch = new SwitchStmt(
     559                        noLabels,
     560                        result,
     561                        std::list<Statement *>()
     562                );
     563
     564                unsigned long i = 0;
     565                for( auto & clause : waitfor->clauses ) {
     566                        swtch->statements.push_back(
     567                                new CaseStmt(
     568                                        noLabels,
     569                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
     570                                        {
     571                                                clause.statement,
     572                                                new BranchStmt(
     573                                                        noLabels,
     574                                                        "",
     575                                                        BranchStmt::Break
     576                                                )
     577                                        }
     578                                )
     579                        );
     580                }
     581
     582                if(waitfor->timeout.statement) {
     583                        swtch->statements.push_back(
     584                                new CaseStmt(
     585                                        noLabels,
     586                                        new ConstantExpr( Constant::from_int( -2 ) ),
     587                                        {
     588                                                waitfor->timeout.statement,
     589                                                new BranchStmt(
     590                                                        noLabels,
     591                                                        "",
     592                                                        BranchStmt::Break
     593                                                )
     594                                        }
     595                                )
     596                        );
     597                }
     598
     599                if(waitfor->orelse.statement) {
     600                        swtch->statements.push_back(
     601                                new CaseStmt(
     602                                        noLabels,
     603                                        new ConstantExpr( Constant::from_int( -1 ) ),
     604                                        {
     605                                                waitfor->orelse.statement,
     606                                                new BranchStmt(
     607                                                        noLabels,
     608                                                        "",
     609                                                        BranchStmt::Break
     610                                                )
     611                                        }
     612                                )
     613                        );
     614                }
     615
     616                stmt->push_back( swtch );
    408617        }
    409618};
Note: See TracChangeset for help on using the changeset viewer.