source: src/Concurrency/Keywords.cc@ 0428aad

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

Implemented thread keyword

  • Property mode set to 100644
File size: 16.4 KB
Line 
1// -*- Mode: CPP -*-
2//
3// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
4//
5// The contents of this file are covered under the licence agreement in the
6// file "LICENCE" distributed with Cforall.
7//
8// Keywords.cc --
9//
10// Author : Thierry Delisle
11// Created On : Mon Mar 13 12:41:22 2017
12// Last Modified By :
13// Last Modified On :
14// Update Count : 3
15//
16
17#include "Concurrency/Keywords.h"
18
19#include "InitTweak/InitTweak.h"
20#include "SymTab/AddVisit.h"
21#include "SynTree/Declaration.h"
22#include "SynTree/Expression.h"
23#include "SynTree/Initializer.h"
24#include "SynTree/Statement.h"
25#include "SynTree/Type.h"
26#include "SynTree/Visitor.h"
27
28namespace Concurrency {
29
30 namespace {
31 const std::list<Label> noLabels;
32 const std::list< Attribute * > noAttributes;
33 Type::StorageClasses noStorage;
34 Type::Qualifiers noQualifiers;
35 }
36
37 //=============================================================================================
38 // Visitors declaration
39 //=============================================================================================
40
41 //-----------------------------------------------------------------------------
42 //Handles sue type declarations :
43 // sue MyType { struct MyType {
44 // int data; int data;
45 // a_struct_t more_data; a_struct_t more_data;
46 // => NewField_t newField;
47 // }; };
48 // static inline NewField_t * getter_name( MyType * this ) { return &this->newField; }
49 //
50 class ConcurrentSueKeyword : public Visitor {
51 protected:
52 template< typename Visitor >
53 friend void SymTab::acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
54 public:
55
56 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main ) :
57 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ) {}
58
59 virtual ~ConcurrentSueKeyword() {}
60
61 using Visitor::visit;
62 virtual void visit( StructDecl * decl ) override final;
63
64 void handle( StructDecl * );
65 FunctionDecl * forwardDeclare( StructDecl * );
66 ObjectDecl * addField( StructDecl * );
67 void addRoutines( StructDecl *, ObjectDecl *, FunctionDecl * );
68
69 virtual bool is_target( StructDecl * decl ) = 0;
70
71 private:
72 const std::string type_name;
73 const std::string field_name;
74 const std::string getter_name;
75 const std::string context_error;
76 bool needs_main;
77
78 std::list< Declaration * > declsToAdd, declsToAddAfter;
79 StructDecl* type_decl = nullptr;
80 };
81
82
83 //-----------------------------------------------------------------------------
84 //Handles thread type declarations :
85 // thread Mythread { struct MyThread {
86 // int data; int data;
87 // a_struct_t more_data; a_struct_t more_data;
88 // => thread_desc __thrd_d;
89 // }; };
90 // static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
91 //
92 class ThreadKeyword final : public ConcurrentSueKeyword {
93 public:
94
95 ThreadKeyword() : ConcurrentSueKeyword(
96 "thread_desc",
97 "__thrd",
98 "get_thread",
99 "thread keyword requires threads to be in scope, add #include <thread>",
100 true
101 )
102 {}
103
104 virtual ~ThreadKeyword() {}
105
106 virtual bool is_target( StructDecl * decl ) override final { return decl->is_thread(); }
107
108 static void implement( std::list< Declaration * > & translationUnit ) {
109 ThreadKeyword impl;
110 SymTab::acceptAndAdd( translationUnit, impl );
111 }
112 };
113
114 //-----------------------------------------------------------------------------
115 //Handles coroutine type declarations :
116 // coroutine MyCoroutine { struct MyCoroutine {
117 // int data; int data;
118 // a_struct_t more_data; a_struct_t more_data;
119 // => coroutine_desc __cor_d;
120 // }; };
121 // static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
122 //
123 class CoroutineKeyword final : public ConcurrentSueKeyword {
124 public:
125
126 CoroutineKeyword() : ConcurrentSueKeyword(
127 "coroutine_desc",
128 "__cor",
129 "get_coroutine",
130 "coroutine keyword requires coroutines to be in scope, add #include <coroutine>",
131 true
132 )
133 {}
134
135 virtual ~CoroutineKeyword() {}
136
137 virtual bool is_target( StructDecl * decl ) override final { return decl->is_coroutine(); }
138
139 static void implement( std::list< Declaration * > & translationUnit ) {
140 CoroutineKeyword impl;
141 SymTab::acceptAndAdd( translationUnit, impl );
142 }
143 };
144
145 //-----------------------------------------------------------------------------
146 //Handles monitor type declarations :
147 // monitor MyMonitor { struct MyMonitor {
148 // int data; int data;
149 // a_struct_t more_data; a_struct_t more_data;
150 // => monitor_desc __mon_d;
151 // }; };
152 // static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
153 //
154 class MonitorKeyword final : public ConcurrentSueKeyword {
155 public:
156
157 MonitorKeyword() : ConcurrentSueKeyword(
158 "monitor_desc",
159 "__mon",
160 "get_monitor",
161 "monitor keyword requires monitors to be in scope, add #include <monitor>",
162 false
163 )
164 {}
165
166 virtual ~MonitorKeyword() {}
167
168 virtual bool is_target( StructDecl * decl ) override final { return decl->is_monitor(); }
169
170 static void implement( std::list< Declaration * > & translationUnit ) {
171 MonitorKeyword impl;
172 SymTab::acceptAndAdd( translationUnit, impl );
173 }
174 };
175
176 //-----------------------------------------------------------------------------
177 //Handles mutex routines definitions :
178 // void foo( A * mutex a, B * mutex b, int i ) { void foo( A * a, B * b, int i ) {
179 // monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
180 // monitor_guard_t __guard = { __monitors, 2 };
181 // /*Some code*/ => /*Some code*/
182 // } }
183 //
184 class MutexKeyword final : public Visitor {
185 public:
186
187 using Visitor::visit;
188 virtual void visit( FunctionDecl * decl ) override final;
189 virtual void visit( StructDecl * decl ) override final;
190
191 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
192 void validate( DeclarationWithType * );
193 void addStatments( CompoundStmt *, const std::list<DeclarationWithType * > &);
194
195 static void implement( std::list< Declaration * > & translationUnit ) {
196 MutexKeyword impl;
197 acceptAll( translationUnit, impl );
198 }
199
200 private:
201 StructDecl* monitor_decl = nullptr;
202 StructDecl* guard_decl = nullptr;
203 };
204
205 //-----------------------------------------------------------------------------
206 //Handles mutex routines definitions :
207 // void foo( A * mutex a, B * mutex b, int i ) { void foo( A * a, B * b, int i ) {
208 // monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
209 // monitor_guard_t __guard = { __monitors, 2 };
210 // /*Some code*/ => /*Some code*/
211 // } }
212 //
213 class ThreadStarter final : public Visitor {
214 public:
215
216 using Visitor::visit;
217 virtual void visit( FunctionDecl * decl ) override final;
218
219 void addStartStatement( FunctionDecl * decl, DeclarationWithType * param );
220
221 static void implement( std::list< Declaration * > & translationUnit ) {
222 ThreadStarter impl;
223 acceptAll( translationUnit, impl );
224 }
225 };
226
227 //=============================================================================================
228 // General entry routine
229 //=============================================================================================
230 void applyKeywords( std::list< Declaration * > & translationUnit ) {
231 ThreadKeyword ::implement( translationUnit );
232 CoroutineKeyword ::implement( translationUnit );
233 MonitorKeyword ::implement( translationUnit );
234 }
235
236 void implementMutexFuncs( std::list< Declaration * > & translationUnit ) {
237 MutexKeyword ::implement( translationUnit );
238 }
239
240 void implementThreadStarter( std::list< Declaration * > & translationUnit ) {
241 ThreadStarter ::implement( translationUnit );
242 }
243
244 //=============================================================================================
245 // Generic keyword implementation
246 //=============================================================================================
247 void ConcurrentSueKeyword::visit(StructDecl * decl) {
248 if( decl->get_name() == type_name ) {
249 assert( !type_decl );
250 type_decl = decl;
251 }
252 else if ( is_target(decl) ) {
253 handle( decl );
254 }
255
256 }
257
258 void ConcurrentSueKeyword::handle( StructDecl * decl ) {
259 if( ! decl->has_body() ) return;
260
261 if( !type_decl ) throw SemanticError( context_error, decl );
262
263 FunctionDecl * func = forwardDeclare( decl );
264 ObjectDecl * field = addField( decl );
265 addRoutines( decl, field, func );
266 }
267
268 FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) {
269
270 StructDecl * forward = decl->clone();
271 forward->set_body( false );
272 deleteAll( forward->get_members() );
273 forward->get_members().clear();
274
275 FunctionType * get_type = new FunctionType( noQualifiers, false );
276 ObjectDecl * this_decl = new ObjectDecl(
277 "this",
278 noStorage,
279 LinkageSpec::Cforall,
280 nullptr,
281 new PointerType(
282 noQualifiers,
283 new StructInstType(
284 noQualifiers,
285 decl
286 )
287 ),
288 nullptr
289 );
290
291 get_type->get_parameters().push_back( this_decl );
292 get_type->get_returnVals().push_back(
293 new ObjectDecl(
294 "ret",
295 noStorage,
296 LinkageSpec::Cforall,
297 nullptr,
298 new PointerType(
299 noQualifiers,
300 new StructInstType(
301 noQualifiers,
302 type_decl
303 )
304 ),
305 nullptr
306 )
307 );
308
309 FunctionDecl * get_decl = new FunctionDecl(
310 getter_name,
311 Type::Static,
312 LinkageSpec::Cforall,
313 get_type,
314 nullptr,
315 noAttributes,
316 Type::Inline
317 );
318
319 FunctionDecl * main_decl = nullptr;
320
321 if( needs_main ) {
322 FunctionType * main_type = new FunctionType( noQualifiers, false );
323
324 main_type->get_parameters().push_back( this_decl->clone() );
325
326 main_decl = new FunctionDecl(
327 "main",
328 noStorage,
329 LinkageSpec::Cforall,
330 main_type,
331 nullptr
332 );
333 }
334
335 declsToAdd.push_back( forward );
336 if( needs_main ) declsToAdd.push_back( main_decl );
337 declsToAdd.push_back( get_decl );
338
339 return get_decl;
340 }
341
342 ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) {
343 ObjectDecl * field = new ObjectDecl(
344 field_name,
345 noStorage,
346 LinkageSpec::Cforall,
347 nullptr,
348 new StructInstType(
349 noQualifiers,
350 type_decl
351 ),
352 nullptr
353 );
354
355 decl->get_members().push_back( field );
356
357 return field;
358 }
359
360 void ConcurrentSueKeyword::addRoutines( StructDecl * decl, ObjectDecl * field, FunctionDecl * func ) {
361 CompoundStmt * statement = new CompoundStmt( noLabels );
362 statement->push_back(
363 new ReturnStmt(
364 noLabels,
365 new AddressExpr(
366 new MemberExpr(
367 field,
368 UntypedExpr::createDeref( new VariableExpr( func->get_functionType()->get_parameters().front() ) )
369 )
370 )
371 )
372 );
373
374 FunctionDecl * get_decl = func->clone();
375
376 get_decl->set_statements( statement );
377
378 declsToAddAfter.push_back( get_decl );
379
380 // get_decl->fixUniqueId();
381 }
382
383 //=============================================================================================
384 // Mutex keyword implementation
385 //=============================================================================================
386 void MutexKeyword::visit(FunctionDecl* decl) {
387 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
388 if( mutexArgs.empty() ) return;
389
390 for(auto arg : mutexArgs) {
391 validate( arg );
392 }
393
394 CompoundStmt* body = decl->get_statements();
395 if( ! body ) return;
396
397 if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
398 if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
399
400 addStatments( body, mutexArgs );
401 }
402
403 void MutexKeyword::visit(StructDecl* decl) {
404 if( decl->get_name() == "monitor_desc" ) {
405 assert( !monitor_decl );
406 monitor_decl = decl;
407 }
408 else if( decl->get_name() == "monitor_guard_t" ) {
409 assert( !guard_decl );
410 guard_decl = decl;
411 }
412 }
413
414 std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
415 std::list<DeclarationWithType*> mutexArgs;
416
417 for( auto arg : decl->get_functionType()->get_parameters()) {
418 //Find mutex arguments
419 Type* ty = arg->get_type();
420 if( ! ty->get_mutex() ) continue;
421
422 //Append it to the list
423 mutexArgs.push_back( arg );
424 }
425
426 return mutexArgs;
427 }
428
429 void MutexKeyword::validate( DeclarationWithType * arg ) {
430 Type* ty = arg->get_type();
431
432 //Makes sure it's not a copy
433 PointerType* pty = dynamic_cast< PointerType * >( ty );
434 if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );
435
436 //Make sure the we are pointing directly to a type
437 Type* base = pty->get_base();
438 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
439
440 //Make sure that typed isn't mutex
441 if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
442 }
443
444 void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
445 ObjectDecl * monitors = new ObjectDecl(
446 "__monitors",
447 noStorage,
448 LinkageSpec::Cforall,
449 nullptr,
450 new ArrayType(
451 noQualifiers,
452 new PointerType(
453 noQualifiers,
454 new StructInstType(
455 noQualifiers,
456 monitor_decl
457 )
458 ),
459 new ConstantExpr( Constant::from_ulong( args.size() ) ),
460 false,
461 false
462 ),
463 new ListInit(
464 map_range < std::list<Initializer*> > ( args, [this](DeclarationWithType * var ){
465 Type * type = var->get_type()->clone();
466 type->set_mutex( false );
467 return new SingleInit( new UntypedExpr(
468 new NameExpr( "get_monitor" ),
469 { new CastExpr( new VariableExpr( var ), type ) }
470 ) );
471 })
472 )
473 );
474
475 //in reverse order :
476 // monitor_guard_t __guard = { __monitors, # };
477 body->push_front(
478 new DeclStmt( noLabels, new ObjectDecl(
479 "__guard",
480 noStorage,
481 LinkageSpec::Cforall,
482 nullptr,
483 new StructInstType(
484 noQualifiers,
485 guard_decl
486 ),
487 new ListInit(
488 {
489 new SingleInit( new VariableExpr( monitors ) ),
490 new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
491 },
492 noDesignators,
493 true
494 )
495 ))
496 );
497
498 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
499 body->push_front( new DeclStmt( noLabels, monitors) );
500 }
501
502 //=============================================================================================
503 // General entry routine
504 //=============================================================================================
505 void ThreadStarter::visit(FunctionDecl * decl) {
506 if( ! InitTweak::isConstructor(decl->get_name()) ) return;
507
508 DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
509 auto ptr = dynamic_cast< PointerType * >( param->get_type() );
510 // if( ptr ) std::cerr << "FRED1" << std::endl;
511 auto type = dynamic_cast< StructInstType * >( ptr->get_base() );
512 // if( type ) std::cerr << "FRED2" << std::endl;
513 if( type && type->get_baseStruct()->is_thread() ) {
514 addStartStatement( decl, param );
515 }
516 }
517
518 void ThreadStarter::addStartStatement( FunctionDecl * decl, DeclarationWithType * param ) {
519 CompoundStmt * stmt = decl->get_statements();
520
521 if( ! stmt ) return;
522
523 stmt->push_back(
524 new ExprStmt(
525 noLabels,
526 new UntypedExpr(
527 new NameExpr( "__thrd_start" ),
528 { new VariableExpr( param ) }
529 )
530 )
531 );
532 }
533};
Note: See TracBrowser for help on using the repository browser.