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

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 stuck-waitfor-destruct with_gc
Last change on this file since 1dcd9554 was 1dcd9554, checked in by Thierry Delisle <tdelisle@…>, 9 years ago

First "working" implementation of waitfor

  • Property mode set to 100644
File size: 12.4 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 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 WithIndexer {
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(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
132 void choose( WaitForStmt * waitfor, Expression * result, CompoundStmt * stmt );
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;
150 UniqueName namer_ret = "__return_"s;
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 ) {
166 return new UntypedExpr(
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 ) {
176 return new UntypedExpr(
177 new NameExpr( "?=?" ),
178 { lhs, rhs }
179 );
180 }
181
182 Expression * makeOpMember( Expression * sue, const std::string & mem ) {
183 return new UntypedMemberExpr( new NameExpr( mem ), sue );
184 }
185
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
192 ),
193 member
194 ),
195 value
196 ) );
197
198 return new ExprStmt( noLabels, ResolvExpr::findVoidExpression( expr.get(), indexer ) );
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
208
209 //=============================================================================================
210 // Generate waitfor implementation
211 //=============================================================================================
212
213 void GenerateWaitForPass::premutate( FunctionDecl * decl) {
214 if( decl->name != "__accept_internal" ) return;
215
216 decl_waitfor = decl;
217 }
218
219 void GenerateWaitForPass::premutate( StructDecl * decl ) {
220 if( ! decl->body ) return;
221
222 if( decl->name == "__acceptable_t" ) {
223 assert( !decl_acceptable );
224 decl_acceptable = decl;
225 }
226 else if( decl->name == "monitor_desc" ) {
227 assert( !decl_monitor );
228 decl_monitor = decl;
229 }
230 }
231
232 Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
233 if( !decl_monitor || !decl_acceptable ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
234
235 CompoundStmt * stmt = new CompoundStmt( noLabels );
236
237 ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
238
239 int index = 0;
240 for( auto & clause : waitfor->clauses ) {
241 init( acceptables, index, clause, stmt );
242
243 index++;
244 }
245
246 Expression * timeout = init_timeout(
247 waitfor->timeout.time,
248 waitfor->timeout.condition,
249 waitfor->orelse .statement,
250 waitfor->orelse .condition,
251 stmt
252 );
253
254 Expression * result = call( waitfor->clauses.size(), acceptables, timeout, stmt );
255
256 choose( waitfor, result, stmt );
257
258 return stmt;
259 }
260
261 ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
262 {
263 ObjectDecl * acceptables = ObjectDecl::newObject(
264 namer_acc.newName(),
265 new ArrayType(
266 noQualifiers,
267 new StructInstType(
268 noQualifiers,
269 decl_acceptable
270 ),
271 new ConstantExpr( Constant::from_ulong( count ) ),
272 false,
273 false
274 ),
275 nullptr
276 );
277
278 stmt->push_back( new DeclStmt( noLabels, acceptables) );
279
280 return acceptables;
281 }
282
283 ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
284
285 ObjectDecl * mon = ObjectDecl::newObject(
286 namer_mon.newName(),
287 new ArrayType(
288 noQualifiers,
289 new StructInstType(
290 noQualifiers,
291 decl_monitor
292 ),
293 new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
294 false,
295 false
296 ),
297 new ListInit(
298 map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
299 return new SingleInit( expr );
300 })
301 )
302 );
303
304 stmt->push_back( new DeclStmt( noLabels, mon) );
305
306 return mon;
307 }
308
309 void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
310
311 ObjectDecl * monitors = declMon( clause, stmt );
312
313 Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
314
315 CompoundStmt * compound = new CompoundStmt( noLabels );
316 compound->push_back( makeAccStatement( acceptables, index, "func" , new CastExpr( clause.target.function, fptr_t ) , indexer ) );
317 compound->push_back( makeAccStatement( acceptables, index, "count" , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ) );
318 compound->push_back( makeAccStatement( acceptables, index, "monitors", new VariableExpr( monitors ) , indexer ) );
319 compound->push_back( makeAccStatement( acceptables, index, "is_dtor" , new ConstantExpr( Constant::from_bool( true ) ) , indexer ) );
320
321 stmt->push_back( new IfStmt(
322 noLabels,
323 safeCond( clause.condition ),
324 compound,
325 nullptr
326 ));
327
328 clause.target.function = nullptr;
329 clause.target.arguments.empty();
330 clause.condition = nullptr;
331 }
332
333 Expression * GenerateWaitForPass::init_timeout(
334 Expression *& time,
335 Expression *& time_cond,
336 bool has_else,
337 Expression *& else_cond,
338 CompoundStmt * stmt
339 ) {
340 ObjectDecl * timeout = ObjectDecl::newObject(
341 namer_tim.newName(),
342 new BasicType(
343 noQualifiers,
344 BasicType::LongLongUnsignedInt
345 ),
346 new SingleInit(
347 new ConstantExpr( Constant::from_int( -1 ) )
348 )
349 );
350
351 stmt->push_back( new DeclStmt( noLabels, timeout ) );
352
353 if( time ) {
354 stmt->push_back( new IfStmt(
355 noLabels,
356 safeCond( time_cond ),
357 new ExprStmt(
358 noLabels,
359 makeOpAssign(
360 new VariableExpr( timeout ),
361 time
362 )
363 ),
364 nullptr
365 ));
366
367 time = time_cond = nullptr;
368 }
369
370 if( has_else ) {
371 stmt->push_back( new IfStmt(
372 noLabels,
373 safeCond( else_cond ),
374 new ExprStmt(
375 noLabels,
376 makeOpAssign(
377 new VariableExpr( timeout ),
378 new ConstantExpr( Constant::from_ulong( 0 ) )
379 )
380 ),
381 nullptr
382 ));
383
384 else_cond = nullptr;
385 }
386
387 return new VariableExpr( timeout );
388 }
389
390 Expression * GenerateWaitForPass::call(
391 size_t count,
392 ObjectDecl * acceptables,
393 Expression * timeout,
394 CompoundStmt * stmt
395 ) {
396 ObjectDecl * decl = ObjectDecl::newObject(
397 namer_ret.newName(),
398 new BasicType(
399 noQualifiers,
400 BasicType::LongLongUnsignedInt
401 ),
402 new SingleInit(
403 new UntypedExpr(
404 VariableExpr::functionPointer( decl_waitfor ),
405 {
406 new ConstantExpr( Constant::from_ulong( count ) ),
407 new VariableExpr( acceptables ),
408 timeout
409 }
410 )
411 )
412 );
413
414 stmt->push_back( new DeclStmt( noLabels, decl ) );
415
416 return new VariableExpr( decl );
417 }
418
419 void GenerateWaitForPass::choose(
420 WaitForStmt * waitfor,
421 Expression * result,
422 CompoundStmt * stmt
423 ) {
424 SwitchStmt * swtch = new SwitchStmt(
425 noLabels,
426 result,
427 std::list<Statement *>()
428 );
429
430 unsigned long i = 0;
431 for( auto & clause : waitfor->clauses ) {
432 swtch->statements.push_back(
433 new CaseStmt(
434 noLabels,
435 new ConstantExpr( Constant::from_ulong( i++ ) ),
436 {
437 clause.statement,
438 new BranchStmt(
439 noLabels,
440 "",
441 BranchStmt::Break
442 )
443 }
444 )
445 );
446 }
447
448 if(waitfor->timeout.statement) {
449 swtch->statements.push_back(
450 new CaseStmt(
451 noLabels,
452 new ConstantExpr( Constant::from_ulong( i++ ) ),
453 {
454 waitfor->timeout.statement,
455 new BranchStmt(
456 noLabels,
457 "",
458 BranchStmt::Break
459 )
460 }
461 )
462 );
463 }
464
465 if(waitfor->orelse.statement) {
466 swtch->statements.push_back(
467 new CaseStmt(
468 noLabels,
469 new ConstantExpr( Constant::from_ulong( i++ ) ),
470 {
471 waitfor->orelse.statement,
472 new BranchStmt(
473 noLabels,
474 "",
475 BranchStmt::Break
476 )
477 }
478 )
479 );
480 }
481
482 stmt->push_back( swtch );
483 }
484};
485
486// Local Variables: //
487// mode: c //
488// tab-width: 4 //
489// End: //
Note: See TracBrowser for help on using the repository browser.