source: src/Concurrency/Keywords.cc @ a254fa56

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since a254fa56 was ac2b598, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Changed descriptors for concurrency to use $ prefix instead of trailing _desc

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