source: src/Concurrency/Waitfor.cc@ a2dbad10

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 a2dbad10 was b18830e, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Refactoring monitor code in prevision for proper waitfor support

  • added monitor group struct
  • else and timeout now return negative results
  • Property mode set to 100644
File size: 13.3 KB
RevLine 
[9f5ecf5]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
[1dcd9554]29#include "ResolvExpr/Resolver.h" // for findVoidExpression
[9f5ecf5]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
[1dcd9554]114 class GenerateWaitForPass final : public WithIndexer {
[9f5ecf5]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 );
[1dcd9554]131 Expression * call(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
132 void choose( WaitForStmt * waitfor, Expression * result, CompoundStmt * stmt );
[9f5ecf5]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
145 static std::unique_ptr< Type > generic_func;
146
147 UniqueName namer_mon = "__monitors_"s;
148 UniqueName namer_acc = "__acceptables_"s;
149 UniqueName namer_tim = "__timeout_"s;
[1dcd9554]150 UniqueName namer_ret = "__return_"s;
[9f5ecf5]151 };
152
153 //=============================================================================================
154 // General entry routine
155 //=============================================================================================
156 void generateWaitFor( std::list< Declaration * > & translationUnit ) {
157 GenerateWaitForPass ::implement( translationUnit );
158 }
159
160 //=============================================================================================
161 // Generic helper routine
162 //=============================================================================================
163
164 namespace {
165 Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
[1dcd9554]166 return new UntypedExpr(
[9f5ecf5]167 new NameExpr( "?[?]" ),
168 {
169 new VariableExpr( array ),
170 new ConstantExpr( Constant::from_ulong( index ) )
171 }
172 );
173 }
174
175 Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
[1dcd9554]176 return new UntypedExpr(
[9f5ecf5]177 new NameExpr( "?=?" ),
178 { lhs, rhs }
179 );
180 }
181
[1dcd9554]182 Expression * makeOpMember( Expression * sue, const std::string & mem ) {
183 return new UntypedMemberExpr( new NameExpr( mem ), sue );
[9f5ecf5]184 }
185
[1dcd9554]186 Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
187 std::unique_ptr< Expression > expr( makeOpAssign(
188 makeOpMember(
189 makeOpIndex(
190 object,
191 index
[9f5ecf5]192 ),
[1dcd9554]193 member
194 ),
195 value
196 ) );
197
198 return new ExprStmt( noLabels, ResolvExpr::findVoidExpression( expr.get(), indexer ) );
[9f5ecf5]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 }
[310e5b7]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
[8f98b78]216 Expression * detectIsDtor( Expression * func ) {
[310e5b7]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 }
[9f5ecf5]221 };
222
223
224 //=============================================================================================
225 // Generate waitfor implementation
226 //=============================================================================================
227
228 void GenerateWaitForPass::premutate( FunctionDecl * decl) {
[310e5b7]229 if( decl->name != "__waitfor_internal" ) return;
[9f5ecf5]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 == "monitor_desc" ) {
242 assert( !decl_monitor );
243 decl_monitor = decl;
244 }
245 }
246
247 Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
248 if( !decl_monitor || !decl_acceptable ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
249
250 CompoundStmt * stmt = new CompoundStmt( noLabels );
251
252 ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
253
254 int index = 0;
255 for( auto & clause : waitfor->clauses ) {
256 init( acceptables, index, clause, stmt );
257
258 index++;
259 }
260
261 Expression * timeout = init_timeout(
262 waitfor->timeout.time,
263 waitfor->timeout.condition,
264 waitfor->orelse .statement,
265 waitfor->orelse .condition,
266 stmt
267 );
268
[1dcd9554]269 Expression * result = call( waitfor->clauses.size(), acceptables, timeout, stmt );
[9f5ecf5]270
[1dcd9554]271 choose( waitfor, result, stmt );
[9f5ecf5]272
273 return stmt;
274 }
275
276 ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
277 {
[1dcd9554]278 ObjectDecl * acceptables = ObjectDecl::newObject(
[9f5ecf5]279 namer_acc.newName(),
280 new ArrayType(
281 noQualifiers,
282 new StructInstType(
283 noQualifiers,
284 decl_acceptable
285 ),
286 new ConstantExpr( Constant::from_ulong( count ) ),
287 false,
288 false
289 ),
290 nullptr
291 );
292
293 stmt->push_back( new DeclStmt( noLabels, acceptables) );
294
295 return acceptables;
296 }
297
298 ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
299
[1dcd9554]300 ObjectDecl * mon = ObjectDecl::newObject(
[9f5ecf5]301 namer_mon.newName(),
302 new ArrayType(
303 noQualifiers,
[8f98b78]304 new PointerType(
[9f5ecf5]305 noQualifiers,
[8f98b78]306 new StructInstType(
307 noQualifiers,
308 decl_monitor
309 )
[9f5ecf5]310 ),
311 new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
312 false,
313 false
314 ),
315 new ListInit(
316 map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
[8f98b78]317 Expression * untyped = new CastExpr(
318 new UntypedExpr(
319 new NameExpr( "get_monitor" ),
320 { expr }
321 ),
322 new PointerType(
323 noQualifiers,
324 new StructInstType(
325 noQualifiers,
326 decl_monitor
327 )
328 )
329 );
330
331 Expression * init = ResolvExpr::findSingleExpression( untyped, indexer );
332 delete untyped;
333 return new SingleInit( init );
[9f5ecf5]334 })
335 )
336 );
337
338 stmt->push_back( new DeclStmt( noLabels, mon) );
339
340 return mon;
341 }
342
343 void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
344
345 ObjectDecl * monitors = declMon( clause, stmt );
346
[1dcd9554]347 Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
348
[9f5ecf5]349 CompoundStmt * compound = new CompoundStmt( noLabels );
[8f98b78]350 compound->push_back( makeAccStatement( acceptables, index, "is_dtor" , detectIsDtor( clause.target.function ) , indexer ) );
[1dcd9554]351 compound->push_back( makeAccStatement( acceptables, index, "func" , new CastExpr( clause.target.function, fptr_t ) , indexer ) );
352 compound->push_back( makeAccStatement( acceptables, index, "monitors", new VariableExpr( monitors ) , indexer ) );
[8f98b78]353 compound->push_back( makeAccStatement( acceptables, index, "count" , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ) );
[9f5ecf5]354
355 stmt->push_back( new IfStmt(
356 noLabels,
357 safeCond( clause.condition ),
358 compound,
359 nullptr
360 ));
361
362 clause.target.function = nullptr;
363 clause.target.arguments.empty();
364 clause.condition = nullptr;
365 }
366
367 Expression * GenerateWaitForPass::init_timeout(
368 Expression *& time,
369 Expression *& time_cond,
370 bool has_else,
371 Expression *& else_cond,
372 CompoundStmt * stmt
373 ) {
[1dcd9554]374 ObjectDecl * timeout = ObjectDecl::newObject(
[9f5ecf5]375 namer_tim.newName(),
376 new BasicType(
377 noQualifiers,
378 BasicType::LongLongUnsignedInt
379 ),
380 new SingleInit(
381 new ConstantExpr( Constant::from_int( -1 ) )
382 )
383 );
384
385 stmt->push_back( new DeclStmt( noLabels, timeout ) );
386
387 if( time ) {
388 stmt->push_back( new IfStmt(
389 noLabels,
[1dcd9554]390 safeCond( time_cond ),
[9f5ecf5]391 new ExprStmt(
392 noLabels,
393 makeOpAssign(
394 new VariableExpr( timeout ),
395 time
396 )
397 ),
398 nullptr
399 ));
400
401 time = time_cond = nullptr;
402 }
403
404 if( has_else ) {
405 stmt->push_back( new IfStmt(
406 noLabels,
407 safeCond( else_cond ),
408 new ExprStmt(
409 noLabels,
410 makeOpAssign(
411 new VariableExpr( timeout ),
412 new ConstantExpr( Constant::from_ulong( 0 ) )
413 )
414 ),
415 nullptr
416 ));
417
418 else_cond = nullptr;
419 }
420
421 return new VariableExpr( timeout );
422 }
[1dcd9554]423
424 Expression * GenerateWaitForPass::call(
425 size_t count,
426 ObjectDecl * acceptables,
427 Expression * timeout,
428 CompoundStmt * stmt
429 ) {
430 ObjectDecl * decl = ObjectDecl::newObject(
431 namer_ret.newName(),
432 new BasicType(
433 noQualifiers,
434 BasicType::LongLongUnsignedInt
435 ),
436 new SingleInit(
437 new UntypedExpr(
438 VariableExpr::functionPointer( decl_waitfor ),
439 {
440 new ConstantExpr( Constant::from_ulong( count ) ),
441 new VariableExpr( acceptables ),
442 timeout
443 }
444 )
445 )
446 );
447
448 stmt->push_back( new DeclStmt( noLabels, decl ) );
449
450 return new VariableExpr( decl );
451 }
452
453 void GenerateWaitForPass::choose(
454 WaitForStmt * waitfor,
455 Expression * result,
456 CompoundStmt * stmt
457 ) {
458 SwitchStmt * swtch = new SwitchStmt(
459 noLabels,
460 result,
461 std::list<Statement *>()
462 );
463
464 unsigned long i = 0;
465 for( auto & clause : waitfor->clauses ) {
466 swtch->statements.push_back(
467 new CaseStmt(
468 noLabels,
469 new ConstantExpr( Constant::from_ulong( i++ ) ),
470 {
471 clause.statement,
472 new BranchStmt(
473 noLabels,
474 "",
475 BranchStmt::Break
476 )
477 }
478 )
479 );
480 }
481
482 if(waitfor->timeout.statement) {
483 swtch->statements.push_back(
484 new CaseStmt(
485 noLabels,
[b18830e]486 new ConstantExpr( Constant::from_int( -2 ) ),
[1dcd9554]487 {
488 waitfor->timeout.statement,
489 new BranchStmt(
490 noLabels,
491 "",
492 BranchStmt::Break
493 )
494 }
495 )
496 );
497 }
498
499 if(waitfor->orelse.statement) {
500 swtch->statements.push_back(
501 new CaseStmt(
502 noLabels,
[b18830e]503 new ConstantExpr( Constant::from_int( -1 ) ),
[1dcd9554]504 {
505 waitfor->orelse.statement,
506 new BranchStmt(
507 noLabels,
508 "",
509 BranchStmt::Break
510 )
511 }
512 )
513 );
514 }
515
516 stmt->push_back( swtch );
517 }
[9f5ecf5]518};
519
520// Local Variables: //
521// mode: c //
522// tab-width: 4 //
523// End: //
Note: See TracBrowser for help on using the repository browser.