source: src/Concurrency/Waitfor.cc@ df7a162

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since df7a162 was d55d7a6, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Massive change to errors to enable warnings

  • 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 throw SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" );
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.