source: src/Concurrency/Keywords.cc @ 68fe077a

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 68fe077a was 68fe077a, checked in by Peter A. Buhr <pabuhr@…>, 7 years ago

move type StorageClasses? from DeclarationNode? to Type

  • Property mode set to 100644
File size: 8.0 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        };
114
115        //=============================================================================================
116        // General entry routine
117        //=============================================================================================
118        void applyKeywords( std::list< Declaration * > & translationUnit ) {
119                ThreadKeyword   ::implement( translationUnit );
120                CoroutineKeyword        ::implement( translationUnit );
121                MonitorKeyword  ::implement( translationUnit );
122                MutexKeyword    ::implement( translationUnit );
123        }
124
125        //=============================================================================================
126        // Mutex keyword implementation
127        //=============================================================================================
128        void MutexKeyword::visit(FunctionDecl* decl) {
129                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
130                if( mutexArgs.empty() ) return;
131
132                for(auto arg : mutexArgs) {
133                        validate( arg );
134                }
135
136                CompoundStmt* body = decl->get_statements();
137                if( ! body ) return;
138
139                assert(monitor_decl);
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        }
149
150        std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
151                std::list<DeclarationWithType*> mutexArgs;
152
153                for( auto arg : decl->get_functionType()->get_parameters()) {
154                        //Find mutex arguments
155                        Type* ty = arg->get_type();
156                        if( ! ty->get_qualifiers().isMutex ) continue;
157
158                        //Append it to the list
159                        mutexArgs.push_back( arg );
160                }
161
162                return mutexArgs;
163        }
164
165        void MutexKeyword::validate( DeclarationWithType * arg ) {
166                Type* ty = arg->get_type();
167
168                //Makes sure it's not a copy
169                PointerType* pty = dynamic_cast< PointerType * >( ty );
170                if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );
171
172                //Make sure the we are pointing directly to a type
173                Type* base = pty->get_base();
174                if(  dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
175
176                //Make sure that typed isn't mutex
177                if( ! base->get_qualifiers().isMutex ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
178        }
179
180        void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
181
182                ObjectDecl * monitors = new ObjectDecl(
183                        "__monitors",
184                        noStorage,
185                        LinkageSpec::Cforall,
186                        nullptr,
187                        new ArrayType(
188                                noQualifiers,
189                                new PointerType(
190                                        noQualifiers,
191                                        new StructInstType(
192                                                noQualifiers,
193                                                monitor_decl
194                                        )
195                                ),
196                                new ConstantExpr( Constant::from_ulong( args.size() ) ),
197                                false,
198                                false
199                        ),
200                        new ListInit(
201                                map_range < std::list<Initializer*> > ( args, [](DeclarationWithType * var ){
202                                        return new SingleInit( new UntypedExpr(
203                                                new NameExpr( "get_monitor" ),
204                                                {  new VariableExpr( var ) }
205                                        ) );
206                                })
207                        )
208                );
209
210                //in reverse order :
211                // monitor_guard_t __guard = { __monitors, # };
212                body->push_front(
213                        new DeclStmt( noLabels, new ObjectDecl(
214                                "__guard",
215                                noStorage,
216                                LinkageSpec::Cforall,
217                                nullptr,
218                                new StructInstType(
219                                        noQualifiers,
220                                        "monitor_guard_t"
221                                ),
222                                new ListInit(
223                                        {
224                                                new SingleInit( new VariableExpr( monitors ) ),
225                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
226                                        }
227                                )
228                        ))
229                );
230
231                //monitor_desc * __monitors[] = { a, b };
232                body->push_front( new DeclStmt( noLabels, monitors) );
233        }
234};
Note: See TracBrowser for help on using the repository browser.