source: src/Concurrency/Waitfor.cc@ acdfb45

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

Renamed safe_dynamic_cast to strict_dynamic_cast

  • Property mode set to 100644
File size: 11.0 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 "SymTab/AddVisit.h" // for acceptAndAdd
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 WithStmtsToAdd {
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();
132 void choose();
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 DeclarationWithType * decl_m_func = nullptr;
145 DeclarationWithType * decl_m_count = nullptr;
146 DeclarationWithType * decl_m_monitors = nullptr;
147 DeclarationWithType * decl_m_isdtor = nullptr;
148
149 static std::unique_ptr< Type > generic_func;
150
151 UniqueName namer_mon = "__monitors_"s;
152 UniqueName namer_acc = "__acceptables_"s;
153 UniqueName namer_tim = "__timeout_"s;
154 };
155
156 //=============================================================================================
157 // General entry routine
158 //=============================================================================================
159 void generateWaitFor( std::list< Declaration * > & translationUnit ) {
160 GenerateWaitForPass ::implement( translationUnit );
161 }
162
163 //=============================================================================================
164 // Generic helper routine
165 //=============================================================================================
166
167 namespace {
168 Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
169 return new ApplicationExpr(
170 new NameExpr( "?[?]" ),
171 {
172 new VariableExpr( array ),
173 new ConstantExpr( Constant::from_ulong( index ) )
174 }
175 );
176 }
177
178 Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
179 return new ApplicationExpr(
180 new NameExpr( "?=?" ),
181 { lhs, rhs }
182 );
183 }
184
185 Expression * makeOpMember( Expression * sue, DeclarationWithType * mem ) {
186 return new MemberExpr( mem, sue );
187 }
188
189 Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, DeclarationWithType * member, Expression * value ) {
190 return new ExprStmt(
191 noLabels,
192 makeOpAssign(
193 makeOpMember(
194 makeOpIndex(
195 object,
196 index
197 ),
198 member
199 ),
200 value
201 )
202 );
203 }
204
205 Expression * safeCond( Expression * expr, bool ifnull = true ) {
206 if( expr ) return expr;
207
208 return new ConstantExpr( Constant::from_bool( ifnull ) );
209 }
210 };
211
212
213 //=============================================================================================
214 // Generate waitfor implementation
215 //=============================================================================================
216
217 void GenerateWaitForPass::premutate( FunctionDecl * decl) {
218 if( decl->name != "__accept_internal" ) return;
219
220 decl_waitfor = decl;
221 }
222
223 void GenerateWaitForPass::premutate( StructDecl * decl ) {
224 if( ! decl->body ) return;
225
226 if( decl->name == "__acceptable_t" ) {
227 assert( !decl_acceptable );
228 decl_acceptable = decl;
229 for( Declaration * field : decl_acceptable->members ) {
230 if( field->name == "func" ) decl_m_func = strict_dynamic_cast< DeclarationWithType * >( field );
231 else if( field->name == "count" ) decl_m_count = strict_dynamic_cast< DeclarationWithType * >( field );
232 else if( field->name == "monitor" ) decl_m_monitors = strict_dynamic_cast< DeclarationWithType * >( field );
233 else if( field->name == "is_dtor" ) decl_m_isdtor = strict_dynamic_cast< DeclarationWithType * >( field );
234 }
235
236 }
237 else if( decl->name == "monitor_desc" ) {
238 assert( !decl_monitor );
239 decl_monitor = decl;
240 }
241 }
242
243 Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
244 return waitfor;
245
246 if( !decl_monitor || !decl_acceptable ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
247
248 CompoundStmt * stmt = new CompoundStmt( noLabels );
249
250 ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
251
252 int index = 0;
253 for( auto & clause : waitfor->clauses ) {
254 init( acceptables, index, clause, stmt );
255
256 index++;
257 }
258
259 Expression * timeout = init_timeout(
260 waitfor->timeout.time,
261 waitfor->timeout.condition,
262 waitfor->orelse .statement,
263 waitfor->orelse .condition,
264 stmt
265 );
266
267 // Expression * result = call( acceptables, timeout, orelse, stmt );
268
269 // choose( waitfor, result );
270
271 return stmt;
272 }
273
274 ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
275 {
276 ObjectDecl * acceptables = new ObjectDecl(
277 namer_acc.newName(),
278 noStorage,
279 LinkageSpec::Cforall,
280 nullptr,
281 new ArrayType(
282 noQualifiers,
283 new StructInstType(
284 noQualifiers,
285 decl_acceptable
286 ),
287 new ConstantExpr( Constant::from_ulong( count ) ),
288 false,
289 false
290 ),
291 nullptr
292 );
293
294 stmt->push_back( new DeclStmt( noLabels, acceptables) );
295
296 return acceptables;
297 }
298
299 ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
300
301 ObjectDecl * mon = new ObjectDecl(
302 namer_mon.newName(),
303 noStorage,
304 LinkageSpec::Cforall,
305 nullptr,
306 new ArrayType(
307 noQualifiers,
308 new StructInstType(
309 noQualifiers,
310 decl_monitor
311 ),
312 new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
313 false,
314 false
315 ),
316 new ListInit(
317 map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
318 return new SingleInit( expr );
319 })
320 )
321 );
322
323 stmt->push_back( new DeclStmt( noLabels, mon) );
324
325 return mon;
326 }
327
328 void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
329
330 ObjectDecl * monitors = declMon( clause, stmt );
331
332 CompoundStmt * compound = new CompoundStmt( noLabels );
333 compound->push_back( makeAccStatement( acceptables, index, decl_m_func , clause.target.function ) );
334 compound->push_back( makeAccStatement( acceptables, index, decl_m_count , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ) ) );
335 compound->push_back( makeAccStatement( acceptables, index, decl_m_monitors, new VariableExpr( monitors ) ) );
336 compound->push_back( makeAccStatement( acceptables, index, decl_m_isdtor , new ConstantExpr( Constant::from_bool( true ) ) ) );
337
338 stmt->push_back( new IfStmt(
339 noLabels,
340 safeCond( clause.condition ),
341 compound,
342 nullptr
343 ));
344
345 clause.target.function = nullptr;
346 clause.target.arguments.empty();
347 clause.condition = nullptr;
348 }
349
350 Expression * GenerateWaitForPass::init_timeout(
351 Expression *& time,
352 Expression *& time_cond,
353 bool has_else,
354 Expression *& else_cond,
355 CompoundStmt * stmt
356 ) {
357 ObjectDecl * timeout = new ObjectDecl(
358 namer_tim.newName(),
359 noStorage,
360 LinkageSpec::Cforall,
361 nullptr,
362 new BasicType(
363 noQualifiers,
364 BasicType::LongLongUnsignedInt
365 ),
366 new SingleInit(
367 new ConstantExpr( Constant::from_int( -1 ) )
368 )
369 );
370
371 stmt->push_back( new DeclStmt( noLabels, timeout ) );
372
373 if( time ) {
374 stmt->push_back( new IfStmt(
375 noLabels,
376 safeCond( else_cond ),
377 new ExprStmt(
378 noLabels,
379 makeOpAssign(
380 new VariableExpr( timeout ),
381 time
382 )
383 ),
384 nullptr
385 ));
386
387 time = time_cond = nullptr;
388 }
389
390 if( has_else ) {
391 stmt->push_back( new IfStmt(
392 noLabels,
393 safeCond( else_cond ),
394 new ExprStmt(
395 noLabels,
396 makeOpAssign(
397 new VariableExpr( timeout ),
398 new ConstantExpr( Constant::from_ulong( 0 ) )
399 )
400 ),
401 nullptr
402 ));
403
404 else_cond = nullptr;
405 }
406
407 return new VariableExpr( timeout );
408 }
409};
410
411// Local Variables: //
412// mode: c //
413// tab-width: 4 //
414// End: //
Note: See TracBrowser for help on using the repository browser.