source: src/Concurrency/Keywords.cc@ bcda04c

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

Fixed autogen constructors for concurrent sues

  • Property mode set to 100644
File size: 13.8 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 "SymTab/AddVisit.h"
20#include "SynTree/Declaration.h"
21#include "SynTree/Expression.h"
22#include "SynTree/Initializer.h"
23#include "SynTree/Statement.h"
24#include "SynTree/Type.h"
25#include "SynTree/Visitor.h"
26
27namespace Concurrency {
28
29 namespace {
30 const std::list<Label> noLabels;
31 const std::list< Attribute * > noAttributes;
32 Type::StorageClasses noStorage;
33 Type::Qualifiers noQualifiers;
34 }
35
36 //=============================================================================================
37 // Visitors declaration
38 //=============================================================================================
39
40 //-----------------------------------------------------------------------------
41 //Handles sue type declarations :
42 // sue MyType { struct MyType {
43 // int data; int data;
44 // a_struct_t more_data; a_struct_t more_data;
45 // => NewField_t newField;
46 // }; };
47 // static inline NewField_t * getter_name( MyType * this ) { return &this->newField; }
48 //
49 class ConcurrentSueKeyword : public Visitor {
50 protected:
51 template< typename Visitor >
52 friend void SymTab::acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
53 public:
54
55 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error ) :
56 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ) {}
57
58 virtual ~ConcurrentSueKeyword() {}
59
60 using Visitor::visit;
61 virtual void visit( StructDecl * decl ) override final;
62
63 void handle( StructDecl * );
64 FunctionDecl * forwardDeclare( StructDecl * );
65 ObjectDecl * addField( StructDecl * );
66 void addRoutines( StructDecl *, ObjectDecl *, FunctionDecl * );
67
68 virtual bool is_target( StructDecl * decl ) = 0;
69
70 private:
71 const std::string type_name;
72 const std::string field_name;
73 const std::string getter_name;
74 const std::string context_error;
75
76 std::list< Declaration * > declsToAdd, declsToAddAfter;
77 StructDecl* type_decl = nullptr;
78 };
79
80
81 //-----------------------------------------------------------------------------
82 //Handles thread type declarations :
83 // thread Mythread { struct MyThread {
84 // int data; int data;
85 // a_struct_t more_data; a_struct_t more_data;
86 // => thread_desc __thrd_d;
87 // }; };
88 // static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
89 //
90 class ThreadKeyword final : public ConcurrentSueKeyword {
91 public:
92
93 ThreadKeyword() : ConcurrentSueKeyword(
94 "thread_desc",
95 "__thrd",
96 "get_thread",
97 "thread keyword requires threads to be in scope, add #include <thread>"
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 ThreadKeyword impl;
107 SymTab::acceptAndAdd( 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 )
129 {}
130
131 virtual ~CoroutineKeyword() {}
132
133 virtual bool is_target( StructDecl * decl ) override final { return decl->is_coroutine(); }
134
135 static void implement( std::list< Declaration * > & translationUnit ) {
136 CoroutineKeyword impl;
137 SymTab::acceptAndAdd( translationUnit, impl );
138 }
139 };
140
141 //-----------------------------------------------------------------------------
142 //Handles monitor type declarations :
143 // monitor MyMonitor { struct MyMonitor {
144 // int data; int data;
145 // a_struct_t more_data; a_struct_t more_data;
146 // => monitor_desc __mon_d;
147 // }; };
148 // static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
149 //
150 class MonitorKeyword final : public ConcurrentSueKeyword {
151 public:
152
153 MonitorKeyword() : ConcurrentSueKeyword(
154 "monitor_desc",
155 "__mon",
156 "get_monitor",
157 "monitor keyword requires monitors to be in scope, add #include <monitor>"
158 )
159 {}
160
161 virtual ~MonitorKeyword() {}
162
163 virtual bool is_target( StructDecl * decl ) override final { return decl->is_monitor(); }
164
165 static void implement( std::list< Declaration * > & translationUnit ) {
166 MonitorKeyword impl;
167 SymTab::acceptAndAdd( translationUnit, impl );
168 }
169 };
170
171 //-----------------------------------------------------------------------------
172 //Handles mutex routines definitions :
173 // void foo( A * mutex a, B * mutex b, int i ) { void foo( A * a, B * b, int i ) {
174 // monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
175 // monitor_guard_t __guard = { __monitors, 2 };
176 // /*Some code*/ => /*Some code*/
177 // } }
178 //
179 class MutexKeyword final : public Visitor {
180 public:
181
182 using Visitor::visit;
183 virtual void visit( FunctionDecl * decl ) override final;
184 virtual void visit( StructDecl * decl ) override final;
185
186 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
187 void validate( DeclarationWithType * );
188 void addStatments( CompoundStmt *, const std::list<DeclarationWithType * > &);
189
190 static void implement( std::list< Declaration * > & translationUnit ) {
191 MutexKeyword impl;
192 acceptAll( translationUnit, impl );
193 }
194
195 private:
196 StructDecl* monitor_decl = nullptr;
197 StructDecl* guard_decl = nullptr;
198 };
199
200 //=============================================================================================
201 // General entry routine
202 //=============================================================================================
203 void applyKeywords( std::list< Declaration * > & translationUnit ) {
204 ThreadKeyword ::implement( translationUnit );
205 CoroutineKeyword ::implement( translationUnit );
206 MonitorKeyword ::implement( translationUnit );
207 }
208
209 void implementMutexFuncs( std::list< Declaration * > & translationUnit ) {
210 MutexKeyword ::implement( translationUnit );
211 }
212
213 void implementThreadStarter( std::list< Declaration * > & translationUnit ) {
214
215 }
216
217 //=============================================================================================
218 // Generic keyword implementation
219 //=============================================================================================
220 void ConcurrentSueKeyword::visit(StructDecl * decl) {
221 if( decl->get_name() == type_name ) {
222 assert( !type_decl );
223 type_decl = decl;
224 }
225 else if ( is_target(decl) ) {
226 handle( decl );
227 }
228
229 }
230
231 void ConcurrentSueKeyword::handle( StructDecl * decl ) {
232 if( ! decl->has_body() ) return;
233
234 if( !type_decl ) throw SemanticError( context_error, decl );
235
236 FunctionDecl * func = forwardDeclare( decl );
237 ObjectDecl * field = addField( decl );
238 addRoutines( decl, field, func );
239 }
240
241 FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) {
242
243 StructDecl * forward = decl->clone();
244 forward->set_body( false );
245 deleteAll( forward->get_members() );
246 forward->get_members().clear();
247
248 FunctionType * type = new FunctionType( noQualifiers, false );
249 ObjectDecl * this_decl = new ObjectDecl(
250 "this",
251 noStorage,
252 LinkageSpec::Cforall,
253 nullptr,
254 new PointerType(
255 noQualifiers,
256 new StructInstType(
257 noQualifiers,
258 decl
259 )
260 ),
261 nullptr
262 );
263
264 type->get_parameters().push_back( this_decl );
265 type->get_returnVals().push_back(
266 new ObjectDecl(
267 "ret",
268 noStorage,
269 LinkageSpec::Cforall,
270 nullptr,
271 new PointerType(
272 noQualifiers,
273 new StructInstType(
274 noQualifiers,
275 type_decl
276 )
277 ),
278 nullptr
279 )
280 );
281
282 FunctionDecl * get_decl = new FunctionDecl(
283 getter_name,
284 Type::Static,
285 LinkageSpec::Cforall,
286 type,
287 nullptr,
288 noAttributes,
289 Type::Inline
290 );
291
292 declsToAdd.push_back( forward );
293 declsToAdd.push_back( get_decl );
294
295 return get_decl;
296 }
297
298 ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) {
299 ObjectDecl * field = new ObjectDecl(
300 field_name,
301 noStorage,
302 LinkageSpec::Cforall,
303 nullptr,
304 new StructInstType(
305 noQualifiers,
306 type_decl
307 ),
308 nullptr
309 );
310
311 decl->get_members().push_back( field );
312
313 return field;
314 }
315
316 void ConcurrentSueKeyword::addRoutines( StructDecl * decl, ObjectDecl * field, FunctionDecl * func ) {
317 CompoundStmt * statement = new CompoundStmt( noLabels );
318 statement->push_back(
319 new ReturnStmt(
320 noLabels,
321 new AddressExpr(
322 new MemberExpr(
323 field,
324 UntypedExpr::createDeref( new VariableExpr( func->get_functionType()->get_parameters().front() ) )
325 )
326 )
327 )
328 );
329
330 FunctionDecl * get_decl = func->clone();
331
332 get_decl->set_statements( statement );
333
334 declsToAddAfter.push_back( get_decl );
335
336 // get_decl->fixUniqueId();
337 }
338
339 //=============================================================================================
340 // Mutex keyword implementation
341 //=============================================================================================
342 void MutexKeyword::visit(FunctionDecl* decl) {
343 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
344 if( mutexArgs.empty() ) return;
345
346 for(auto arg : mutexArgs) {
347 validate( arg );
348 }
349
350 CompoundStmt* body = decl->get_statements();
351 if( ! body ) return;
352
353 if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
354 if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
355
356 addStatments( body, mutexArgs );
357 }
358
359 void MutexKeyword::visit(StructDecl* decl) {
360 if( decl->get_name() == "monitor_desc" ) {
361 assert( !monitor_decl );
362 monitor_decl = decl;
363 }
364 else if( decl->get_name() == "monitor_guard_t" ) {
365 assert( !guard_decl );
366 guard_decl = decl;
367 }
368 }
369
370 std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
371 std::list<DeclarationWithType*> mutexArgs;
372
373 for( auto arg : decl->get_functionType()->get_parameters()) {
374 //Find mutex arguments
375 Type* ty = arg->get_type();
376 if( ! ty->get_mutex() ) continue;
377
378 //Append it to the list
379 mutexArgs.push_back( arg );
380 }
381
382 return mutexArgs;
383 }
384
385 void MutexKeyword::validate( DeclarationWithType * arg ) {
386 Type* ty = arg->get_type();
387
388 //Makes sure it's not a copy
389 PointerType* pty = dynamic_cast< PointerType * >( ty );
390 if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );
391
392 //Make sure the we are pointing directly to a type
393 Type* base = pty->get_base();
394 if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
395
396 //Make sure that typed isn't mutex
397 if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
398 }
399
400 void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
401 ObjectDecl * monitors = new ObjectDecl(
402 "__monitors",
403 noStorage,
404 LinkageSpec::Cforall,
405 nullptr,
406 new ArrayType(
407 noQualifiers,
408 new PointerType(
409 noQualifiers,
410 new StructInstType(
411 noQualifiers,
412 monitor_decl
413 )
414 ),
415 new ConstantExpr( Constant::from_ulong( args.size() ) ),
416 false,
417 false
418 ),
419 new ListInit(
420 map_range < std::list<Initializer*> > ( args, [this](DeclarationWithType * var ){
421 Type * type = var->get_type()->clone();
422 type->set_mutex( false );
423 return new SingleInit( new UntypedExpr(
424 new NameExpr( "get_monitor" ),
425 { new CastExpr( new VariableExpr( var ), type ) }
426 ) );
427 })
428 )
429 );
430
431 //in reverse order :
432 // monitor_guard_t __guard = { __monitors, # };
433 body->push_front(
434 new DeclStmt( noLabels, new ObjectDecl(
435 "__guard",
436 noStorage,
437 LinkageSpec::Cforall,
438 nullptr,
439 new StructInstType(
440 noQualifiers,
441 guard_decl
442 ),
443 new ListInit(
444 {
445 new SingleInit( new VariableExpr( monitors ) ),
446 new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
447 },
448 noDesignators,
449 true
450 )
451 ))
452 );
453
454 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
455 body->push_front( new DeclStmt( noLabels, monitors) );
456 }
457};
Note: See TracBrowser for help on using the repository browser.