source: src/Concurrency/Keywords.cc @ b32ada31

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since b32ada31 was b32ada31, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

First draft implementation of the coroutine keyword

  • Property mode set to 100644
File size: 10.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     : 1
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/Mutator.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 thread type declarations :
43        // thread Mythread {                         struct MyThread {
44        //      int data;                                  int data;
45        //      a_struct_t more_data;                      a_struct_t more_data;
46        //                                =>             thread_desc __thrd_d;
47        // };                                        };
48        //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
49        //                                           void main( MyThread * this );
50        //
51        class ThreadKeyword final : public Mutator {
52          public:
53
54                static void implement( std::list< Declaration * > & translationUnit ) {}
55        };
56
57        //-----------------------------------------------------------------------------
58        //Handles coroutine type declarations :
59        // coroutine MyCoroutine {                   struct MyCoroutine {
60        //      int data;                                  int data;
61        //      a_struct_t more_data;                      a_struct_t more_data;
62        //                                =>             coroutine_desc __cor_d;
63        // };                                        };
64        //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
65        //                                           void main( MyCoroutine * this );
66        //
67        class CoroutineKeyword final : public Visitor {
68            template< typename Visitor >
69            friend void SymTab::acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
70          public:
71
72                using Visitor::visit;
73                virtual void visit( StructDecl * decl ) override final;
74
75                void handle( StructDecl * );
76                Declaration * addField( StructDecl * );
77                void addRoutines( StructDecl *, Declaration * );
78
79                static void implement( std::list< Declaration * > & translationUnit ) {
80                        CoroutineKeyword impl;
81                        SymTab::acceptAndAdd( translationUnit, impl );
82                }
83
84          private:
85                std::list< Declaration * > declsToAdd, declsToAddAfter;
86                StructDecl* coroutine_decl = nullptr;
87        };
88
89        //-----------------------------------------------------------------------------
90        //Handles monitor type declarations :
91        // monitor MyMonitor {                       struct MyMonitor {
92        //      int data;                                  int data;
93        //      a_struct_t more_data;                      a_struct_t more_data;
94        //                                =>             monitor_desc __mon_d;
95        // };                                        };
96        //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
97        //                                           void main( MyMonitor * this );
98        //
99        class MonitorKeyword final : public Mutator {
100          public:
101
102                static void implement( std::list< Declaration * > & translationUnit ) {}
103        };
104
105        //-----------------------------------------------------------------------------
106        //Handles mutex routines definitions :
107        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
108        //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
109        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
110        //    /*Some code*/                                       =>           /*Some code*/
111        // }                                                               }
112        //
113        class MutexKeyword final : public Visitor {
114          public:
115
116                using Visitor::visit;
117                virtual void visit( FunctionDecl * decl ) override final;
118                virtual void visit(   StructDecl * decl ) override final;
119
120                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
121                void validate( DeclarationWithType * );
122                void addStatments( CompoundStmt *, const std::list<DeclarationWithType * > &);
123
124                static void implement( std::list< Declaration * > & translationUnit ) {
125                        MutexKeyword impl;
126                        acceptAll( translationUnit, impl );
127                }
128
129          private:
130                StructDecl* monitor_decl = nullptr;
131                StructDecl* guard_decl = nullptr;
132        };
133
134        //=============================================================================================
135        // General entry routine
136        //=============================================================================================
137        void applyKeywords( std::list< Declaration * > & translationUnit ) {
138                ThreadKeyword   ::implement( translationUnit );
139                CoroutineKeyword        ::implement( translationUnit );
140                MonitorKeyword  ::implement( translationUnit );
141                MutexKeyword    ::implement( translationUnit );
142        }
143
144        //=============================================================================================
145        // Coroutine keyword implementation
146        //=============================================================================================
147        void CoroutineKeyword::visit(StructDecl * decl) {
148                if( decl->get_name() == "coroutine_desc" ) {
149                        assert( !coroutine_decl );
150                        coroutine_decl = decl;
151                }
152                else if ( false ) {
153                        handle( decl );
154                }
155
156        }
157
158        void CoroutineKeyword::handle( StructDecl * decl ) {
159                if( ! decl->has_body() ) return;
160
161                if( !coroutine_decl ) throw SemanticError( "coroutine keyword requires coroutines to be in scope, add #include <coroutine>", decl );
162
163                Declaration * field = addField( decl );
164                addRoutines( decl, field );
165        }
166
167        Declaration * CoroutineKeyword::addField( StructDecl * decl ) {
168                Declaration * cor = new ObjectDecl(
169                        "__cor",
170                        noStorage,
171                        LinkageSpec::Cforall,
172                        nullptr,
173                        new StructInstType(
174                                noQualifiers,
175                                coroutine_decl
176                        ),
177                        nullptr
178                );
179
180                decl->get_members().push_front( cor );
181
182                return cor;
183        }
184
185        void CoroutineKeyword::addRoutines( StructDecl * decl, Declaration * field ) {
186                FunctionType * type = new FunctionType( noQualifiers, false );
187                type->get_parameters().push_back(
188                        new ObjectDecl(
189                                "this",
190                                noStorage,
191                                LinkageSpec::Cforall,
192                                nullptr,
193                                new PointerType(
194                                        noQualifiers,
195                                        new StructInstType(
196                                                noQualifiers,
197                                                decl
198                                        )
199                                ),
200                                nullptr
201                        )
202                );
203
204                CompoundStmt * statement = new CompoundStmt( noLabels );
205                statement->push_back( 
206                        new ReturnStmt(
207                                noLabels,
208                                new UntypedMemberExpr(
209                                        new NameExpr( "__cor" ),
210                                        new NameExpr( "this" )
211                                )
212                        )
213                );
214
215                declsToAddAfter.push_back( 
216                        new FunctionDecl(
217                                "get_coroutine",
218                                Type::Static,
219                                LinkageSpec::Cforall,
220                                type,
221                                statement,
222                                noAttributes,
223                                Type::Inline
224                        )
225                );
226        }
227       
228
229        //=============================================================================================
230        // Mutex keyword implementation
231        //=============================================================================================
232        void MutexKeyword::visit(FunctionDecl* decl) {
233                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
234                if( mutexArgs.empty() ) return;
235
236                for(auto arg : mutexArgs) {
237                        validate( arg );
238                }
239
240                CompoundStmt* body = decl->get_statements();
241                if( ! body ) return;
242
243                if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
244                if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
245
246                addStatments( body, mutexArgs );
247        }
248
249        void MutexKeyword::visit(StructDecl* decl) {
250                if( decl->get_name() == "monitor_desc" ) {
251                        assert( !monitor_decl );
252                        monitor_decl = decl;
253                }
254                else if( decl->get_name() == "monitor_guard_t" ) {
255                        assert( !guard_decl );
256                        guard_decl = decl;
257                }
258        }
259
260        std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
261                std::list<DeclarationWithType*> mutexArgs;
262
263                for( auto arg : decl->get_functionType()->get_parameters()) {
264                        //Find mutex arguments
265                        Type* ty = arg->get_type();
266                        if( ! ty->get_qualifiers().isMutex ) continue;
267
268                        //Append it to the list
269                        mutexArgs.push_back( arg );
270                }
271
272                return mutexArgs;
273        }
274
275        void MutexKeyword::validate( DeclarationWithType * arg ) {
276                Type* ty = arg->get_type();
277
278                //Makes sure it's not a copy
279                PointerType* pty = dynamic_cast< PointerType * >( ty );
280                if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );
281
282                //Make sure the we are pointing directly to a type
283                Type* base = pty->get_base();
284                if(  dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
285
286                //Make sure that typed isn't mutex
287                if( base->get_qualifiers().isMutex ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
288        }
289
290        void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
291                ObjectDecl * monitors = new ObjectDecl(
292                        "__monitors",
293                        noStorage,
294                        LinkageSpec::Cforall,
295                        nullptr,
296                        new ArrayType(
297                                noQualifiers,
298                                new PointerType(
299                                        noQualifiers,
300                                        new StructInstType(
301                                                noQualifiers,
302                                                monitor_decl
303                                        )
304                                ),
305                                new ConstantExpr( Constant::from_ulong( args.size() ) ),
306                                false,
307                                false
308                        ),
309                        new ListInit(
310                                map_range < std::list<Initializer*> > ( args, [](DeclarationWithType * var ){
311                                        return new SingleInit( new UntypedExpr(
312                                                new NameExpr( "get_monitor" ),
313                                                {  new VariableExpr( var ) }
314                                        ) );
315                                })
316                        )
317                );
318
319                //in reverse order :
320                // monitor_guard_t __guard = { __monitors, # };
321                body->push_front(
322                        new DeclStmt( noLabels, new ObjectDecl(
323                                "__guard",
324                                noStorage,
325                                LinkageSpec::Cforall,
326                                nullptr,
327                                new StructInstType(
328                                        noQualifiers,
329                                        guard_decl
330                                ),
331                                new ListInit(
332                                        {
333                                                new SingleInit( new VariableExpr( monitors ) ),
334                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
335                                        },
336                                        noDesignators,
337                                        true
338                                )
339                        ))
340                );
341
342                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
343                body->push_front( new DeclStmt( noLabels, monitors) );
344        }
345};
Note: See TracBrowser for help on using the repository browser.