source: src/Concurrency/Keywords.cc @ 17af7d1

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 17af7d1 was ef42b143, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Implemented monitor keyword, and it works

  • Property mode set to 100644
File size: 8.2 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 "SynTree/Declaration.h"
20#include "SynTree/Expression.h"
21#include "SynTree/Initializer.h"
22#include "SynTree/Mutator.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                Type::StorageClasses noStorage;
32                Type::Qualifiers noQualifiers;
33        }
34
35        //=============================================================================================
36        // Visitors declaration
37        //=============================================================================================
38
39        //-----------------------------------------------------------------------------
40        //Handles thread type declarations :
41        // thread Mythread {                         struct MyThread {
42        //      int data;                                  int data;
43        //      a_struct_t more_data;                      a_struct_t more_data;
44        //                                =>             thread_desc __thrd_d;
45        // };                                        };
46        //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
47        //                                           void main( MyThread * this );
48        //
49        class ThreadKeyword final : public Mutator {
50          public:
51
52                static void implement( std::list< Declaration * > & translationUnit ) {}
53        };
54
55        //-----------------------------------------------------------------------------
56        //Handles coroutine type declarations :
57        // coroutine MyCoroutine {                   struct MyCoroutine {
58        //      int data;                                  int data;
59        //      a_struct_t more_data;                      a_struct_t more_data;
60        //                                =>             coroutine_desc __cor_d;
61        // };                                        };
62        //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
63        //                                           void main( MyCoroutine * this );
64        //
65        class CoroutineKeyword final : public Mutator {
66          public:
67
68                static void implement( std::list< Declaration * > & translationUnit ) {}
69        };
70
71        //-----------------------------------------------------------------------------
72        //Handles monitor type declarations :
73        // monitor MyMonitor {                       struct MyMonitor {
74        //      int data;                                  int data;
75        //      a_struct_t more_data;                      a_struct_t more_data;
76        //                                =>             monitor_desc __mon_d;
77        // };                                        };
78        //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
79        //                                           void main( MyMonitor * this );
80        //
81        class MonitorKeyword final : public Mutator {
82          public:
83
84                static void implement( std::list< Declaration * > & translationUnit ) {}
85        };
86
87        //-----------------------------------------------------------------------------
88        //Handles mutex routines definitions :
89        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
90        //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
91        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
92        //    /*Some code*/                                       =>           /*Some code*/
93        // }                                                               }
94        //
95        class MutexKeyword final : public Visitor {
96          public:
97
98                using Visitor::visit;
99                virtual void visit( FunctionDecl *functionDecl ) override final;
100                virtual void visit(   StructDecl *functionDecl ) override final;
101
102                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
103                void validate( DeclarationWithType * );
104                void addStatments( CompoundStmt *, const std::list<DeclarationWithType * > &);
105
106                static void implement( std::list< Declaration * > & translationUnit ) {
107                        MutexKeyword impl;
108                        acceptAll( translationUnit, impl );
109                }
110
111          private:
112                StructDecl* monitor_decl = nullptr;
113                StructDecl* guard_decl = nullptr;
114        };
115
116        //=============================================================================================
117        // General entry routine
118        //=============================================================================================
119        void applyKeywords( std::list< Declaration * > & translationUnit ) {
120                ThreadKeyword   ::implement( translationUnit );
121                CoroutineKeyword        ::implement( translationUnit );
122                MonitorKeyword  ::implement( translationUnit );
123                MutexKeyword    ::implement( translationUnit );
124        }
125
126        //=============================================================================================
127        // Mutex keyword implementation
128        //=============================================================================================
129        void MutexKeyword::visit(FunctionDecl* decl) {
130                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
131                if( mutexArgs.empty() ) return;
132
133                for(auto arg : mutexArgs) {
134                        validate( arg );
135                }
136
137                CompoundStmt* body = decl->get_statements();
138                if( ! body ) return;
139
140                addStatments( body, mutexArgs );
141        }
142
143        void MutexKeyword::visit(StructDecl* decl) {
144                if( decl->get_name() == "monitor_desc" ) {
145                        assert( !monitor_decl );
146                        monitor_decl = decl;
147                }
148                else if( decl->get_name() == "monitor_guard_t" ) {
149                        assert( !guard_decl );
150                        guard_decl = decl;
151                }
152        }
153
154        std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
155                std::list<DeclarationWithType*> mutexArgs;
156
157                for( auto arg : decl->get_functionType()->get_parameters()) {
158                        //Find mutex arguments
159                        Type* ty = arg->get_type();
160                        if( ! ty->get_qualifiers().isMutex ) continue;
161
162                        //Append it to the list
163                        mutexArgs.push_back( arg );
164                }
165
166                return mutexArgs;
167        }
168
169        void MutexKeyword::validate( DeclarationWithType * arg ) {
170                Type* ty = arg->get_type();
171
172                //Makes sure it's not a copy
173                PointerType* pty = dynamic_cast< PointerType * >( ty );
174                if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );
175
176                //Make sure the we are pointing directly to a type
177                Type* base = pty->get_base();
178                if(  dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
179
180                //Make sure that typed isn't mutex
181                if( base->get_qualifiers().isMutex ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
182        }
183
184        void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
185                assert(monitor_decl);
186                assert(guard_decl);
187
188                ObjectDecl * monitors = new ObjectDecl(
189                        "__monitors",
190                        noStorage,
191                        LinkageSpec::Cforall,
192                        nullptr,
193                        new ArrayType(
194                                noQualifiers,
195                                new PointerType(
196                                        noQualifiers,
197                                        new StructInstType(
198                                                noQualifiers,
199                                                monitor_decl
200                                        )
201                                ),
202                                new ConstantExpr( Constant::from_ulong( args.size() ) ),
203                                false,
204                                false
205                        ),
206                        new ListInit(
207                                map_range < std::list<Initializer*> > ( args, [](DeclarationWithType * var ){
208                                        return new SingleInit( new UntypedExpr(
209                                                new NameExpr( "get_monitor" ),
210                                                {  new VariableExpr( var ) }
211                                        ) );
212                                })
213                        )
214                );
215
216                //in reverse order :
217                // monitor_guard_t __guard = { __monitors, # };
218                body->push_front(
219                        new DeclStmt( noLabels, new ObjectDecl(
220                                "__guard",
221                                noStorage,
222                                LinkageSpec::Cforall,
223                                nullptr,
224                                new StructInstType(
225                                        noQualifiers,
226                                        guard_decl
227                                ),
228                                new ListInit(
229                                        {
230                                                new SingleInit( new VariableExpr( monitors ) ),
231                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
232                                        },
233                                        noDesignators,
234                                        true
235                                )
236                        ))
237                );
238
239                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
240                body->push_front( new DeclStmt( noLabels, monitors) );
241        }
242};
Note: See TracBrowser for help on using the repository browser.