source: src/Concurrency/Waitfor.cc@ 1ed958c3

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

First compiling build of CFA-CC with GC

  • 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 UniqueName namer_acc = "__acceptables_"s;
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;
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 ) {
161 return new UntypedExpr(
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 ) {
171 return new UntypedExpr(
172 new NameExpr( "?=?" ),
173 { lhs, rhs }
174 );
175 }
176
177 Expression * makeOpMember( Expression * sue, const std::string & mem ) {
178 return new UntypedMemberExpr( new NameExpr( mem ), sue );
179 }
180
181 Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
182 Expression * expr = makeOpAssign(
183 makeOpMember(
184 makeOpIndex(
185 object,
186 index
187 ),
188 member
189 ),
190 value
191 );
192
193 ResolvExpr::findVoidExpression( expr, indexer );
194
195 return new ExprStmt( expr );
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 }
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
213 Expression * detectIsDtor( Expression * func ) {
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 }
218 };
219
220
221 //=============================================================================================
222 // Generate waitfor implementation
223 //=============================================================================================
224
225 void GenerateWaitForPass::premutate( FunctionDecl * decl) {
226 if( decl->name != "__waitfor_internal" ) return;
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 }
238 else if( decl->name == "__waitfor_mask_t" ) {
239 assert( !decl_mask );
240 decl_mask = decl;
241 }
242 else if( decl->name == "monitor_desc" ) {
243 assert( !decl_monitor );
244 decl_monitor = decl;
245 }
246 }
247
248 Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
249 if( !decl_monitor || !decl_acceptable || !decl_mask )
250 SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" );
251
252 CompoundStmt * stmt = new CompoundStmt();
253
254 ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
255 ObjectDecl * flag = declareFlag( stmt );
256 Statement * setter = makeSetter( flag );
257
258 int index = 0;
259 for( auto & clause : waitfor->clauses ) {
260 init( acceptables, index, clause, setter, stmt );
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,
270 setter,
271 stmt
272 );
273
274 CompoundStmt * compound = new CompoundStmt();
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 );
282
283 choose( waitfor, result, compound );
284
285 return stmt;
286 }
287
288 ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
289 {
290 ObjectDecl * acceptables = ObjectDecl::newObject(
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
305 stmt->push_back( new DeclStmt( acceptables) );
306
307 Expression * set = new UntypedExpr(
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
316 ResolvExpr::findVoidExpression( set, indexer );
317
318 stmt->push_back( new ExprStmt( set ) );
319
320 return acceptables;
321 }
322
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
333 stmt->push_back( new DeclStmt( flag) );
334
335 return flag;
336 }
337
338 Statement * GenerateWaitForPass::makeSetter( ObjectDecl * flag ) {
339 Expression * expr = new UntypedExpr(
340 new NameExpr( "?=?" ),
341 {
342 new VariableExpr( flag ),
343 new ConstantExpr( Constant::from_ulong( 1 ) )
344 }
345 );
346
347 ResolvExpr::findVoidExpression( expr, indexer );
348
349 return new ExprStmt( expr );
350 }
351
352 ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
353
354 ObjectDecl * mon = ObjectDecl::newObject(
355 namer_mon.newName(),
356 new ArrayType(
357 noQualifiers,
358 new PointerType(
359 noQualifiers,
360 new StructInstType(
361 noQualifiers,
362 decl_monitor
363 )
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 ){
371 Expression * init = new CastExpr(
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
385 ResolvExpr::findSingleExpression( init, indexer );
386 return new SingleInit( init );
387 })
388 )
389 );
390
391 stmt->push_back( new DeclStmt( mon) );
392
393 return mon;
394 }
395
396 void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * setter, CompoundStmt * stmt ) {
397
398 ObjectDecl * monitors = declMon( clause, stmt );
399
400 Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
401
402 stmt->push_back( new IfStmt(
403 safeCond( clause.condition ),
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 ),
407 makeAccStatement( acceptables, index, "data" , new VariableExpr( monitors ) , indexer ),
408 makeAccStatement( acceptables, index, "size" , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
409 setter->clone()
410 }),
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,
424 Statement * setter,
425 CompoundStmt * stmt
426 ) {
427 ObjectDecl * timeout = ObjectDecl::newObject(
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
438 stmt->push_back( new DeclStmt( timeout ) );
439
440 if( time ) {
441 stmt->push_back( new IfStmt(
442 safeCond( time_cond ),
443 new CompoundStmt({
444 new ExprStmt(
445 makeOpAssign(
446 new VariableExpr( timeout ),
447 time
448 )
449 ),
450 setter->clone()
451 }),
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 ),
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 }),
470 nullptr
471 ));
472
473 else_cond = nullptr;
474 }
475
476 return new VariableExpr( timeout );
477 }
478
479 Expression * GenerateWaitForPass::call(
480 size_t count,
481 ObjectDecl * acceptables,
482 Expression * timeout,
483 CompoundStmt * stmt
484 ) {
485 ObjectDecl * index = ObjectDecl::newObject(
486 namer_idx.newName(),
487 new BasicType(
488 noQualifiers,
489 BasicType::ShortSignedInt
490 ),
491 new SingleInit(
492 new ConstantExpr( Constant::from_int( -1 ) )
493 )
494 );
495
496 stmt->push_back( new DeclStmt( index ) );
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 ) ) ),
506 new ListInit({
507 new SingleInit( new VariableExpr( acceptables ) ),
508 new SingleInit( new ConstantExpr( Constant::from_ulong( count ) ) )
509 })
510 })
511 );
512
513 stmt->push_back( new DeclStmt( mask ) );
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 ));
533
534 return new VariableExpr( index );
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(
566 new ConstantExpr( Constant::from_int( -2 ) ),
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(
581 new ConstantExpr( Constant::from_int( -1 ) ),
582 {
583 waitfor->orelse.statement,
584 new BranchStmt(
585 "",
586 BranchStmt::Break
587 )
588 }
589 )
590 );
591 }
592
593 stmt->push_back( swtch );
594 }
595};
596
597// Local Variables: //
598// mode: c //
599// tab-width: 4 //
600// End: //
Note: See TracBrowser for help on using the repository browser.