source: src/Concurrency/Waitfor.cc @ 80a9898

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexerpthread-emulationqualifiedEnum
Last change on this file since 80a9898 was 42506e1, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Added compound statements around waitfor statements.
closes #106

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