source: src/Concurrency/Keywords.cc@ 6a8df56

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

Remove unused AddVisit.h

  • Property mode set to 100644
File size: 20.2 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// Keywords.cc --
8//
9// Author : Thierry Delisle
10// Created On : Mon Mar 13 12:41:22 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
21#include "Common/PassVisitor.h" // for PassVisitor
22#include "Common/SemanticError.h" // for SemanticError
23#include "Common/utility.h" // for deleteAll, map_range
24#include "CodeGen/OperatorTable.h" // for isConstructor
25#include "InitTweak/InitTweak.h" // for getPointerBase
26#include "Parser/LinkageSpec.h" // for Cforall
27#include "SynTree/Constant.h" // for Constant
28#include "SynTree/Declaration.h" // for StructDecl, FunctionDecl, ObjectDecl
29#include "SynTree/Expression.h" // for VariableExpr, ConstantExpr, Untype...
30#include "SynTree/Initializer.h" // for SingleInit, ListInit, Initializer ...
31#include "SynTree/Label.h" // for Label
32#include "SynTree/Statement.h" // for CompoundStmt, DeclStmt, ExprStmt
33#include "SynTree/Type.h" // for StructInstType, Type, PointerType
34#include "SynTree/Visitor.h" // for Visitor, acceptAll
35
36class Attribute;
37
38namespace Concurrency {
39 //=============================================================================================
40 // Pass declarations
41 //=============================================================================================
42
43 //-----------------------------------------------------------------------------
44 //Handles sue type declarations :
45 // sue MyType { struct MyType {
46 // int data; int data;
47 // a_struct_t more_data; a_struct_t more_data;
48 // => NewField_t newField;
49 // }; };
50 // static inline NewField_t * getter_name( MyType * this ) { return &this->newField; }
51 //
52 class ConcurrentSueKeyword : public WithDeclsToAdd {
53 public:
54
55 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main ) :
56 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ) {}
57
58 virtual ~ConcurrentSueKeyword() {}
59
60 void postvisit( StructDecl * decl );
61
62 void handle( StructDecl * );
63 FunctionDecl * forwardDeclare( StructDecl * );
64 ObjectDecl * addField( StructDecl * );
65 void addRoutines( ObjectDecl *, FunctionDecl * );
66
67 virtual bool is_target( StructDecl * decl ) = 0;
68
69 private:
70 const std::string type_name;
71 const std::string field_name;
72 const std::string getter_name;
73 const std::string context_error;
74 bool needs_main;
75
76 StructDecl* type_decl = nullptr;
77 };
78
79
80 //-----------------------------------------------------------------------------
81 //Handles thread type declarations :
82 // thread Mythread { struct MyThread {
83 // int data; int data;
84 // a_struct_t more_data; a_struct_t more_data;
85 // => thread_desc __thrd_d;
86 // }; };
87 // static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
88 //
89 class ThreadKeyword final : public ConcurrentSueKeyword {
90 public:
91
92 ThreadKeyword() : ConcurrentSueKeyword(
93 "thread_desc",
94 "__thrd",
95 "get_thread",
96 "thread keyword requires threads to be in scope, add #include <thread>",
97 true
98 )
99 {}
100
101 virtual ~ThreadKeyword() {}
102
103 virtual bool is_target( StructDecl * decl ) override final { return decl->is_thread(); }
104
105 static void implement( std::list< Declaration * > & translationUnit ) {
106 PassVisitor< ThreadKeyword > impl;
107 acceptAll( translationUnit, impl );
108 }
109 };
110
111 //-----------------------------------------------------------------------------
112 //Handles coroutine type declarations :
113 // coroutine MyCoroutine { struct MyCoroutine {
114 // int data; int data;
115 // a_struct_t more_data; a_struct_t more_data;
116 // => coroutine_desc __cor_d;
117 // }; };
118 // static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
119 //
120 class CoroutineKeyword final : public ConcurrentSueKeyword {
121 public:
122
123 CoroutineKeyword() : ConcurrentSueKeyword(
124 "coroutine_desc",
125 "__cor",
126 "get_coroutine",
127 "coroutine keyword requires coroutines to be in scope, add #include <coroutine>",
128 true
129 )
130 {}
131
132 virtual ~CoroutineKeyword() {}
133
134 virtual bool is_target( StructDecl * decl ) override final { return decl->is_coroutine(); }
135
136 static void implement( std::list< Declaration * > & translationUnit ) {
137 PassVisitor< CoroutineKeyword > impl;
138 acceptAll( translationUnit, impl );
139 }
140 };
141
142 //-----------------------------------------------------------------------------
143 //Handles monitor type declarations :
144 // monitor MyMonitor { struct MyMonitor {
145 // int data; int data;
146 // a_struct_t more_data; a_struct_t more_data;
147 // => monitor_desc __mon_d;
148 // }; };
149 // static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
150 //
151 class MonitorKeyword final : public ConcurrentSueKeyword {
152 public:
153
154 MonitorKeyword() : ConcurrentSueKeyword(
155 "monitor_desc",
156 "__mon",
157 "get_monitor",
158 "monitor keyword requires monitors to be in scope, add #include <monitor>",
159 false
160 )
161 {}
162
163 virtual ~MonitorKeyword() {}
164
165 virtual bool is_target( StructDecl * decl ) override final { return decl->is_monitor(); }
166
167 static void implement( std::list< Declaration * > & translationUnit ) {
168 PassVisitor< MonitorKeyword > impl;
169 acceptAll( translationUnit, impl );
170 }
171 };
172
173 //-----------------------------------------------------------------------------
174 //Handles mutex routines definitions :
175 // void foo( A * mutex a, B * mutex b, int i ) { void foo( A * a, B * b, int i ) {
176 // monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
177 // monitor_guard_t __guard = { __monitors, 2 };
178 // /*Some code*/ => /*Some code*/
179 // } }
180 //
181 class MutexKeyword final {
182 public:
183
184 void postvisit( FunctionDecl * decl );
185 void postvisit( StructDecl * decl );
186
187 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
188 void validate( DeclarationWithType * );
189 void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
190 void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
191
192 static void implement( std::list< Declaration * > & translationUnit ) {
193 PassVisitor< MutexKeyword > impl;
194 acceptAll( translationUnit, impl );
195 }
196
197 private:
198 StructDecl* monitor_decl = nullptr;
199 StructDecl* guard_decl = nullptr;
200 StructDecl* dtor_guard_decl = nullptr;
201
202 static std::unique_ptr< Type > generic_func;
203 };
204
205 std::unique_ptr< Type > MutexKeyword::generic_func = std::unique_ptr< Type >(
206 new FunctionType(
207 noQualifiers,
208 true
209 )
210 );
211
212 //-----------------------------------------------------------------------------
213 //Handles mutex routines definitions :
214 // void foo( A * mutex a, B * mutex b, int i ) { void foo( A * a, B * b, int i ) {
215 // monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
216 // monitor_guard_t __guard = { __monitors, 2 };
217 // /*Some code*/ => /*Some code*/
218 // } }
219 //
220 class ThreadStarter final {
221 public:
222
223 void postvisit( FunctionDecl * decl );
224 void previsit ( StructDecl * decl );
225
226 void addStartStatement( FunctionDecl * decl, DeclarationWithType * param );
227
228 static void implement( std::list< Declaration * > & translationUnit ) {
229 PassVisitor< ThreadStarter > impl;
230 acceptAll( translationUnit, impl );
231 }
232
233 private :
234 bool thread_ctor_seen = false;
235 StructDecl * thread_decl = nullptr;
236 };
237
238 //=============================================================================================
239 // General entry routine
240 //=============================================================================================
241 void applyKeywords( std::list< Declaration * > & translationUnit ) {
242 ThreadKeyword ::implement( translationUnit );
243 CoroutineKeyword ::implement( translationUnit );
244 MonitorKeyword ::implement( translationUnit );
245 }
246
247 void implementMutexFuncs( std::list< Declaration * > & translationUnit ) {
248 MutexKeyword ::implement( translationUnit );
249 }
250
251 void implementThreadStarter( std::list< Declaration * > & translationUnit ) {
252 ThreadStarter ::implement( translationUnit );
253 }
254
255 //=============================================================================================
256 // Generic keyword implementation
257 //=============================================================================================
258 void fixupGenerics(FunctionType * func, StructDecl * decl) {
259 cloneAll(decl->parameters, func->forall);
260 for ( TypeDecl * td : func->forall ) {
261 strict_dynamic_cast<StructInstType*>(
262 func->parameters.front()->get_type()->stripReferences()
263 )->parameters.push_back(
264 new TypeExpr( new TypeInstType( noQualifiers, td->name, td ) )
265 );
266 }
267 }
268
269 void ConcurrentSueKeyword::postvisit(StructDecl * decl) {
270 if( decl->name == type_name && decl->body ) {
271 assert( !type_decl );
272 type_decl = decl;
273 }
274 else if ( is_target(decl) ) {
275 handle( decl );
276 }
277 }
278
279 void ConcurrentSueKeyword::handle( StructDecl * decl ) {
280 if( ! decl->body ) return;
281
282 if( !type_decl ) throw SemanticError( decl, context_error );
283
284 FunctionDecl * func = forwardDeclare( decl );
285 ObjectDecl * field = addField( decl );
286 addRoutines( field, func );
287 }
288
289 FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) {
290
291 StructDecl * forward = decl->clone();
292 forward->set_body( false );
293 deleteAll( forward->get_members() );
294 forward->get_members().clear();
295
296 FunctionType * get_type = new FunctionType( noQualifiers, false );
297 ObjectDecl * this_decl = new ObjectDecl(
298 "this",
299 noStorageClasses,
300 LinkageSpec::Cforall,
301 nullptr,
302 new ReferenceType(
303 noQualifiers,
304 new StructInstType(
305 noQualifiers,
306 decl
307 )
308 ),
309 nullptr
310 );
311
312 get_type->get_parameters().push_back( this_decl->clone() );
313 get_type->get_returnVals().push_back(
314 new ObjectDecl(
315 "ret",
316 noStorageClasses,
317 LinkageSpec::Cforall,
318 nullptr,
319 new PointerType(
320 noQualifiers,
321 new StructInstType(
322 noQualifiers,
323 type_decl
324 )
325 ),
326 nullptr
327 )
328 );
329 fixupGenerics(get_type, decl);
330
331 FunctionDecl * get_decl = new FunctionDecl(
332 getter_name,
333 Type::Static,
334 LinkageSpec::Cforall,
335 get_type,
336 nullptr,
337 noAttributes,
338 Type::Inline
339 );
340
341 FunctionDecl * main_decl = nullptr;
342
343 if( needs_main ) {
344 FunctionType * main_type = new FunctionType( noQualifiers, false );
345
346 main_type->get_parameters().push_back( this_decl->clone() );
347
348 main_decl = new FunctionDecl(
349 "main",
350 noStorageClasses,
351 LinkageSpec::Cforall,
352 main_type,
353 nullptr
354 );
355 fixupGenerics(main_type, decl);
356 }
357
358 delete this_decl;
359
360 declsToAddBefore.push_back( forward );
361 if( needs_main ) declsToAddBefore.push_back( main_decl );
362 declsToAddBefore.push_back( get_decl );
363
364 return get_decl;
365 }
366
367 ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) {
368 ObjectDecl * field = new ObjectDecl(
369 field_name,
370 noStorageClasses,
371 LinkageSpec::Cforall,
372 nullptr,
373 new StructInstType(
374 noQualifiers,
375 type_decl
376 ),
377 nullptr
378 );
379
380 decl->get_members().push_back( field );
381
382 return field;
383 }
384
385 void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
386 CompoundStmt * statement = new CompoundStmt();
387 statement->push_back(
388 new ReturnStmt(
389 new AddressExpr(
390 new MemberExpr(
391 field,
392 new CastExpr(
393 new VariableExpr( func->get_functionType()->get_parameters().front() ),
394 func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone()
395 )
396 )
397 )
398 )
399 );
400
401 FunctionDecl * get_decl = func->clone();
402
403 get_decl->set_statements( statement );
404
405 declsToAddAfter.push_back( get_decl );
406
407 // get_decl->fixUniqueId();
408 }
409
410 //=============================================================================================
411 // Mutex keyword implementation
412 //=============================================================================================
413
414 void MutexKeyword::postvisit(FunctionDecl* decl) {
415
416 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
417 if( mutexArgs.empty() ) return;
418
419 if( CodeGen::isConstructor(decl->name) ) throw SemanticError( decl, "constructors cannot have mutex parameters" );
420
421 bool isDtor = CodeGen::isDestructor( decl->name );
422
423 if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( decl, "destructors can only have 1 mutex argument" );
424
425 for(auto arg : mutexArgs) {
426 validate( arg );
427 }
428
429 CompoundStmt* body = decl->get_statements();
430 if( ! body ) return;
431
432 if( !monitor_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
433 if( !guard_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
434 if( !dtor_guard_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
435
436 if( isDtor ) {
437 addDtorStatments( decl, body, mutexArgs );
438 }
439 else {
440 addStatments( decl, body, mutexArgs );
441 }
442 }
443
444 void MutexKeyword::postvisit(StructDecl* decl) {
445
446 if( decl->name == "monitor_desc" ) {
447 assert( !monitor_decl );
448 monitor_decl = decl;
449 }
450 else if( decl->name == "monitor_guard_t" ) {
451 assert( !guard_decl );
452 guard_decl = decl;
453 }
454 else if( decl->name == "monitor_dtor_guard_t" ) {
455 assert( !dtor_guard_decl );
456 dtor_guard_decl = decl;
457 }
458 }
459
460 std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
461 std::list<DeclarationWithType*> mutexArgs;
462
463 for( auto arg : decl->get_functionType()->get_parameters()) {
464 //Find mutex arguments
465 Type* ty = arg->get_type();
466 if( ! ty->get_mutex() ) continue;
467
468 //Append it to the list
469 mutexArgs.push_back( arg );
470 }
471
472 return mutexArgs;
473 }
474
475 void MutexKeyword::validate( DeclarationWithType * arg ) {
476 Type* ty = arg->get_type();
477
478 //Makes sure it's not a copy
479 ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
480 if( ! rty ) throw SemanticError( arg, "Mutex argument must be of reference type " );
481
482 //Make sure the we are pointing directly to a type
483 Type* base = rty->get_base();
484 if( dynamic_cast< ReferenceType * >( base ) ) throw SemanticError( arg, "Mutex argument have exactly one level of indirection " );
485 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( arg, "Mutex argument have exactly one level of indirection " );
486
487 //Make sure that typed isn't mutex
488 if( base->get_mutex() ) throw SemanticError( arg, "mutex keyword may only appear once per argument " );
489 }
490
491 void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
492 Type * arg_type = args.front()->get_type()->clone();
493 arg_type->set_mutex( false );
494
495 ObjectDecl * monitors = new ObjectDecl(
496 "__monitor",
497 noStorageClasses,
498 LinkageSpec::Cforall,
499 nullptr,
500 new PointerType(
501 noQualifiers,
502 new StructInstType(
503 noQualifiers,
504 monitor_decl
505 )
506 ),
507 new SingleInit( new UntypedExpr(
508 new NameExpr( "get_monitor" ),
509 { new CastExpr( new VariableExpr( args.front() ), arg_type ) }
510 ))
511 );
512
513 assert(generic_func);
514
515 //in reverse order :
516 // monitor_guard_t __guard = { __monitors, #, func };
517 body->push_front(
518 new DeclStmt( new ObjectDecl(
519 "__guard",
520 noStorageClasses,
521 LinkageSpec::Cforall,
522 nullptr,
523 new StructInstType(
524 noQualifiers,
525 dtor_guard_decl
526 ),
527 new ListInit(
528 {
529 new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
530 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
531 },
532 noDesignators,
533 true
534 )
535 ))
536 );
537
538 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
539 body->push_front( new DeclStmt( monitors) );
540 }
541
542 void MutexKeyword::addStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
543 ObjectDecl * monitors = new ObjectDecl(
544 "__monitors",
545 noStorageClasses,
546 LinkageSpec::Cforall,
547 nullptr,
548 new ArrayType(
549 noQualifiers,
550 new PointerType(
551 noQualifiers,
552 new StructInstType(
553 noQualifiers,
554 monitor_decl
555 )
556 ),
557 new ConstantExpr( Constant::from_ulong( args.size() ) ),
558 false,
559 false
560 ),
561 new ListInit(
562 map_range < std::list<Initializer*> > ( args, [](DeclarationWithType * var ){
563 Type * type = var->get_type()->clone();
564 type->set_mutex( false );
565 return new SingleInit( new UntypedExpr(
566 new NameExpr( "get_monitor" ),
567 { new CastExpr( new VariableExpr( var ), type ) }
568 ) );
569 })
570 )
571 );
572
573 assert(generic_func);
574
575 //in reverse order :
576 // monitor_guard_t __guard = { __monitors, #, func };
577 body->push_front(
578 new DeclStmt( new ObjectDecl(
579 "__guard",
580 noStorageClasses,
581 LinkageSpec::Cforall,
582 nullptr,
583 new StructInstType(
584 noQualifiers,
585 guard_decl
586 ),
587 new ListInit(
588 {
589 new SingleInit( new VariableExpr( monitors ) ),
590 new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ),
591 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
592 },
593 noDesignators,
594 true
595 )
596 ))
597 );
598
599 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
600 body->push_front( new DeclStmt( monitors) );
601 }
602
603 //=============================================================================================
604 // General entry routine
605 //=============================================================================================
606 void ThreadStarter::previsit( StructDecl * decl ) {
607 if( decl->name == "thread_desc" && decl->body ) {
608 assert( !thread_decl );
609 thread_decl = decl;
610 }
611 }
612
613 void ThreadStarter::postvisit(FunctionDecl * decl) {
614 if( ! CodeGen::isConstructor(decl->name) ) return;
615
616 Type * typeof_this = InitTweak::getTypeofThis(decl->type);
617 StructInstType * ctored_type = dynamic_cast< StructInstType * >( typeof_this );
618 if( ctored_type && ctored_type->baseStruct == thread_decl ) {
619 thread_ctor_seen = true;
620 }
621
622 DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
623 auto type = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
624 if( type && type->get_baseStruct()->is_thread() ) {
625 if( !thread_decl || !thread_ctor_seen ) {
626 throw SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread>");
627 }
628
629 addStartStatement( decl, param );
630 }
631 }
632
633 void ThreadStarter::addStartStatement( FunctionDecl * decl, DeclarationWithType * param ) {
634 CompoundStmt * stmt = decl->get_statements();
635
636 if( ! stmt ) return;
637
638 stmt->push_back(
639 new ExprStmt(
640 new UntypedExpr(
641 new NameExpr( "__thrd_start" ),
642 { new VariableExpr( param ) }
643 )
644 )
645 );
646 }
647};
648
649// Local Variables: //
650// mode: c //
651// tab-width: 4 //
652// End: //
Note: See TracBrowser for help on using the repository browser.