source: src/Concurrency/Keywords.cc @ bbbc067

no_list
Last change on this file since bbbc067 was bbbc067, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Changed std::list<Initializer> to vector

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