source: src/Concurrency/Waitfor.cc@ eb28d7e

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since eb28d7e was e15853c, checked in by Peter A. Buhr <pabuhr@…>, 7 years ago

remove leading underscores in enums for _FloatNN and _Bool

  • Property mode set to 100644
File size: 15.3 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 : 7
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}*/
101
102namespace Concurrency {
103 //=============================================================================================
104 // Pass declarations
105 //=============================================================================================
106
107 class GenerateWaitForPass final : public WithIndexer {
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 );
121 ObjectDecl * declareFlag( CompoundStmt * stmt );
122 Statement * makeSetter( ObjectDecl * flag );
123 ObjectDecl * declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt );
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 );
126 Expression * call(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
127 void choose( WaitForStmt * waitfor, Expression * result, CompoundStmt * stmt );
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;
137 StructDecl * decl_mask = nullptr;
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;
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;
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 ) {
164 return new UntypedExpr(
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 ) {
174 return new UntypedExpr(
175 new NameExpr( "?=?" ),
176 { lhs, rhs }
177 );
178 }
179
180 Expression * makeOpMember( Expression * sue, const std::string & mem ) {
181 return new UntypedMemberExpr( new NameExpr( mem ), sue );
182 }
183
184 Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
185 Expression * expr = makeOpAssign(
186 makeOpMember(
187 makeOpIndex(
188 object,
189 index
190 ),
191 member
192 ),
193 value
194 );
195
196 ResolvExpr::findVoidExpression( expr, indexer );
197
198 return new ExprStmt( expr );
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 }
206
207 VariableExpr * extractVariable( Expression * func ) {
208 if( VariableExpr * var = dynamic_cast< VariableExpr * >( func ) ) {
209 return var;
210 }
211
212 CastExpr * cast = strict_dynamic_cast< CastExpr * >( func );
213 return strict_dynamic_cast< VariableExpr * >( cast->arg );
214 }
215
216 Expression * detectIsDtor( Expression * func ) {
217 VariableExpr * typed_func = extractVariable( func );
218 bool is_dtor = InitTweak::isDestructor( typed_func->var );
219 return new ConstantExpr( Constant::from_bool( is_dtor ) );
220 }
221 };
222
223
224 //=============================================================================================
225 // Generate waitfor implementation
226 //=============================================================================================
227
228 void GenerateWaitForPass::premutate( FunctionDecl * decl) {
229 if( decl->name != "__waitfor_internal" ) return;
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 }
241 else if( decl->name == "__waitfor_mask_t" ) {
242 assert( !decl_mask );
243 decl_mask = decl;
244 }
245 else if( decl->name == "monitor_desc" ) {
246 assert( !decl_monitor );
247 decl_monitor = decl;
248 }
249 }
250
251 Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
252 if( !decl_monitor || !decl_acceptable || !decl_mask )
253 SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor.hfa>" );
254
255 CompoundStmt * stmt = new CompoundStmt();
256
257 ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
258 ObjectDecl * flag = declareFlag( stmt );
259 Statement * setter = makeSetter( flag );
260
261 int index = 0;
262 for( auto & clause : waitfor->clauses ) {
263 init( acceptables, index, clause, setter, stmt );
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,
273 setter,
274 stmt
275 );
276
277 CompoundStmt * compound = new CompoundStmt();
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 );
285
286 choose( waitfor, result, compound );
287
288 return stmt;
289 }
290
291 ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
292 {
293 ObjectDecl * acceptables = ObjectDecl::newObject(
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
308 stmt->push_back( new DeclStmt( acceptables) );
309
310 Expression * set = new UntypedExpr(
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
319 ResolvExpr::findVoidExpression( set, indexer );
320
321 stmt->push_back( new ExprStmt( set ) );
322
323 return acceptables;
324 }
325
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
336 stmt->push_back( new DeclStmt( flag) );
337
338 return flag;
339 }
340
341 Statement * GenerateWaitForPass::makeSetter( ObjectDecl * flag ) {
342 Expression * expr = new UntypedExpr(
343 new NameExpr( "?=?" ),
344 {
345 new VariableExpr( flag ),
346 new ConstantExpr( Constant::from_ulong( 1 ) )
347 }
348 );
349
350 ResolvExpr::findVoidExpression( expr, indexer );
351
352 return new ExprStmt( expr );
353 }
354
355 ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
356
357 ObjectDecl * mon = ObjectDecl::newObject(
358 namer_mon.newName(),
359 new ArrayType(
360 noQualifiers,
361 new PointerType(
362 noQualifiers,
363 new StructInstType(
364 noQualifiers,
365 decl_monitor
366 )
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 ){
374 Expression * init = new CastExpr(
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
388 ResolvExpr::findSingleExpression( init, indexer );
389 return new SingleInit( init );
390 })
391 )
392 );
393
394 stmt->push_back( new DeclStmt( mon) );
395
396 return mon;
397 }
398
399 void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * setter, CompoundStmt * stmt ) {
400
401 ObjectDecl * monitors = declMon( clause, stmt );
402
403 Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
404
405 stmt->push_back( new IfStmt(
406 safeCond( clause.condition ),
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 ),
410 makeAccStatement( acceptables, index, "data" , new VariableExpr( monitors ) , indexer ),
411 makeAccStatement( acceptables, index, "size" , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
412 setter->clone()
413 }),
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,
427 Statement * setter,
428 CompoundStmt * stmt
429 ) {
430 ObjectDecl * timeout = ObjectDecl::newObject(
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
441 stmt->push_back( new DeclStmt( timeout ) );
442
443 if( time ) {
444 stmt->push_back( new IfStmt(
445 safeCond( time_cond ),
446 new CompoundStmt({
447 new ExprStmt(
448 makeOpAssign(
449 new VariableExpr( timeout ),
450 time
451 )
452 ),
453 setter->clone()
454 }),
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 ),
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 }),
473 nullptr
474 ));
475
476 else_cond = nullptr;
477 }
478
479 delete setter;
480
481 return new VariableExpr( timeout );
482 }
483
484 Expression * GenerateWaitForPass::call(
485 size_t count,
486 ObjectDecl * acceptables,
487 Expression * timeout,
488 CompoundStmt * stmt
489 ) {
490 ObjectDecl * index = ObjectDecl::newObject(
491 namer_idx.newName(),
492 new BasicType(
493 noQualifiers,
494 BasicType::ShortSignedInt
495 ),
496 new SingleInit(
497 new ConstantExpr( Constant::from_int( -1 ) )
498 )
499 );
500
501 stmt->push_back( new DeclStmt( index ) );
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 ) ) ),
511 new ListInit({
512 new SingleInit( new VariableExpr( acceptables ) ),
513 new SingleInit( new ConstantExpr( Constant::from_ulong( count ) ) )
514 })
515 })
516 );
517
518 stmt->push_back( new DeclStmt( mask ) );
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 ));
538
539 return new VariableExpr( index );
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 {
558 new CompoundStmt({
559 clause.statement,
560 new BranchStmt(
561 "",
562 BranchStmt::Break
563 )
564 })
565 }
566 )
567 );
568 }
569
570 if(waitfor->timeout.statement) {
571 swtch->statements.push_back(
572 new CaseStmt(
573 new ConstantExpr( Constant::from_int( -2 ) ),
574 {
575 new CompoundStmt({
576 waitfor->timeout.statement,
577 new BranchStmt(
578 "",
579 BranchStmt::Break
580 )
581 })
582 }
583 )
584 );
585 }
586
587 if(waitfor->orelse.statement) {
588 swtch->statements.push_back(
589 new CaseStmt(
590 new ConstantExpr( Constant::from_int( -1 ) ),
591 {
592 new CompoundStmt({
593 waitfor->orelse.statement,
594 new BranchStmt(
595 "",
596 BranchStmt::Break
597 )
598 })
599 }
600 )
601 );
602 }
603
604 stmt->push_back( swtch );
605 }
606};
607
608// Local Variables: //
609// mode: c //
610// tab-width: 4 //
611// End: //
Note: See TracBrowser for help on using the repository browser.