source: src/Concurrency/Keywords.cc @ 6c3a5ac1

arm-ehjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since 6c3a5ac1 was 6c3a5ac1, checked in by Thierry Delisle <tdelisle@…>, 2 years ago

Added better check to guarantee proper includes are present when using concurrency keywords

  • Property mode set to 100644
File size: 22.9 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     : 5
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 "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;
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, 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 ) {}
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                KeywordCastExpr::Target 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_desc __thrd_d;
91        // };                                        };
92        //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
93        //
94        class ThreadKeyword final : public ConcurrentSueKeyword {
95          public:
96
97                ThreadKeyword() : ConcurrentSueKeyword(
98                        "thread_desc",
99                        "__thrd",
100                        "get_thread",
101                        "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
102                        true,
103                        KeywordCastExpr::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_desc __cor_d;
123        // };                                        };
124        //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
125        //
126        class CoroutineKeyword final : public ConcurrentSueKeyword {
127          public:
128
129                CoroutineKeyword() : ConcurrentSueKeyword(
130                        "coroutine_desc",
131                        "__cor",
132                        "get_coroutine",
133                        "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
134                        true,
135                        KeywordCastExpr::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_desc __mon_d;
155        // };                                        };
156        //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
157        //
158        class MonitorKeyword final : public ConcurrentSueKeyword {
159          public:
160
161                MonitorKeyword() : ConcurrentSueKeyword(
162                        "monitor_desc",
163                        "__mon",
164                        "get_monitor",
165                        "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
166                        false,
167                        KeywordCastExpr::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_desc * __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_desc * __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_desc &)*get_thread(t), etc.
309                        if( !type_decl ) SemanticError( cast, context_error );
310                        if( !dtor_decl ) SemanticError( cast, context_error );
311                        Expression * arg = cast->arg;
312                        cast->arg = nullptr;
313                        delete cast;
314                        return new CastExpr(
315                                UntypedExpr::createDeref(
316                                        new UntypedExpr( new NameExpr( getter_name ), { arg } )
317                                ),
318                                new ReferenceType(
319                                        noQualifiers,
320                                        new StructInstType( noQualifiers, type_decl ) )
321                                );
322                }
323                return cast;
324        }
325
326
327        void ConcurrentSueKeyword::handle( StructDecl * decl ) {
328                if( ! decl->body ) return;
329
330                if( !type_decl ) SemanticError( decl, context_error );
331                if( !dtor_decl ) SemanticError( decl, context_error );
332
333                FunctionDecl * func = forwardDeclare( decl );
334                ObjectDecl * field = addField( decl );
335                addRoutines( field, func );
336        }
337
338        FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) {
339
340                StructDecl * forward = decl->clone();
341                forward->set_body( false );
342                deleteAll( forward->get_members() );
343                forward->get_members().clear();
344
345                FunctionType * get_type = new FunctionType( noQualifiers, false );
346                ObjectDecl * this_decl = new ObjectDecl(
347                        "this",
348                        noStorageClasses,
349                        LinkageSpec::Cforall,
350                        nullptr,
351                        new ReferenceType(
352                                noQualifiers,
353                                new StructInstType(
354                                        noQualifiers,
355                                        decl
356                                )
357                        ),
358                        nullptr
359                );
360
361                get_type->get_parameters().push_back( this_decl->clone() );
362                get_type->get_returnVals().push_back(
363                        new ObjectDecl(
364                                "ret",
365                                noStorageClasses,
366                                LinkageSpec::Cforall,
367                                nullptr,
368                                new PointerType(
369                                        noQualifiers,
370                                        new StructInstType(
371                                                noQualifiers,
372                                                type_decl
373                                        )
374                                ),
375                                nullptr
376                        )
377                );
378                fixupGenerics(get_type, decl);
379
380                FunctionDecl * get_decl = new FunctionDecl(
381                        getter_name,
382                        Type::Static,
383                        LinkageSpec::Cforall,
384                        get_type,
385                        nullptr,
386                        noAttributes,
387                        Type::Inline
388                );
389
390                FunctionDecl * main_decl = nullptr;
391
392                if( needs_main ) {
393                        FunctionType * main_type = new FunctionType( noQualifiers, false );
394
395                        main_type->get_parameters().push_back( this_decl->clone() );
396
397                        main_decl = new FunctionDecl(
398                                "main",
399                                noStorageClasses,
400                                LinkageSpec::Cforall,
401                                main_type,
402                                nullptr
403                        );
404                        fixupGenerics(main_type, decl);
405                }
406
407                delete this_decl;
408
409                declsToAddBefore.push_back( forward );
410                if( needs_main ) declsToAddBefore.push_back( main_decl );
411                declsToAddBefore.push_back( get_decl );
412
413                return get_decl;
414        }
415
416        ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) {
417                ObjectDecl * field = new ObjectDecl(
418                        field_name,
419                        noStorageClasses,
420                        LinkageSpec::Cforall,
421                        nullptr,
422                        new StructInstType(
423                                noQualifiers,
424                                type_decl
425                        ),
426                        nullptr
427                );
428
429                decl->get_members().push_back( field );
430
431                return field;
432        }
433
434        void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
435                CompoundStmt * statement = new CompoundStmt();
436                statement->push_back(
437                        new ReturnStmt(
438                                new AddressExpr(
439                                        new MemberExpr(
440                                                field,
441                                                new CastExpr(
442                                                        new VariableExpr( func->get_functionType()->get_parameters().front() ),
443                                                        func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone()
444                                                )
445                                        )
446                                )
447                        )
448                );
449
450                FunctionDecl * get_decl = func->clone();
451
452                get_decl->set_statements( statement );
453
454                declsToAddAfter.push_back( get_decl );
455
456                // get_decl->fixUniqueId();
457        }
458
459        //=============================================================================================
460        // Mutex keyword implementation
461        //=============================================================================================
462
463        void MutexKeyword::postvisit(FunctionDecl* decl) {
464
465                bool first = false;
466                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
467                bool isDtor = CodeGen::isDestructor( decl->name );
468
469                // Is this function relevant to monitors
470                if( mutexArgs.empty() ) {
471                        // If this is the destructor for a monitor it must be mutex
472                        if(isDtor) {
473                                Type* ty = decl->get_functionType()->get_parameters().front()->get_type();
474
475                                // If it's a copy, it's not a mutex
476                                ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
477                                if( ! rty ) return;
478
479                                // If we are not pointing directly to a type, it's not a mutex
480                                Type* base = rty->get_base();
481                                if( dynamic_cast< ReferenceType * >( base ) ) return;
482                                if( dynamic_cast< PointerType * >( base ) ) return;
483
484                                // Check if its a struct
485                                StructInstType * baseStruct = dynamic_cast< StructInstType * >( base );
486                                if( !baseStruct ) return;
487
488                                // Check if its a monitor
489                                if(baseStruct->baseStruct->is_monitor() || baseStruct->baseStruct->is_thread())
490                                        SemanticError( decl, "destructors for structures declared as \"monitor\" must use mutex parameters\n" );
491                        }
492                        return;
493                }
494
495                // Monitors can't be constructed with mutual exclusion
496                if( CodeGen::isConstructor(decl->name) && !first ) SemanticError( decl, "constructors cannot have mutex parameters" );
497
498                // It makes no sense to have multiple mutex parameters for the destructor
499                if( isDtor && mutexArgs.size() != 1 ) SemanticError( decl, "destructors can only have 1 mutex argument" );
500
501                // Make sure all the mutex arguments are monitors
502                for(auto arg : mutexArgs) {
503                        validate( arg );
504                }
505
506                // Check if we need to instrument the body
507                CompoundStmt* body = decl->get_statements();
508                if( ! body ) return;
509
510                // Do we have the required headers
511                if( !monitor_decl || !guard_decl || !dtor_guard_decl )
512                        SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor.hfa>\n" );
513
514                // Instrument the body
515                if( isDtor ) {
516                        addDtorStatments( decl, body, mutexArgs );
517                }
518                else {
519                        addStatments( decl, body, mutexArgs );
520                }
521        }
522
523        void MutexKeyword::postvisit(StructDecl* decl) {
524
525                if( decl->name == "monitor_desc" && decl->body ) {
526                        assert( !monitor_decl );
527                        monitor_decl = decl;
528                }
529                else if( decl->name == "monitor_guard_t" && decl->body ) {
530                        assert( !guard_decl );
531                        guard_decl = decl;
532                }
533                else if( decl->name == "monitor_dtor_guard_t" && decl->body ) {
534                        assert( !dtor_guard_decl );
535                        dtor_guard_decl = decl;
536                }
537        }
538
539        std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl, bool & first ) {
540                std::list<DeclarationWithType*> mutexArgs;
541
542                bool once = true;
543                for( auto arg : decl->get_functionType()->get_parameters()) {
544                        //Find mutex arguments
545                        Type* ty = arg->get_type();
546                        if( ! ty->get_mutex() ) continue;
547
548                        if(once) {first = true;}
549                        once = false;
550
551                        //Append it to the list
552                        mutexArgs.push_back( arg );
553                }
554
555                return mutexArgs;
556        }
557
558        void MutexKeyword::validate( DeclarationWithType * arg ) {
559                Type* ty = arg->get_type();
560
561                //Makes sure it's not a copy
562                ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
563                if( ! rty ) SemanticError( arg, "Mutex argument must be of reference type " );
564
565                //Make sure the we are pointing directly to a type
566                Type* base = rty->get_base();
567                if( dynamic_cast< ReferenceType * >( base ) ) SemanticError( arg, "Mutex argument have exactly one level of indirection " );
568                if( dynamic_cast< PointerType * >( base ) ) SemanticError( arg, "Mutex argument have exactly one level of indirection " );
569
570                //Make sure that typed isn't mutex
571                if( base->get_mutex() ) SemanticError( arg, "mutex keyword may only appear once per argument " );
572        }
573
574        void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
575                Type * arg_type = args.front()->get_type()->clone();
576                arg_type->set_mutex( false );
577
578                ObjectDecl * monitors = new ObjectDecl(
579                        "__monitor",
580                        noStorageClasses,
581                        LinkageSpec::Cforall,
582                        nullptr,
583                        new PointerType(
584                                noQualifiers,
585                                new StructInstType(
586                                        noQualifiers,
587                                        monitor_decl
588                                )
589                        ),
590                        new SingleInit( new UntypedExpr(
591                                new NameExpr( "get_monitor" ),
592                                {  new CastExpr( new VariableExpr( args.front() ), arg_type ) }
593                        ))
594                );
595
596                assert(generic_func);
597
598                //in reverse order :
599                // monitor_dtor_guard_t __guard = { __monitors, func };
600                body->push_front(
601                        new DeclStmt( new ObjectDecl(
602                                "__guard",
603                                noStorageClasses,
604                                LinkageSpec::Cforall,
605                                nullptr,
606                                new StructInstType(
607                                        noQualifiers,
608                                        dtor_guard_decl
609                                ),
610                                new ListInit(
611                                        {
612                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
613                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
614                                        },
615                                        noDesignators,
616                                        true
617                                )
618                        ))
619                );
620
621                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
622                body->push_front( new DeclStmt( monitors) );
623        }
624
625        void MutexKeyword::addStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
626                ObjectDecl * monitors = new ObjectDecl(
627                        "__monitors",
628                        noStorageClasses,
629                        LinkageSpec::Cforall,
630                        nullptr,
631                        new ArrayType(
632                                noQualifiers,
633                                new PointerType(
634                                        noQualifiers,
635                                        new StructInstType(
636                                                noQualifiers,
637                                                monitor_decl
638                                        )
639                                ),
640                                new ConstantExpr( Constant::from_ulong( args.size() ) ),
641                                false,
642                                false
643                        ),
644                        new ListInit(
645                                map_range < std::list<Initializer*> > ( args, [](DeclarationWithType * var ){
646                                        Type * type = var->get_type()->clone();
647                                        type->set_mutex( false );
648                                        return new SingleInit( new UntypedExpr(
649                                                new NameExpr( "get_monitor" ),
650                                                {  new CastExpr( new VariableExpr( var ), type ) }
651                                        ) );
652                                })
653                        )
654                );
655
656                assert(generic_func);
657
658                // in reverse order :
659                // monitor_guard_t __guard = { __monitors, #, func };
660                body->push_front(
661                        new DeclStmt( new ObjectDecl(
662                                "__guard",
663                                noStorageClasses,
664                                LinkageSpec::Cforall,
665                                nullptr,
666                                new StructInstType(
667                                        noQualifiers,
668                                        guard_decl
669                                ),
670                                new ListInit(
671                                        {
672                                                new SingleInit( new VariableExpr( monitors ) ),
673                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ),
674                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
675                                        },
676                                        noDesignators,
677                                        true
678                                )
679                        ))
680                );
681
682                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
683                body->push_front( new DeclStmt( monitors) );
684        }
685
686        //=============================================================================================
687        // General entry routine
688        //=============================================================================================
689        void ThreadStarter::previsit( StructDecl * decl ) {
690                if( decl->name == "thread_desc" && decl->body ) {
691                        assert( !thread_decl );
692                        thread_decl = decl;
693                }
694        }
695
696        void ThreadStarter::postvisit(FunctionDecl * decl) {
697                if( ! CodeGen::isConstructor(decl->name) ) return;
698
699                Type * typeof_this = InitTweak::getTypeofThis(decl->type);
700                StructInstType * ctored_type = dynamic_cast< StructInstType * >( typeof_this );
701                if( ctored_type && ctored_type->baseStruct == thread_decl ) {
702                        thread_ctor_seen = true;
703                }
704
705                DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
706                auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
707                if( type && type->get_baseStruct()->is_thread() ) {
708                        if( !thread_decl || !thread_ctor_seen ) {
709                                SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread.hfa>");
710                        }
711
712                        addStartStatement( decl, param );
713                }
714        }
715
716        void ThreadStarter::addStartStatement( FunctionDecl * decl, DeclarationWithType * param ) {
717                CompoundStmt * stmt = decl->get_statements();
718
719                if( ! stmt ) return;
720
721                stmt->push_back(
722                        new ExprStmt(
723                                new UntypedExpr(
724                                        new NameExpr( "__thrd_start" ),
725                                        { new VariableExpr( param ) }
726                                )
727                        )
728                );
729        }
730};
731
732// Local Variables: //
733// mode: c //
734// tab-width: 4 //
735// End: //
Note: See TracBrowser for help on using the repository browser.