source: src/Concurrency/Waitfor.cc @ 58b6d1b

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexerpthread-emulation
Last change on this file since 58b6d1b was 73abe95, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Replace extension-less headers with .hfa

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