source: src/Concurrency/Waitfor.cc @ 8d7bef2

new-envwith_gc
Last change on this file since 8d7bef2 was 8d7bef2, checked in by Aaron Moss <a3moss@…>, 6 years ago

First compiling build of CFA-CC with GC

  • Property mode set to 100644
File size: 15.1 KB
RevLine 
[9f5ecf5]1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Waitfor.cc --
8//
9// Author           : Thierry Delisle
10// Created On       : Mon Aug 28 11:06:52 2017
11// Last Modified By :
12// Last Modified On :
13// Update Count     : 5
14//
15
16#include "Concurrency/Keywords.h"
17
18#include <cassert>                 // for assert
19#include <string>                  // for string, operator==
20
21using namespace std::string_literals;
22
23#include "Common/PassVisitor.h"    // for PassVisitor
24#include "Common/SemanticError.h"  // for SemanticError
25#include "Common/utility.h"        // for deleteAll, map_range
26#include "CodeGen/OperatorTable.h" // for isConstructor
27#include "InitTweak/InitTweak.h"   // for getPointerBase
28#include "Parser/LinkageSpec.h"    // for Cforall
[1dcd9554]29#include "ResolvExpr/Resolver.h"   // for findVoidExpression
[9f5ecf5]30#include "SynTree/Constant.h"      // for Constant
31#include "SynTree/Declaration.h"   // for StructDecl, FunctionDecl, ObjectDecl
32#include "SynTree/Expression.h"    // for VariableExpr, ConstantExpr, Untype...
33#include "SynTree/Initializer.h"   // for SingleInit, ListInit, Initializer ...
34#include "SynTree/Label.h"         // for Label
35#include "SynTree/Statement.h"     // for CompoundStmt, DeclStmt, ExprStmt
36#include "SynTree/Type.h"          // for StructInstType, Type, PointerType
37#include "SynTree/Visitor.h"       // for Visitor, acceptAll
38
39class Attribute;
40/*
41void foo() {
42        while( true ) {
43                when( a < 1 ) waitfor( f, a ) { bar(); }
44                or timeout( swagl() );
45                or waitfor( g, a ) { baz(); }
46                or waitfor( ^?{}, a ) { break; }
47                or waitfor( ^?{} ) { break; }
48        }
49}
50
51void f(int i, float f, A & mutex b, struct foo *  );
52void f(int );
53
54
55                      |  |
56                      |  |
57                            |  |
58                      |  |
59                      |  |
60                    \ |  | /
61                     \    /
62                      \  /
63                       \/
64
65
66void foo() {
67        while( true ) {
68
69                acceptable_t acceptables[3];
70                if( a < 1 ) {
71                        acceptables[0].func = f;
72                        acceptables[0].mon = a;
73                }
74                acceptables[1].func = g;
75                acceptables[1].mon = a;
76
77                acceptables[2].func = f;
78                acceptables[2].mon = a;
79                acceptables[2].is_dtor = true;
80
81                int ret = waitfor_internal( acceptables, swagl() );
82
83                switch( ret ) {
84                        case 0:
85                        {
86                                bar();
87                        }
88                        case 1:
89                        {
90                                baz();
91                        }
92                        case 2:
93                                signal(a);
94                                {
95                                        break;
96                                }
97                }
98        }
99}*/
100
101namespace Concurrency {
102        //=============================================================================================
103        // Pass declarations
104        //=============================================================================================
105
[1dcd9554]106        class GenerateWaitForPass final : public WithIndexer {
[9f5ecf5]107          public:
108
109                void premutate( FunctionDecl * decl );
110                void premutate( StructDecl   * decl );
111
112                Statement * postmutate( WaitForStmt * stmt );
113
114                static void generate( std::list< Declaration * > & translationUnit ) {
115                        PassVisitor< GenerateWaitForPass > impl;
116                        acceptAll( translationUnit, impl );
117                }
118
119                ObjectDecl * declare( unsigned long count, CompoundStmt * stmt );
[aaa4f93]120                ObjectDecl * declareFlag( CompoundStmt * stmt );
121                Statement  * makeSetter( ObjectDecl * flag );
[9f5ecf5]122                ObjectDecl * declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt );
[aaa4f93]123                void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * settter, CompoundStmt * stmt );
124                Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, Statement * settter, CompoundStmt * stmt );
[1dcd9554]125                Expression * call(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
126                void         choose( WaitForStmt * waitfor, Expression  * result, CompoundStmt * stmt );
[9f5ecf5]127
128                static void implement( std::list< Declaration * > & translationUnit ) {
129                        PassVisitor< GenerateWaitForPass > impl;
130                        mutateAll( translationUnit, impl );
131                }
132
133
134          private:
135                FunctionDecl        * decl_waitfor    = nullptr;
[aaa4f93]136                StructDecl          * decl_mask       = nullptr;
[9f5ecf5]137                StructDecl          * decl_acceptable = nullptr;
138                StructDecl          * decl_monitor    = nullptr;
139
140                UniqueName namer_acc = "__acceptables_"s;
[aaa4f93]141                UniqueName namer_idx = "__index_"s;
142                UniqueName namer_flg = "__do_run_"s;
143                UniqueName namer_msk = "__mask_"s;
144                UniqueName namer_mon = "__monitors_"s;
[9f5ecf5]145                UniqueName namer_tim = "__timeout_"s;
146        };
147
148        //=============================================================================================
149        // General entry routine
150        //=============================================================================================
151        void generateWaitFor( std::list< Declaration * > & translationUnit ) {
152                GenerateWaitForPass     ::implement( translationUnit );
153        }
154
155        //=============================================================================================
156        // Generic helper routine
157        //=============================================================================================
158
159        namespace {
160                Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
[1dcd9554]161                        return new UntypedExpr(
[9f5ecf5]162                                new NameExpr( "?[?]" ),
163                                {
164                                        new VariableExpr( array ),
165                                        new ConstantExpr( Constant::from_ulong( index ) )
166                                }
167                        );
168                }
169
170                Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
[1dcd9554]171                        return new UntypedExpr(
[9f5ecf5]172                                        new NameExpr( "?=?" ),
173                                        { lhs, rhs }
174                        );
175                }
176
[1dcd9554]177                Expression * makeOpMember( Expression * sue, const std::string & mem ) {
178                        return new UntypedMemberExpr( new NameExpr( mem ), sue );
[9f5ecf5]179                }
180
[1dcd9554]181                Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
[08da53d]182                        Expression * expr = makeOpAssign(
[1dcd9554]183                                makeOpMember(
184                                        makeOpIndex(
185                                                object,
186                                                index
[9f5ecf5]187                                        ),
[1dcd9554]188                                        member
189                                ),
190                                value
[08da53d]191                        );
192
193                        ResolvExpr::findVoidExpression( expr, indexer );
[1dcd9554]194
[ba3706f]195                        return new ExprStmt( expr );
[9f5ecf5]196                }
197
198                Expression * safeCond( Expression * expr, bool ifnull = true ) {
199                        if( expr ) return expr;
200
201                        return new ConstantExpr( Constant::from_bool( ifnull ) );
202                }
[310e5b7]203
204                VariableExpr * extractVariable( Expression * func ) {
205                        if( VariableExpr * var = dynamic_cast< VariableExpr * >( func ) ) {
206                                return var;
207                        }
208
209                        CastExpr * cast = strict_dynamic_cast< CastExpr * >( func );
210                        return strict_dynamic_cast< VariableExpr * >( cast->arg );
211                }
212
[8f98b78]213                Expression * detectIsDtor( Expression * func ) {
[310e5b7]214                        VariableExpr * typed_func = extractVariable( func );
215                        bool is_dtor = InitTweak::isDestructor( typed_func->var );
216                        return new ConstantExpr( Constant::from_bool( is_dtor ) );
217                }
[9f5ecf5]218        };
219
220
221        //=============================================================================================
222        // Generate waitfor implementation
223        //=============================================================================================
224
225        void GenerateWaitForPass::premutate( FunctionDecl * decl) {
[310e5b7]226                if( decl->name != "__waitfor_internal" ) return;
[9f5ecf5]227
228                decl_waitfor = decl;
229        }
230
231        void GenerateWaitForPass::premutate( StructDecl   * decl ) {
232                if( ! decl->body ) return;
233
234                if( decl->name == "__acceptable_t" ) {
235                        assert( !decl_acceptable );
236                        decl_acceptable = decl;
237                }
[aaa4f93]238                else if( decl->name == "__waitfor_mask_t" ) {
239                        assert( !decl_mask );
240                        decl_mask = decl;
241                }
[9f5ecf5]242                else if( decl->name == "monitor_desc" ) {
243                        assert( !decl_monitor );
244                        decl_monitor = decl;
245                }
246        }
247
248        Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
[d55d7a6]249                if( !decl_monitor || !decl_acceptable || !decl_mask )
[a16764a6]250                        SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" );
[9f5ecf5]251
[ba3706f]252                CompoundStmt * stmt = new CompoundStmt();
[9f5ecf5]253
254                ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
[aaa4f93]255                ObjectDecl * flag        = declareFlag( stmt );
256                Statement  * setter      = makeSetter( flag );
[9f5ecf5]257
258                int index = 0;
259                for( auto & clause : waitfor->clauses ) {
[aaa4f93]260                        init( acceptables, index, clause, setter, stmt );
[9f5ecf5]261
262                        index++;
263                }
264
265                Expression * timeout = init_timeout(
266                        waitfor->timeout.time,
267                        waitfor->timeout.condition,
268                        waitfor->orelse .statement,
269                        waitfor->orelse .condition,
[aaa4f93]270                        setter,
[9f5ecf5]271                        stmt
272                );
273
[ba3706f]274                CompoundStmt * compound = new CompoundStmt();
[aaa4f93]275                stmt->push_back( new IfStmt(
276                        safeCond( new VariableExpr( flag ) ),
277                        compound,
278                        nullptr
279                ));
280
281                Expression * result = call( waitfor->clauses.size(), acceptables, timeout, compound );
[9f5ecf5]282
[aaa4f93]283                choose( waitfor, result, compound );
[9f5ecf5]284
285                return stmt;
286        }
287
288        ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
289        {
[1dcd9554]290                ObjectDecl * acceptables = ObjectDecl::newObject(
[9f5ecf5]291                        namer_acc.newName(),
292                        new ArrayType(
293                                noQualifiers,
294                                new StructInstType(
295                                        noQualifiers,
296                                        decl_acceptable
297                                ),
298                                new ConstantExpr( Constant::from_ulong( count ) ),
299                                false,
300                                false
301                        ),
302                        nullptr
303                );
304
[ba3706f]305                stmt->push_back( new DeclStmt( acceptables) );
[9f5ecf5]306
[08da53d]307                Expression * set = new UntypedExpr(
[aaa4f93]308                        new NameExpr( "__builtin_memset" ),
309                        {
310                                new VariableExpr( acceptables ),
311                                new ConstantExpr( Constant::from_int( 0 ) ),
312                                new SizeofExpr( new VariableExpr( acceptables ) )
313                        }
314                );
315
[08da53d]316                ResolvExpr::findVoidExpression( set, indexer );
[aaa4f93]317
[ba3706f]318                stmt->push_back( new ExprStmt( set ) );
[aaa4f93]319
[9f5ecf5]320                return acceptables;
321        }
322
[aaa4f93]323        ObjectDecl * GenerateWaitForPass::declareFlag( CompoundStmt * stmt ) {
324                ObjectDecl * flag = ObjectDecl::newObject(
325                        namer_flg.newName(),
326                        new BasicType(
327                                noQualifiers,
328                                BasicType::Bool
329                        ),
330                        new SingleInit( new ConstantExpr( Constant::from_ulong( 0 ) ) )
331                );
332
[ba3706f]333                stmt->push_back( new DeclStmt( flag) );
[aaa4f93]334
335                return flag;
336        }
337
338        Statement * GenerateWaitForPass::makeSetter( ObjectDecl * flag ) {
[08da53d]339                Expression * expr = new UntypedExpr(
[aaa4f93]340                        new NameExpr( "?=?" ),
341                        {
342                                new VariableExpr( flag ),
343                                new ConstantExpr( Constant::from_ulong( 1 ) )
344                        }
345                );
346
[08da53d]347                ResolvExpr::findVoidExpression( expr, indexer );
[aaa4f93]348
[ba3706f]349                return new ExprStmt( expr );
[aaa4f93]350        }
351
[9f5ecf5]352        ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
353
[1dcd9554]354                ObjectDecl * mon = ObjectDecl::newObject(
[9f5ecf5]355                        namer_mon.newName(),
356                        new ArrayType(
357                                noQualifiers,
[8f98b78]358                                new PointerType(
[9f5ecf5]359                                        noQualifiers,
[8f98b78]360                                        new StructInstType(
361                                                noQualifiers,
362                                                decl_monitor
363                                        )
[9f5ecf5]364                                ),
365                                new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
366                                false,
367                                false
368                        ),
369                        new ListInit(
370                                map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
[08da53d]371                                        Expression * init = new CastExpr(
[8f98b78]372                                                new UntypedExpr(
373                                                        new NameExpr( "get_monitor" ),
374                                                        { expr }
375                                                ),
376                                                new PointerType(
377                                                        noQualifiers,
378                                                        new StructInstType(
379                                                                noQualifiers,
380                                                                decl_monitor
381                                                        )
382                                                )
383                                        );
384
[08da53d]385                                        ResolvExpr::findSingleExpression( init, indexer );
[8f98b78]386                                        return new SingleInit( init );
[9f5ecf5]387                                })
388                        )
389                );
390
[ba3706f]391                stmt->push_back( new DeclStmt( mon) );
[9f5ecf5]392
393                return mon;
394        }
395
[aaa4f93]396        void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * setter, CompoundStmt * stmt ) {
[9f5ecf5]397
398                ObjectDecl * monitors = declMon( clause, stmt );
399
[1dcd9554]400                Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
401
[9f5ecf5]402                stmt->push_back( new IfStmt(
403                        safeCond( clause.condition ),
[aaa4f93]404                        new CompoundStmt({
405                                makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
406                                makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t )                            , indexer ),
[0cf5b79]407                                makeAccStatement( acceptables, index, "data"   , new VariableExpr( monitors )                                              , indexer ),
[aaa4f93]408                                makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
409                                setter->clone()
410                        }),
[9f5ecf5]411                        nullptr
412                ));
413
414                clause.target.function = nullptr;
415                clause.target.arguments.empty();
416                clause.condition = nullptr;
417        }
418
419        Expression * GenerateWaitForPass::init_timeout(
420                Expression *& time,
421                Expression *& time_cond,
422                bool has_else,
423                Expression *& else_cond,
[aaa4f93]424                Statement * setter,
[9f5ecf5]425                CompoundStmt * stmt
426        ) {
[1dcd9554]427                ObjectDecl * timeout = ObjectDecl::newObject(
[9f5ecf5]428                        namer_tim.newName(),
429                        new BasicType(
430                                noQualifiers,
431                                BasicType::LongLongUnsignedInt
432                        ),
433                        new SingleInit(
434                                new ConstantExpr( Constant::from_int( -1 ) )
435                        )
436                );
437
[ba3706f]438                stmt->push_back( new DeclStmt( timeout ) );
[9f5ecf5]439
440                if( time ) {
441                        stmt->push_back( new IfStmt(
[1dcd9554]442                                safeCond( time_cond ),
[aaa4f93]443                                new CompoundStmt({
444                                        new ExprStmt(
445                                                makeOpAssign(
446                                                        new VariableExpr( timeout ),
447                                                        time
448                                                )
449                                        ),
450                                        setter->clone()
451                                }),
[9f5ecf5]452                                nullptr
453                        ));
454
455                        time = time_cond = nullptr;
456                }
457
458                if( has_else ) {
459                        stmt->push_back( new IfStmt(
460                                safeCond( else_cond ),
[aaa4f93]461                                new CompoundStmt({
462                                        new ExprStmt(
463                                                makeOpAssign(
464                                                        new VariableExpr( timeout ),
465                                                        new ConstantExpr( Constant::from_ulong( 0 ) )
466                                                )
467                                        ),
468                                        setter->clone()
469                                }),
[9f5ecf5]470                                nullptr
471                        ));
472
473                        else_cond = nullptr;
474                }
475
476                return new VariableExpr( timeout );
477        }
[1dcd9554]478
479        Expression * GenerateWaitForPass::call(
480                size_t count,
481                ObjectDecl * acceptables,
482                Expression * timeout,
483                CompoundStmt * stmt
484        ) {
[aaa4f93]485                ObjectDecl * index = ObjectDecl::newObject(
486                        namer_idx.newName(),
[1dcd9554]487                        new BasicType(
488                                noQualifiers,
[aaa4f93]489                                BasicType::ShortSignedInt
[1dcd9554]490                        ),
491                        new SingleInit(
[aaa4f93]492                                new ConstantExpr( Constant::from_int( -1 ) )
[1dcd9554]493                        )
494                );
495
[ba3706f]496                stmt->push_back( new DeclStmt( index ) );
[aaa4f93]497
498                ObjectDecl * mask = ObjectDecl::newObject(
499                        namer_msk.newName(),
500                        new StructInstType(
501                                noQualifiers,
502                                decl_mask
503                        ),
504                        new ListInit({
505                                new SingleInit( new AddressExpr( new VariableExpr( index ) ) ),
[d2d50d7]506                                new ListInit({
507                                        new SingleInit( new VariableExpr( acceptables ) ),
508                                        new SingleInit( new ConstantExpr( Constant::from_ulong( count ) ) )
509                                })
[aaa4f93]510                        })
511                );
512
[ba3706f]513                stmt->push_back( new DeclStmt( mask ) );
[aaa4f93]514
515                stmt->push_back( new ExprStmt(
516                        new ApplicationExpr(
517                                VariableExpr::functionPointer( decl_waitfor ),
518                                {
519                                        new CastExpr(
520                                                new VariableExpr( mask ),
521                                                new ReferenceType(
522                                                        noQualifiers,
523                                                        new StructInstType(
524                                                                noQualifiers,
525                                                                decl_mask
526                                                        )
527                                                )
528                                        ),
529                                        timeout
530                                }
531                        )
532                ));
[1dcd9554]533
[aaa4f93]534                return new VariableExpr( index );
[1dcd9554]535        }
536
537        void GenerateWaitForPass::choose(
538                WaitForStmt * waitfor,
539                Expression  * result,
540                CompoundStmt * stmt
541        ) {
542                SwitchStmt * swtch = new SwitchStmt(
543                        result,
544                        std::list<Statement *>()
545                );
546
547                unsigned long i = 0;
548                for( auto & clause : waitfor->clauses ) {
549                        swtch->statements.push_back(
550                                new CaseStmt(
551                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
552                                        {
553                                                clause.statement,
554                                                new BranchStmt(
555                                                        "",
556                                                        BranchStmt::Break
557                                                )
558                                        }
559                                )
560                        );
561                }
562
563                if(waitfor->timeout.statement) {
564                        swtch->statements.push_back(
565                                new CaseStmt(
[b18830e]566                                        new ConstantExpr( Constant::from_int( -2 ) ),
[1dcd9554]567                                        {
568                                                waitfor->timeout.statement,
569                                                new BranchStmt(
570                                                        "",
571                                                        BranchStmt::Break
572                                                )
573                                        }
574                                )
575                        );
576                }
577
578                if(waitfor->orelse.statement) {
579                        swtch->statements.push_back(
580                                new CaseStmt(
[b18830e]581                                        new ConstantExpr( Constant::from_int( -1 ) ),
[1dcd9554]582                                        {
583                                                waitfor->orelse.statement,
584                                                new BranchStmt(
585                                                        "",
586                                                        BranchStmt::Break
587                                                )
588                                        }
589                                )
590                        );
591                }
592
593                stmt->push_back( swtch );
594        }
[9f5ecf5]595};
596
597// Local Variables: //
598// mode: c //
599// tab-width: 4 //
[08da53d]600// End: //
Note: See TracBrowser for help on using the repository browser.