source: src/Concurrency/Waitfor.cc @ f92c696

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since f92c696 was e3e16bc, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Renamed safe_dynamic_cast to strict_dynamic_cast

  • Property mode set to 100644
File size: 11.0 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 "SymTab/AddVisit.h"       // for acceptAndAdd
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        namespace {
104                const std::list<Label> noLabels;
105                const std::list< Attribute * > noAttributes;
106                Type::StorageClasses noStorage;
107                Type::Qualifiers noQualifiers;
108        }
109
110        //=============================================================================================
111        // Pass declarations
112        //=============================================================================================
113
114        class GenerateWaitForPass final : public WithStmtsToAdd {
115          public:
116
117                void premutate( FunctionDecl * decl );
118                void premutate( StructDecl   * decl );
119
120                Statement * postmutate( WaitForStmt * stmt );
121
122                static void generate( std::list< Declaration * > & translationUnit ) {
123                        PassVisitor< GenerateWaitForPass > impl;
124                        acceptAll( translationUnit, impl );
125                }
126
127                ObjectDecl * declare( unsigned long count, CompoundStmt * stmt );
128                ObjectDecl * declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt );
129                void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt );
130                Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, CompoundStmt * stmt );
131                Expression * call();
132                void choose();
133
134                static void implement( std::list< Declaration * > & translationUnit ) {
135                        PassVisitor< GenerateWaitForPass > impl;
136                        mutateAll( translationUnit, impl );
137                }
138
139
140          private:
141                FunctionDecl        * decl_waitfor    = nullptr;
142                StructDecl          * decl_acceptable = nullptr;
143                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;
148
149                static std::unique_ptr< Type > generic_func;
150
151                UniqueName namer_mon = "__monitors_"s;
152                UniqueName namer_acc = "__acceptables_"s;
153                UniqueName namer_tim = "__timeout_"s;
154        };
155
156        //=============================================================================================
157        // General entry routine
158        //=============================================================================================
159        void generateWaitFor( std::list< Declaration * > & translationUnit ) {
160                GenerateWaitForPass     ::implement( translationUnit );
161        }
162
163        //=============================================================================================
164        // Generic helper routine
165        //=============================================================================================
166
167        namespace {
168                Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
169                        return new ApplicationExpr(
170                                new NameExpr( "?[?]" ),
171                                {
172                                        new VariableExpr( array ),
173                                        new ConstantExpr( Constant::from_ulong( index ) )
174                                }
175                        );
176                }
177
178                Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
179                        return new ApplicationExpr(
180                                        new NameExpr( "?=?" ),
181                                        { lhs, rhs }
182                        );
183                }
184
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
199                                        ),
200                                        value
201                                )
202                        );
203                }
204
205                Expression * safeCond( Expression * expr, bool ifnull = true ) {
206                        if( expr ) return expr;
207
208                        return new ConstantExpr( Constant::from_bool( ifnull ) );
209                }
210        };
211
212
213        //=============================================================================================
214        // Generate waitfor implementation
215        //=============================================================================================
216
217        void GenerateWaitForPass::premutate( FunctionDecl * decl) {
218                if( decl->name != "__accept_internal" ) return;
219
220                decl_waitfor = decl;
221        }
222
223        void GenerateWaitForPass::premutate( StructDecl   * decl ) {
224                if( ! decl->body ) return;
225
226                if( decl->name == "__acceptable_t" ) {
227                        assert( !decl_acceptable );
228                        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
236                }
237                else if( decl->name == "monitor_desc" ) {
238                        assert( !decl_monitor );
239                        decl_monitor = decl;
240                }
241        }
242
243        Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
244                return waitfor;
245
246                if( !decl_monitor || !decl_acceptable ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
247
248                CompoundStmt * stmt = new CompoundStmt( noLabels );
249
250                ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
251
252                int index = 0;
253                for( auto & clause : waitfor->clauses ) {
254                        init( acceptables, index, clause, stmt );
255
256                        index++;
257                }
258
259                Expression * timeout = init_timeout(
260                        waitfor->timeout.time,
261                        waitfor->timeout.condition,
262                        waitfor->orelse .statement,
263                        waitfor->orelse .condition,
264                        stmt
265                );
266
267                // Expression * result  = call( acceptables, timeout, orelse, stmt );
268
269                // choose( waitfor, result );
270
271                return stmt;
272        }
273
274        ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
275        {
276                ObjectDecl * acceptables = new ObjectDecl(
277                        namer_acc.newName(),
278                        noStorage,
279                        LinkageSpec::Cforall,
280                        nullptr,
281                        new ArrayType(
282                                noQualifiers,
283                                new StructInstType(
284                                        noQualifiers,
285                                        decl_acceptable
286                                ),
287                                new ConstantExpr( Constant::from_ulong( count ) ),
288                                false,
289                                false
290                        ),
291                        nullptr
292                );
293
294                stmt->push_back( new DeclStmt( noLabels, acceptables) );
295
296                return acceptables;
297        }
298
299        ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
300
301                ObjectDecl * mon = new ObjectDecl(
302                        namer_mon.newName(),
303                        noStorage,
304                        LinkageSpec::Cforall,
305                        nullptr,
306                        new ArrayType(
307                                noQualifiers,
308                                new StructInstType(
309                                        noQualifiers,
310                                        decl_monitor
311                                ),
312                                new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
313                                false,
314                                false
315                        ),
316                        new ListInit(
317                                map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
318                                        return new SingleInit( expr );
319                                })
320                        )
321                );
322
323                stmt->push_back( new DeclStmt( noLabels, mon) );
324
325                return mon;
326        }
327
328        void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
329
330                ObjectDecl * monitors = declMon( clause, stmt );
331
332                CompoundStmt * compound = new CompoundStmt( noLabels );
333                compound->push_back( makeAccStatement( acceptables, index, decl_m_func    , clause.target.function ) );
334                compound->push_back( makeAccStatement( acceptables, index, decl_m_count   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ) ) );
335                compound->push_back( makeAccStatement( acceptables, index, decl_m_monitors, new VariableExpr( monitors ) ) );
336                compound->push_back( makeAccStatement( acceptables, index, decl_m_isdtor  , new ConstantExpr( Constant::from_bool( true ) ) ) );
337
338                stmt->push_back( new IfStmt(
339                        noLabels,
340                        safeCond( clause.condition ),
341                        compound,
342                        nullptr
343                ));
344
345                clause.target.function = nullptr;
346                clause.target.arguments.empty();
347                clause.condition = nullptr;
348        }
349
350        Expression * GenerateWaitForPass::init_timeout(
351                Expression *& time,
352                Expression *& time_cond,
353                bool has_else,
354                Expression *& else_cond,
355                CompoundStmt * stmt
356        ) {
357                ObjectDecl * timeout = new ObjectDecl(
358                        namer_tim.newName(),
359                        noStorage,
360                        LinkageSpec::Cforall,
361                        nullptr,
362                        new BasicType(
363                                noQualifiers,
364                                BasicType::LongLongUnsignedInt
365                        ),
366                        new SingleInit(
367                                new ConstantExpr( Constant::from_int( -1 ) )
368                        )
369                );
370
371                stmt->push_back( new DeclStmt( noLabels, timeout ) );
372
373                if( time ) {
374                        stmt->push_back( new IfStmt(
375                                noLabels,
376                                safeCond( else_cond ),
377                                new ExprStmt(
378                                        noLabels,
379                                        makeOpAssign(
380                                                new VariableExpr( timeout ),
381                                                time
382                                        )
383                                ),
384                                nullptr
385                        ));
386
387                        time = time_cond = nullptr;
388                }
389
390                if( has_else ) {
391                        stmt->push_back( new IfStmt(
392                                noLabels,
393                                safeCond( else_cond ),
394                                new ExprStmt(
395                                        noLabels,
396                                        makeOpAssign(
397                                                new VariableExpr( timeout ),
398                                                new ConstantExpr( Constant::from_ulong( 0 ) )
399                                        )
400                                ),
401                                nullptr
402                        ));
403
404                        else_cond = nullptr;
405                }
406
407                return new VariableExpr( timeout );
408        }
409};
410
411// Local Variables: //
412// mode: c //
413// tab-width: 4 //
414// End: //
Note: See TracBrowser for help on using the repository browser.