Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Waitfor.cc

    re3e16bc r310e5b7  
    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
     
    129129                void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt );
    130130                Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, CompoundStmt * stmt );
    131                 Expression * call();
    132                 void choose();
     131                Expression * call(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
     132                void         choose( WaitForStmt * waitfor, Expression  * result, CompoundStmt * stmt );
    133133
    134134                static void implement( std::list< Declaration * > & translationUnit ) {
     
    142142                StructDecl          * decl_acceptable = nullptr;
    143143                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;
    148144
    149145                static std::unique_ptr< Type > generic_func;
     
    152148                UniqueName namer_acc = "__acceptables_"s;
    153149                UniqueName namer_tim = "__timeout_"s;
     150                UniqueName namer_ret = "__return_"s;
    154151        };
    155152
     
    167164        namespace {
    168165                Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
    169                         return new ApplicationExpr(
     166                        return new UntypedExpr(
    170167                                new NameExpr( "?[?]" ),
    171168                                {
     
    177174
    178175                Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
    179                         return new ApplicationExpr(
     176                        return new UntypedExpr(
    180177                                        new NameExpr( "?=?" ),
    181178                                        { lhs, rhs }
     
    183180                }
    184181
    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
     182                Expression * makeOpMember( Expression * sue, const std::string & mem ) {
     183                        return new UntypedMemberExpr( new NameExpr( mem ), sue );
     184                }
     185
     186                Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
     187                        std::unique_ptr< Expression > expr( makeOpAssign(
     188                                makeOpMember(
     189                                        makeOpIndex(
     190                                                object,
     191                                                index
    199192                                        ),
    200                                         value
    201                                 )
    202                         );
     193                                        member
     194                                ),
     195                                value
     196                        ) );
     197
     198                        return new ExprStmt( noLabels, ResolvExpr::findVoidExpression( expr.get(), indexer ) );
    203199                }
    204200
     
    208204                        return new ConstantExpr( Constant::from_bool( ifnull ) );
    209205                }
     206
     207                VariableExpr * extractVariable( Expression * func ) {
     208                        if( VariableExpr * var = dynamic_cast< VariableExpr * >( func ) ) {
     209                                return var;
     210                        }
     211
     212                        CastExpr * cast = strict_dynamic_cast< CastExpr * >( func );
     213                        return strict_dynamic_cast< VariableExpr * >( cast->arg );
     214                }
     215
     216                Expression * betterIsDtor( Expression * func ) {
     217                        VariableExpr * typed_func = extractVariable( func );
     218                        bool is_dtor = InitTweak::isDestructor( typed_func->var );
     219                        return new ConstantExpr( Constant::from_bool( is_dtor ) );
     220                }
    210221        };
    211222
     
    216227
    217228        void GenerateWaitForPass::premutate( FunctionDecl * decl) {
    218                 if( decl->name != "__accept_internal" ) return;
     229                if( decl->name != "__waitfor_internal" ) return;
    219230
    220231                decl_waitfor = decl;
     
    227238                        assert( !decl_acceptable );
    228239                        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 
    236240                }
    237241                else if( decl->name == "monitor_desc" ) {
     
    242246
    243247        Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
    244                 return waitfor;
    245 
    246248                if( !decl_monitor || !decl_acceptable ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
    247249
     
    265267                );
    266268
    267                 // Expression * result  = call( acceptables, timeout, orelse, stmt );
    268 
    269                 // choose( waitfor, result );
     269                Expression * result = call( waitfor->clauses.size(), acceptables, timeout, stmt );
     270
     271                choose( waitfor, result, stmt );
    270272
    271273                return stmt;
     
    274276        ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
    275277        {
    276                 ObjectDecl * acceptables = new ObjectDecl(
     278                ObjectDecl * acceptables = ObjectDecl::newObject(
    277279                        namer_acc.newName(),
    278                         noStorage,
    279                         LinkageSpec::Cforall,
    280                         nullptr,
    281280                        new ArrayType(
    282281                                noQualifiers,
     
    299298        ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
    300299
    301                 ObjectDecl * mon = new ObjectDecl(
     300                ObjectDecl * mon = ObjectDecl::newObject(
    302301                        namer_mon.newName(),
    303                         noStorage,
    304                         LinkageSpec::Cforall,
    305                         nullptr,
    306302                        new ArrayType(
    307303                                noQualifiers,
     
    330326                ObjectDecl * monitors = declMon( clause, stmt );
    331327
     328                Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
     329
     330                Expression * is_dtor = betterIsDtor( clause.target.function );
    332331                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 ) ) ) );
     332                compound->push_back( makeAccStatement( acceptables, index, "func"    , new CastExpr( clause.target.function, fptr_t )                            , indexer ) );
     333                compound->push_back( makeAccStatement( acceptables, index, "count"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ) );
     334                compound->push_back( makeAccStatement( acceptables, index, "monitors", new VariableExpr( monitors )                                              , indexer ) );
     335                compound->push_back( makeAccStatement( acceptables, index, "is_dtor" , is_dtor                                                                   , indexer ) );
    337336
    338337                stmt->push_back( new IfStmt(
     
    355354                CompoundStmt * stmt
    356355        ) {
    357                 ObjectDecl * timeout = new ObjectDecl(
     356                ObjectDecl * timeout = ObjectDecl::newObject(
    358357                        namer_tim.newName(),
    359                         noStorage,
    360                         LinkageSpec::Cforall,
    361                         nullptr,
    362358                        new BasicType(
    363359                                noQualifiers,
     
    374370                        stmt->push_back( new IfStmt(
    375371                                noLabels,
    376                                 safeCond( else_cond ),
     372                                safeCond( time_cond ),
    377373                                new ExprStmt(
    378374                                        noLabels,
     
    407403                return new VariableExpr( timeout );
    408404        }
     405
     406        Expression * GenerateWaitForPass::call(
     407                size_t count,
     408                ObjectDecl * acceptables,
     409                Expression * timeout,
     410                CompoundStmt * stmt
     411        ) {
     412                ObjectDecl * decl = ObjectDecl::newObject(
     413                        namer_ret.newName(),
     414                        new BasicType(
     415                                noQualifiers,
     416                                BasicType::LongLongUnsignedInt
     417                        ),
     418                        new SingleInit(
     419                                new UntypedExpr(
     420                                        VariableExpr::functionPointer( decl_waitfor ),
     421                                        {
     422                                                new ConstantExpr( Constant::from_ulong( count ) ),
     423                                                new VariableExpr( acceptables ),
     424                                                timeout
     425                                        }
     426                                )
     427                        )
     428                );
     429
     430                stmt->push_back( new DeclStmt( noLabels, decl ) );
     431
     432                return new VariableExpr( decl );
     433        }
     434
     435        void GenerateWaitForPass::choose(
     436                WaitForStmt * waitfor,
     437                Expression  * result,
     438                CompoundStmt * stmt
     439        ) {
     440                SwitchStmt * swtch = new SwitchStmt(
     441                        noLabels,
     442                        result,
     443                        std::list<Statement *>()
     444                );
     445
     446                unsigned long i = 0;
     447                for( auto & clause : waitfor->clauses ) {
     448                        swtch->statements.push_back(
     449                                new CaseStmt(
     450                                        noLabels,
     451                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
     452                                        {
     453                                                clause.statement,
     454                                                new BranchStmt(
     455                                                        noLabels,
     456                                                        "",
     457                                                        BranchStmt::Break
     458                                                )
     459                                        }
     460                                )
     461                        );
     462                }
     463
     464                if(waitfor->timeout.statement) {
     465                        swtch->statements.push_back(
     466                                new CaseStmt(
     467                                        noLabels,
     468                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
     469                                        {
     470                                                waitfor->timeout.statement,
     471                                                new BranchStmt(
     472                                                        noLabels,
     473                                                        "",
     474                                                        BranchStmt::Break
     475                                                )
     476                                        }
     477                                )
     478                        );
     479                }
     480
     481                if(waitfor->orelse.statement) {
     482                        swtch->statements.push_back(
     483                                new CaseStmt(
     484                                        noLabels,
     485                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
     486                                        {
     487                                                waitfor->orelse.statement,
     488                                                new BranchStmt(
     489                                                        noLabels,
     490                                                        "",
     491                                                        BranchStmt::Break
     492                                                )
     493                                        }
     494                                )
     495                        );
     496                }
     497
     498                stmt->push_back( swtch );
     499        }
    409500};
    410501
Note: See TracChangeset for help on using the changeset viewer.