source: src/Concurrency/Keywords.cc@ b1e63ac5

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 b1e63ac5 was b1e63ac5, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Merge branch 'master' into references

  • 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( 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 Visitor::visit(decl);
249 if( decl->get_name() == type_name && decl->has_body() ) {
250 assert( !type_decl );
251 type_decl = decl;
252 }
253 else if ( is_target(decl) ) {
254 handle( decl );
255 }
256
257 }
258
259 void ConcurrentSueKeyword::handle( StructDecl * decl ) {
260 if( ! decl->has_body() ) return;
261
262 if( !type_decl ) throw SemanticError( context_error, decl );
263
264 FunctionDecl * func = forwardDeclare( decl );
265 ObjectDecl * field = addField( decl );
266 addRoutines( field, func );
267 }
268
269 FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) {
270
271 StructDecl * forward = decl->clone();
272 forward->set_body( false );
273 deleteAll( forward->get_members() );
274 forward->get_members().clear();
275
276 FunctionType * get_type = new FunctionType( noQualifiers, false );
277 ObjectDecl * this_decl = new ObjectDecl(
278 "this",
279 noStorage,
280 LinkageSpec::Cforall,
281 nullptr,
282 new PointerType(
283 noQualifiers,
284 new StructInstType(
285 noQualifiers,
286 decl
287 )
288 ),
289 nullptr
290 );
291
292 get_type->get_parameters().push_back( this_decl );
293 get_type->get_returnVals().push_back(
294 new ObjectDecl(
295 "ret",
296 noStorage,
297 LinkageSpec::Cforall,
298 nullptr,
299 new PointerType(
300 noQualifiers,
301 new StructInstType(
302 noQualifiers,
303 type_decl
304 )
305 ),
306 nullptr
307 )
308 );
309
310 FunctionDecl * get_decl = new FunctionDecl(
311 getter_name,
312 Type::Static,
313 LinkageSpec::Cforall,
314 get_type,
315 nullptr,
316 noAttributes,
317 Type::Inline
318 );
319
320 FunctionDecl * main_decl = nullptr;
321
322 if( needs_main ) {
323 FunctionType * main_type = new FunctionType( noQualifiers, false );
324
325 main_type->get_parameters().push_back( this_decl->clone() );
326
327 main_decl = new FunctionDecl(
328 "main",
329 noStorage,
330 LinkageSpec::Cforall,
331 main_type,
332 nullptr
333 );
334 }
335
336 declsToAdd.push_back( forward );
337 if( needs_main ) declsToAdd.push_back( main_decl );
338 declsToAdd.push_back( get_decl );
339
340 return get_decl;
341 }
342
343 ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) {
344 ObjectDecl * field = new ObjectDecl(
345 field_name,
346 noStorage,
347 LinkageSpec::Cforall,
348 nullptr,
349 new StructInstType(
350 noQualifiers,
351 type_decl
352 ),
353 nullptr
354 );
355
356 decl->get_members().push_back( field );
357
358 return field;
359 }
360
361 void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
362 CompoundStmt * statement = new CompoundStmt( noLabels );
363 statement->push_back(
364 new ReturnStmt(
365 noLabels,
366 new AddressExpr(
367 new MemberExpr(
368 field,
369 UntypedExpr::createDeref( new VariableExpr( func->get_functionType()->get_parameters().front() ) )
370 )
371 )
372 )
373 );
374
375 FunctionDecl * get_decl = func->clone();
376
377 get_decl->set_statements( statement );
378
379 declsToAddAfter.push_back( get_decl );
380
381 // get_decl->fixUniqueId();
382 }
383
384 //=============================================================================================
385 // Mutex keyword implementation
386 //=============================================================================================
387 void MutexKeyword::visit(FunctionDecl* decl) {
388 Visitor::visit(decl);
389
390 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
391 if( mutexArgs.empty() ) return;
392
393 for(auto arg : mutexArgs) {
394 validate( arg );
395 }
396
397 CompoundStmt* body = decl->get_statements();
398 if( ! body ) return;
399
400 if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
401 if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
402
403 addStatments( body, mutexArgs );
404 }
405
406 void MutexKeyword::visit(StructDecl* decl) {
407 Visitor::visit(decl);
408
409 if( decl->get_name() == "monitor_desc" ) {
410 assert( !monitor_decl );
411 monitor_decl = decl;
412 }
413 else if( decl->get_name() == "monitor_guard_t" ) {
414 assert( !guard_decl );
415 guard_decl = decl;
416 }
417 }
418
419 std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
420 std::list<DeclarationWithType*> mutexArgs;
421
422 for( auto arg : decl->get_functionType()->get_parameters()) {
423 //Find mutex arguments
424 Type* ty = arg->get_type();
425 if( ! ty->get_mutex() ) continue;
426
427 //Append it to the list
428 mutexArgs.push_back( arg );
429 }
430
431 return mutexArgs;
432 }
433
434 void MutexKeyword::validate( DeclarationWithType * arg ) {
435 Type* ty = arg->get_type();
436
437 //Makes sure it's not a copy
438 PointerType* pty = dynamic_cast< PointerType * >( ty );
439 if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );
440
441 //Make sure the we are pointing directly to a type
442 Type* base = pty->get_base();
443 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
444
445 //Make sure that typed isn't mutex
446 if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
447 }
448
449 void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
450 ObjectDecl * monitors = new ObjectDecl(
451 "__monitors",
452 noStorage,
453 LinkageSpec::Cforall,
454 nullptr,
455 new ArrayType(
456 noQualifiers,
457 new PointerType(
458 noQualifiers,
459 new StructInstType(
460 noQualifiers,
461 monitor_decl
462 )
463 ),
464 new ConstantExpr( Constant::from_ulong( args.size() ) ),
465 false,
466 false
467 ),
468 new ListInit(
469 map_range < std::list<Initializer*> > ( args, [this](DeclarationWithType * var ){
470 Type * type = var->get_type()->clone();
471 type->set_mutex( false );
472 return new SingleInit( new UntypedExpr(
473 new NameExpr( "get_monitor" ),
474 { new CastExpr( new VariableExpr( var ), type ) }
475 ) );
476 })
477 )
478 );
479
480 //in reverse order :
481 // monitor_guard_t __guard = { __monitors, # };
482 body->push_front(
483 new DeclStmt( noLabels, new ObjectDecl(
484 "__guard",
485 noStorage,
486 LinkageSpec::Cforall,
487 nullptr,
488 new StructInstType(
489 noQualifiers,
490 guard_decl
491 ),
492 new ListInit(
493 {
494 new SingleInit( new VariableExpr( monitors ) ),
495 new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
496 },
497 noDesignators,
498 true
499 )
500 ))
501 );
502
503 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
504 body->push_front( new DeclStmt( noLabels, monitors) );
505 }
506
507 //=============================================================================================
508 // General entry routine
509 //=============================================================================================
510 void ThreadStarter::visit(FunctionDecl * decl) {
511 Visitor::visit(decl);
512
513 if( ! InitTweak::isConstructor(decl->get_name()) ) return;
514
515 DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
516 auto type = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
517 // if( type ) std::cerr << "FRED2" << std::endl;
518 if( type && type->get_baseStruct()->is_thread() ) {
519 addStartStatement( decl, param );
520 }
521 }
522
523 void ThreadStarter::addStartStatement( FunctionDecl * decl, DeclarationWithType * param ) {
524 CompoundStmt * stmt = decl->get_statements();
525
526 if( ! stmt ) return;
527
528 stmt->push_back(
529 new ExprStmt(
530 noLabels,
531 new UntypedExpr(
532 new NameExpr( "__thrd_start" ),
533 { new VariableExpr( param ) }
534 )
535 )
536 );
537 }
538};
Note: See TracBrowser for help on using the repository browser.