source: src/Concurrency/Keywords.cc @ 751e2eb

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 751e2eb was 43cedfb1, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Fixed extra declaration of vtable on forwarded declarations of threads

  • Property mode set to 100644
File size: 35.0 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 :
[07de76b]13// Update Count     : 10
[64adb03]14//
15
16#include "Concurrency/Keywords.h"
17
[427854b]18#include <cassert>                        // for assert
19#include <string>                         // for string, operator==
20
[1c01c58]21#include <iostream>
22
23#include "Common/Examine.h"               // for isMainFor
[427854b]24#include "Common/PassVisitor.h"           // for PassVisitor
25#include "Common/SemanticError.h"         // for SemanticError
26#include "Common/utility.h"               // for deleteAll, map_range
27#include "CodeGen/OperatorTable.h"        // for isConstructor
28#include "ControlStruct/LabelGenerator.h" // for LebelGenerator
29#include "InitTweak/InitTweak.h"          // for getPointerBase
30#include "SynTree/LinkageSpec.h"          // for Cforall
31#include "SynTree/Constant.h"             // for Constant
32#include "SynTree/Declaration.h"          // for StructDecl, FunctionDecl, ObjectDecl
33#include "SynTree/Expression.h"           // for VariableExpr, ConstantExpr, Untype...
34#include "SynTree/Initializer.h"          // for SingleInit, ListInit, Initializer ...
35#include "SynTree/Label.h"                // for Label
36#include "SynTree/Statement.h"            // for CompoundStmt, DeclStmt, ExprStmt
37#include "SynTree/Type.h"                 // for StructInstType, Type, PointerType
38#include "SynTree/Visitor.h"              // for Visitor, acceptAll
[1c01c58]39#include "Virtual/Tables.h"
[bf2438c]40
41class Attribute;
[64adb03]42
43namespace Concurrency {
[1c01c58]44        inline static std::string getVTableName( std::string const & exception_name ) {
45                return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name);
46        }
47
[ab8c6a6]48        // Only detects threads constructed with the keyword thread.
49        inline static bool isThread( DeclarationWithType * decl ) {
50                Type * baseType = decl->get_type()->stripDeclarator();
51                StructInstType * instType = dynamic_cast<StructInstType *>( baseType );
52                if ( nullptr == instType ) { return false; }
53                return instType->baseStruct->is_thread();
54        }
55
[64adb03]56        //=============================================================================================
[2065609]57        // Pass declarations
[64adb03]58        //=============================================================================================
59
[bcda04c]60        //-----------------------------------------------------------------------------
61        //Handles sue type declarations :
62        // sue MyType {                             struct MyType {
63        //      int data;                                  int data;
64        //      a_struct_t more_data;                      a_struct_t more_data;
65        //                                =>             NewField_t newField;
66        // };                                        };
67        //                                           static inline NewField_t * getter_name( MyType * this ) { return &this->newField; }
68        //
[2065609]69        class ConcurrentSueKeyword : public WithDeclsToAdd {
[bcda04c]70          public:
71
[1c01c58]72                ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name,
73                        std::string&& getter_name, std::string&& context_error, std::string&& exception_name,
74                        bool needs_main, AggregateDecl::Aggregate cast_target ) :
75                  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
[69c5c00]76                  context_error( context_error ), exception_name( exception_name ),
77                  vtable_name( getVTableName( exception_name ) ),
[1c01c58]78                  needs_main( needs_main ), cast_target( cast_target ) {}
[bcda04c]79
80                virtual ~ConcurrentSueKeyword() {}
81
[9a705dc8]82                Declaration * postmutate( StructDecl * decl );
[6c3a5ac1]83                DeclarationWithType * postmutate( FunctionDecl * decl );
[bcda04c]84
85                void handle( StructDecl * );
[1c01c58]86                void addVtableForward( StructDecl * );
[bcda04c]87                FunctionDecl * forwardDeclare( StructDecl * );
88                ObjectDecl * addField( StructDecl * );
[2f9a722]89                void addRoutines( ObjectDecl *, FunctionDecl * );
[bcda04c]90
91                virtual bool is_target( StructDecl * decl ) = 0;
92
[9a705dc8]93                Expression * postmutate( KeywordCastExpr * cast );
94
[bcda04c]95          private:
96                const std::string type_name;
97                const std::string field_name;
98                const std::string getter_name;
99                const std::string context_error;
[69c5c00]100                const std::string exception_name;
[1c01c58]101                const std::string vtable_name;
[bd4d011]102                bool needs_main;
[312029a]103                AggregateDecl::Aggregate cast_target;
[bcda04c]104
[6c3a5ac1]105                StructDecl   * type_decl = nullptr;
106                FunctionDecl * dtor_decl = nullptr;
[69c5c00]107                StructDecl * except_decl = nullptr;
[1c01c58]108                StructDecl * vtable_decl = nullptr;
[bcda04c]109        };
110
111
[64adb03]112        //-----------------------------------------------------------------------------
113        //Handles thread type declarations :
114        // thread Mythread {                         struct MyThread {
115        //      int data;                                  int data;
116        //      a_struct_t more_data;                      a_struct_t more_data;
[ac2b598]117        //                                =>             $thread __thrd_d;
[64adb03]118        // };                                        };
[ac2b598]119        //                                           static inline $thread * get_thread( MyThread * this ) { return &this->__thrd_d; }
[64adb03]120        //
[bcda04c]121        class ThreadKeyword final : public ConcurrentSueKeyword {
[64adb03]122          public:
123
[bcda04c]124                ThreadKeyword() : ConcurrentSueKeyword(
[ac2b598]125                        "$thread",
[bcda04c]126                        "__thrd",
127                        "get_thread",
[6c3a5ac1]128                        "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
[ab8c6a6]129                        "ThreadCancelled",
[9a705dc8]130                        true,
[312029a]131                        AggregateDecl::Thread
[bcda04c]132                )
133                {}
134
135                virtual ~ThreadKeyword() {}
136
137                virtual bool is_target( StructDecl * decl ) override final { return decl->is_thread(); }
138
139                static void implement( std::list< Declaration * > & translationUnit ) {
[2065609]140                        PassVisitor< ThreadKeyword > impl;
[9a705dc8]141                        mutateAll( translationUnit, impl );
[bcda04c]142                }
[64adb03]143        };
144
145        //-----------------------------------------------------------------------------
146        //Handles coroutine type declarations :
147        // coroutine MyCoroutine {                   struct MyCoroutine {
148        //      int data;                                  int data;
149        //      a_struct_t more_data;                      a_struct_t more_data;
[ac2b598]150        //                                =>             $coroutine __cor_d;
[64adb03]151        // };                                        };
[ac2b598]152        //                                           static inline $coroutine * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
[64adb03]153        //
[bcda04c]154        class CoroutineKeyword final : public ConcurrentSueKeyword {
[64adb03]155          public:
156
[bcda04c]157                CoroutineKeyword() : ConcurrentSueKeyword(
[ac2b598]158                        "$coroutine",
[bcda04c]159                        "__cor",
160                        "get_coroutine",
[6c3a5ac1]161                        "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
[1c01c58]162                        "CoroutineCancelled",
[9a705dc8]163                        true,
[312029a]164                        AggregateDecl::Coroutine
[bcda04c]165                )
166                {}
[b32ada31]167
[bcda04c]168                virtual ~CoroutineKeyword() {}
169
170                virtual bool is_target( StructDecl * decl ) override final { return decl->is_coroutine(); }
[b32ada31]171
172                static void implement( std::list< Declaration * > & translationUnit ) {
[2065609]173                        PassVisitor< CoroutineKeyword > impl;
[9a705dc8]174                        mutateAll( translationUnit, impl );
[b32ada31]175                }
[64adb03]176        };
177
[427854b]178
179
[64adb03]180        //-----------------------------------------------------------------------------
181        //Handles monitor type declarations :
182        // monitor MyMonitor {                       struct MyMonitor {
183        //      int data;                                  int data;
184        //      a_struct_t more_data;                      a_struct_t more_data;
[ac2b598]185        //                                =>             $monitor __mon_d;
[64adb03]186        // };                                        };
[ac2b598]187        //                                           static inline $monitor * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
[64adb03]188        //
[bcda04c]189        class MonitorKeyword final : public ConcurrentSueKeyword {
[64adb03]190          public:
191
[bcda04c]192                MonitorKeyword() : ConcurrentSueKeyword(
[ac2b598]193                        "$monitor",
[bcda04c]194                        "__mon",
195                        "get_monitor",
[6c3a5ac1]196                        "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
[1c01c58]197                        "",
[9a705dc8]198                        false,
[312029a]199                        AggregateDecl::Monitor
[bcda04c]200                )
201                {}
202
203                virtual ~MonitorKeyword() {}
204
205                virtual bool is_target( StructDecl * decl ) override final { return decl->is_monitor(); }
206
207                static void implement( std::list< Declaration * > & translationUnit ) {
[2065609]208                        PassVisitor< MonitorKeyword > impl;
[9a705dc8]209                        mutateAll( translationUnit, impl );
[bcda04c]210                }
[64adb03]211        };
212
[427854b]213        //-----------------------------------------------------------------------------
214        //Handles generator type declarations :
215        // generator MyGenerator {                   struct MyGenerator {
216        //      int data;                                  int data;
217        //      a_struct_t more_data;                      a_struct_t more_data;
218        //                                =>             int __gen_next;
219        // };                                        };
220        //
221        class GeneratorKeyword final : public ConcurrentSueKeyword {
222          public:
223
224                GeneratorKeyword() : ConcurrentSueKeyword(
225                        "$generator",
226                        "__generator_state",
227                        "get_generator",
228                        "Unable to find builtin type $generator\n",
[1c01c58]229                        "",
[427854b]230                        true,
231                        AggregateDecl::Generator
232                )
233                {}
234
235                virtual ~GeneratorKeyword() {}
236
237                virtual bool is_target( StructDecl * decl ) override final { return decl->is_generator(); }
238
239                static void implement( std::list< Declaration * > & translationUnit ) {
240                        PassVisitor< GeneratorKeyword > impl;
241                        mutateAll( translationUnit, impl );
242                }
243        };
244
245
246        //-----------------------------------------------------------------------------
247        class SuspendKeyword final : public WithStmtsToAdd, public WithGuards {
248        public:
249                SuspendKeyword() = default;
250                virtual ~SuspendKeyword() = default;
251
252                void  premutate( FunctionDecl * );
253                DeclarationWithType * postmutate( FunctionDecl * );
254
255                Statement * postmutate( SuspendStmt * );
256
257                static void implement( std::list< Declaration * > & translationUnit ) {
258                        PassVisitor< SuspendKeyword > impl;
259                        mutateAll( translationUnit, impl );
260                }
261
262        private:
263                bool is_real_suspend( FunctionDecl * );
264
265                Statement * make_generator_suspend( SuspendStmt * );
266                Statement * make_coroutine_suspend( SuspendStmt * );
267
268                struct LabelPair {
269                        Label obj;
270                        int   idx;
271                };
272
273                LabelPair make_label() {
274                        labels.push_back( gen.newLabel("generator") );
275                        return { labels.back(), int(labels.size()) };
276                }
277
278                DeclarationWithType * in_generator = nullptr;
279                FunctionDecl * decl_suspend = nullptr;
280                std::vector<Label> labels;
281                ControlStruct::LabelGenerator & gen = *ControlStruct::LabelGenerator::getGenerator();
282        };
283
[64adb03]284        //-----------------------------------------------------------------------------
285        //Handles mutex routines definitions :
286        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
[ac2b598]287        //                                                                       $monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
[64adb03]288        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
289        //    /*Some code*/                                       =>           /*Some code*/
290        // }                                                               }
291        //
[2065609]292        class MutexKeyword final {
[64adb03]293          public:
294
[2065609]295                void postvisit( FunctionDecl * decl );
296                void postvisit(   StructDecl * decl );
[64adb03]297
[db4d8e3]298                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
[64adb03]299                void validate( DeclarationWithType * );
[ab8c6a6]300                void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
301                void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
302                void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
[64adb03]303
304                static void implement( std::list< Declaration * > & translationUnit ) {
[2065609]305                        PassVisitor< MutexKeyword > impl;
[64adb03]306                        acceptAll( translationUnit, impl );
307                }
[9243cc91]308
309          private:
310                StructDecl* monitor_decl = nullptr;
[ef42b143]311                StructDecl* guard_decl = nullptr;
[549c006]312                StructDecl* dtor_guard_decl = nullptr;
[ab8c6a6]313                StructDecl* thread_guard_decl = nullptr;
[97e3296]314
315                static std::unique_ptr< Type > generic_func;
[64adb03]316        };
317
[97e3296]318        std::unique_ptr< Type > MutexKeyword::generic_func = std::unique_ptr< Type >(
319                new FunctionType(
320                        noQualifiers,
321                        true
322                )
323        );
324
[bd4d011]325        //-----------------------------------------------------------------------------
326        //Handles mutex routines definitions :
327        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
[ac2b598]328        //                                                                       $monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
[bd4d011]329        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
330        //    /*Some code*/                                       =>           /*Some code*/
331        // }                                                               }
332        //
[2065609]333        class ThreadStarter final {
[bd4d011]334          public:
335
[2065609]336                void postvisit( FunctionDecl * decl );
[549c006]337                void previsit ( StructDecl   * decl );
[bd4d011]338
339                void addStartStatement( FunctionDecl * decl, DeclarationWithType * param );
340
341                static void implement( std::list< Declaration * > & translationUnit ) {
[2065609]342                        PassVisitor< ThreadStarter > impl;
[bd4d011]343                        acceptAll( translationUnit, impl );
344                }
[549c006]345
346          private :
347                bool thread_ctor_seen = false;
348                StructDecl * thread_decl = nullptr;
[bd4d011]349        };
350
[64adb03]351        //=============================================================================================
352        // General entry routine
353        //=============================================================================================
354        void applyKeywords( std::list< Declaration * > & translationUnit ) {
355                ThreadKeyword   ::implement( translationUnit );
356                CoroutineKeyword        ::implement( translationUnit );
357                MonitorKeyword  ::implement( translationUnit );
[427854b]358                GeneratorKeyword  ::implement( translationUnit );
359                SuspendKeyword    ::implement( translationUnit );
[bcda04c]360        }
361
362        void implementMutexFuncs( std::list< Declaration * > & translationUnit ) {
[64adb03]363                MutexKeyword    ::implement( translationUnit );
364        }
365
[bcda04c]366        void implementThreadStarter( std::list< Declaration * > & translationUnit ) {
[bd4d011]367                ThreadStarter   ::implement( translationUnit );
[bcda04c]368        }
369
[b32ada31]370        //=============================================================================================
[bcda04c]371        // Generic keyword implementation
[b32ada31]372        //=============================================================================================
[2db79e5]373        void fixupGenerics(FunctionType * func, StructDecl * decl) {
374                cloneAll(decl->parameters, func->forall);
375                for ( TypeDecl * td : func->forall ) {
376                        strict_dynamic_cast<StructInstType*>(
377                                func->parameters.front()->get_type()->stripReferences()
378                        )->parameters.push_back(
379                                new TypeExpr( new TypeInstType( noQualifiers, td->name, td ) )
380                        );
381                }
382        }
383
[9a705dc8]384        Declaration * ConcurrentSueKeyword::postmutate(StructDecl * decl) {
[9f5ecf5]385                if( decl->name == type_name && decl->body ) {
[bcda04c]386                        assert( !type_decl );
387                        type_decl = decl;
[b32ada31]388                }
[bcda04c]389                else if ( is_target(decl) ) {
[b32ada31]390                        handle( decl );
391                }
[69c5c00]392                else if ( !except_decl && exception_name == decl->name && decl->body ) {
393                        except_decl = decl;
394                }
[1c01c58]395                else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
396                        vtable_decl = decl;
397                }
398                // Might be able to get ride of is target.
399                assert( is_target(decl) == (cast_target == decl->kind) );
[9a705dc8]400                return decl;
[b32ada31]401        }
402
[6c3a5ac1]403        DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) {
[1c01c58]404                if ( type_decl && isDestructorFor( decl, type_decl ) )
405                        dtor_decl = decl;
406                else if ( vtable_name.empty() )
407                        ;
[43cedfb1]408                else if( !decl->has_body() )
409                        ;
[1c01c58]410                else if ( auto param = isMainFor( decl, cast_target ) ) {
411                        // This should never trigger.
412                        assert( vtable_decl );
413                        // Should be safe because of isMainFor.
414                        StructInstType * struct_type = static_cast<StructInstType *>(
415                                static_cast<ReferenceType *>( param->get_type() )->base );
416                        assert( struct_type );
417
[69c5c00]418                        std::list< Expression * > poly_args = { new TypeExpr( struct_type->clone() ) };
419                        ObjectDecl * vtable_object = Virtual::makeVtableInstance(
420                                vtable_decl->makeInst( poly_args ), struct_type, nullptr );
421                        declsToAddAfter.push_back( vtable_object );
422                        declsToAddAfter.push_back( Virtual::makeGetExceptionFunction(
423                                vtable_object, except_decl->makeInst( std::move( poly_args ) )
424                        ) );
[1c01c58]425                }
[6c3a5ac1]426
427                return decl;
428        }
429
[9a705dc8]430        Expression * ConcurrentSueKeyword::postmutate( KeywordCastExpr * cast ) {
431                if ( cast_target == cast->target ) {
[ac2b598]432                        // convert (thread &)t to ($thread &)*get_thread(t), etc.
[9a705dc8]433                        if( !type_decl ) SemanticError( cast, context_error );
[6c3a5ac1]434                        if( !dtor_decl ) SemanticError( cast, context_error );
[3b0c8cb]435                        assert( cast->result == nullptr );
436                        cast->set_result( new ReferenceType( noQualifiers, new StructInstType( noQualifiers, type_decl ) ) );
437                        cast->concrete_target.field  = field_name;
438                        cast->concrete_target.getter = getter_name;
[9a705dc8]439                }
440                return cast;
441        }
442
443
[bcda04c]444        void ConcurrentSueKeyword::handle( StructDecl * decl ) {
[9f5ecf5]445                if( ! decl->body ) return;
[b32ada31]446
[a16764a6]447                if( !type_decl ) SemanticError( decl, context_error );
[6c3a5ac1]448                if( !dtor_decl ) SemanticError( decl, context_error );
[b32ada31]449
[1c01c58]450                addVtableForward( decl );
[bcda04c]451                FunctionDecl * func = forwardDeclare( decl );
452                ObjectDecl * field = addField( decl );
[2f9a722]453                addRoutines( field, func );
[b32ada31]454        }
455
[1c01c58]456        void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
457                if ( vtable_decl ) {
[69c5c00]458                        std::list< Expression * > poly_args = {
[1c01c58]459                                new TypeExpr( new StructInstType( noQualifiers, decl ) ),
[69c5c00]460                        };
461                        declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
462                                vtable_decl->makeInst( poly_args ),
463                                except_decl->makeInst( poly_args )
464                        ) );
465                        declsToAddBefore.push_back( Virtual::makeVtableForward(
466                                vtable_decl->makeInst( move( poly_args ) ) ) );
[1c01c58]467                // Its only an error if we want a vtable and don't have one.
468                } else if ( ! vtable_name.empty() ) {
469                        SemanticError( decl, context_error );
470                }
471        }
472
[bcda04c]473        FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) {
474
475                StructDecl * forward = decl->clone();
476                forward->set_body( false );
477                deleteAll( forward->get_members() );
478                forward->get_members().clear();
479
[bd4d011]480                FunctionType * get_type = new FunctionType( noQualifiers, false );
[bcda04c]481                ObjectDecl * this_decl = new ObjectDecl(
482                        "this",
[ba3706f]483                        noStorageClasses,
[b32ada31]484                        LinkageSpec::Cforall,
485                        nullptr,
[83a071f9]486                        new ReferenceType(
[b32ada31]487                                noQualifiers,
[bcda04c]488                                new StructInstType(
489                                        noQualifiers,
490                                        decl
491                                )
[b32ada31]492                        ),
493                        nullptr
494                );
495
[2db79e5]496                get_type->get_parameters().push_back( this_decl->clone() );
[bd4d011]497                get_type->get_returnVals().push_back(
[e04b636]498                        new ObjectDecl(
499                                "ret",
[ba3706f]500                                noStorageClasses,
[e04b636]501                                LinkageSpec::Cforall,
502                                nullptr,
503                                new PointerType(
504                                        noQualifiers,
505                                        new StructInstType(
506                                                noQualifiers,
[bcda04c]507                                                type_decl
[e04b636]508                                        )
509                                ),
510                                nullptr
511                        )
512                );
[2db79e5]513                fixupGenerics(get_type, decl);
[b32ada31]514
[bcda04c]515                FunctionDecl * get_decl = new FunctionDecl(
516                        getter_name,
517                        Type::Static,
518                        LinkageSpec::Cforall,
[bd4d011]519                        get_type,
[bcda04c]520                        nullptr,
[a8078ee]521                        { new Attribute("const") },
[bcda04c]522                        Type::Inline
523                );
524
[bd4d011]525                FunctionDecl * main_decl = nullptr;
526
527                if( needs_main ) {
528                        FunctionType * main_type = new FunctionType( noQualifiers, false );
[bf2438c]529
[bd4d011]530                        main_type->get_parameters().push_back( this_decl->clone() );
531
532                        main_decl = new FunctionDecl(
533                                "main",
[ba3706f]534                                noStorageClasses,
[bd4d011]535                                LinkageSpec::Cforall,
536                                main_type,
537                                nullptr
538                        );
[2db79e5]539                        fixupGenerics(main_type, decl);
[bd4d011]540                }
541
[2db79e5]542                delete this_decl;
543
[2065609]544                declsToAddBefore.push_back( forward );
545                if( needs_main ) declsToAddBefore.push_back( main_decl );
546                declsToAddBefore.push_back( get_decl );
[bcda04c]547
548                return get_decl;
549        }
550
551        ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) {
552                ObjectDecl * field = new ObjectDecl(
553                        field_name,
[ba3706f]554                        noStorageClasses,
[bcda04c]555                        LinkageSpec::Cforall,
556                        nullptr,
557                        new StructInstType(
558                                noQualifiers,
559                                type_decl
560                        ),
561                        nullptr
562                );
563
564                decl->get_members().push_back( field );
565
566                return field;
567        }
568
[2f9a722]569        void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
[ba3706f]570                CompoundStmt * statement = new CompoundStmt();
[bf2438c]571                statement->push_back(
[b32ada31]572                        new ReturnStmt(
[e04b636]573                                new AddressExpr(
[bcda04c]574                                        new MemberExpr(
575                                                field,
[2db79e5]576                                                new CastExpr(
577                                                        new VariableExpr( func->get_functionType()->get_parameters().front() ),
[b81fd95]578                                                        func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone(),
579                                                        false
[2db79e5]580                                                )
[e04b636]581                                        )
[b32ada31]582                                )
583                        )
584                );
585
[bcda04c]586                FunctionDecl * get_decl = func->clone();
587
588                get_decl->set_statements( statement );
[e04b636]589
590                declsToAddAfter.push_back( get_decl );
[427854b]591        }
592
593        //=============================================================================================
594        // Suspend keyword implementation
595        //=============================================================================================
596        bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) {
597                if(isMangled(func->linkage)) return false; // the real suspend isn't mangled
598                if(func->name != "__cfactx_suspend") return false; // the real suspend has a specific name
599                if(func->type->parameters.size() != 0) return false; // Too many parameters
600                if(func->type->returnVals.size() != 0) return false; // Too many return values
601
602                return true;
[b32ada31]603        }
604
[427854b]605        void SuspendKeyword::premutate( FunctionDecl * func ) {
606                GuardValue(in_generator);
607                in_generator = nullptr;
608
609                // Is this the real suspend?
610                if(is_real_suspend(func)) {
611                        decl_suspend = decl_suspend ? decl_suspend : func;
612                        return;
613                }
614
615                // Is this the main of a generator?
[1c01c58]616                auto param = isMainFor( func, AggregateDecl::Aggregate::Generator );
[427854b]617                if(!param) return;
618
619                if(func->type->returnVals.size() != 0) SemanticError(func->location, "Generator main must return void");
620
621                in_generator = param;
622                GuardValue(labels);
623                labels.clear();
624        }
625
626        DeclarationWithType * SuspendKeyword::postmutate( FunctionDecl * func ) {
627                if( !func->statements ) return func; // Not the actual definition, don't do anything
628                if( !in_generator     ) return func; // Not in a generator, don't do anything
629                if( labels.empty()    ) return func; // Generator has no states, nothing to do, could throw a warning
630
631                // This is a generator main, we need to add the following code to the top
632                // static void * __generator_labels[] = {&&s0, &&s1, ...};
633                // goto * __generator_labels[gen.__generator_state];
634                const auto & loc = func->location;
635
636                const auto first_label = gen.newLabel("generator");
637
638                // for each label add to declaration
639                std::list<Initializer*> inits = { new SingleInit( new LabelAddressExpr( first_label ) ) };
640                for(const auto & label : labels) {
641                        inits.push_back(
642                                new SingleInit(
643                                        new LabelAddressExpr( label )
644                                )
645                        );
646                }
647                auto init = new ListInit(std::move(inits), noDesignators, true);
648                labels.clear();
649
650                // create decl
651                auto decl = new ObjectDecl(
652                        "__generator_labels",
653                        Type::StorageClasses( Type::Static ),
654                        LinkageSpec::AutoGen,
655                        nullptr,
656                        new ArrayType(
657                                Type::Qualifiers(),
658                                new PointerType(
659                                        Type::Qualifiers(),
660                                        new VoidType( Type::Qualifiers() )
661                                ),
662                                nullptr,
663                                false, false
664                        ),
665                        init
666                );
667
668                // create the goto
669                assert(in_generator);
670
671                auto go_decl = new ObjectDecl(
672                        "__generator_label",
673                        noStorageClasses,
674                        LinkageSpec::AutoGen,
675                        nullptr,
676                        new PointerType(
677                                Type::Qualifiers(),
678                                new VoidType( Type::Qualifiers() )
679                        ),
680                        new SingleInit(
681                                new UntypedExpr(
682                                        new NameExpr("?[?]"),
683                                        {
684                                                new NameExpr("__generator_labels"),
685                                                new UntypedMemberExpr(
686                                                        new NameExpr("__generator_state"),
687                                                        new VariableExpr( in_generator )
688                                                )
689                                        }
690                                )
691                        )
692                );
693                go_decl->location = loc;
694
695                auto go = new BranchStmt(
696                        new VariableExpr( go_decl ),
697                        BranchStmt::Goto
698                );
699                go->location = loc;
700                go->computedTarget->location = loc;
701
702                auto noop = new NullStmt({ first_label });
703                noop->location = loc;
704
705                // wrap everything in a nice compound
706                auto body = new CompoundStmt({
707                        new DeclStmt( decl ),
708                        new DeclStmt( go_decl ),
709                        go,
710                        noop,
711                        func->statements
712                });
713                body->location   = loc;
714                func->statements = body;
715
716                return func;
717        }
718
719        Statement * SuspendKeyword::postmutate( SuspendStmt * stmt ) {
720                SuspendStmt::Type type = stmt->type;
721                if(type == SuspendStmt::None) {
722                        // This suspend has a implicit target, find it
723                        type = in_generator ? SuspendStmt::Generator : SuspendStmt::Coroutine;
724                }
725
726                // Check that the target makes sense
727                if(!in_generator && type == SuspendStmt::Generator) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type.");
728
729                // Act appropriately
730                switch(type) {
731                        case SuspendStmt::Generator: return make_generator_suspend(stmt);
732                        case SuspendStmt::Coroutine: return make_coroutine_suspend(stmt);
733                        default: abort();
734                }
735        }
736
737        Statement * SuspendKeyword::make_generator_suspend( SuspendStmt * stmt ) {
738                assert(in_generator);
739                // Target code is :
740                //   gen.__generator_state = X;
741                //   { THEN }
742                //   return;
743                //   __gen_X:;
744
745                // Save the location and delete the old statement, we only need the location from this point on
746                auto loc = stmt->location;
747
748                // Build the label and get its index
749                auto label = make_label();
750
751                // Create the context saving statement
752                auto save = new ExprStmt( new UntypedExpr(
753                        new NameExpr( "?=?" ),
754                        {
755                                new UntypedMemberExpr(
756                                        new NameExpr("__generator_state"),
757                                        new VariableExpr( in_generator )
758                                ),
759                                new ConstantExpr(
760                                        Constant::from_int( label.idx )
761                                )
762                        }
763                ));
764                assert(save->expr);
765                save->location = loc;
766                stmtsToAddBefore.push_back( save );
767
768                // if we have a then add it here
769                auto then = stmt->then;
770                stmt->then = nullptr;
771                delete stmt;
772                if(then) stmtsToAddBefore.push_back( then );
773
774                // Create the return statement
775                auto ret = new ReturnStmt( nullptr );
776                ret->location = loc;
777                stmtsToAddBefore.push_back( ret );
778
779                // Create the null statement with the created label
780                auto noop = new NullStmt({ label.obj });
781                noop->location = loc;
782
783                // Return the null statement to take the place of the previous statement
784                return noop;
785        }
786
787        Statement * SuspendKeyword::make_coroutine_suspend( SuspendStmt * stmt ) {
788                if(stmt->then) SemanticError( stmt->location, "Compound statement following coroutines is not implemented.");
789
790                // Save the location and delete the old statement, we only need the location from this point on
791                auto loc = stmt->location;
792                delete stmt;
793
794                // Create the call expression
795                if(!decl_suspend) SemanticError( loc, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n");
796                auto expr = new UntypedExpr( VariableExpr::functionPointer( decl_suspend ) );
[e6cfa8ff]797                expr->location = loc;
[427854b]798
799                // Change this statement into a regular expr
800                assert(expr);
801                auto nstmt = new ExprStmt( expr );
[e6cfa8ff]802                nstmt->location = loc;
[427854b]803                return nstmt;
804        }
805
806
[64adb03]807        //=============================================================================================
808        // Mutex keyword implementation
809        //=============================================================================================
[97e3296]810
[2065609]811        void MutexKeyword::postvisit(FunctionDecl* decl) {
[102a58b]812
[db4d8e3]813                bool first = false;
814                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
[ab8c6a6]815                bool const isDtor = CodeGen::isDestructor( decl->name );
[64adb03]816
[ceedde6]817                // Is this function relevant to monitors
818                if( mutexArgs.empty() ) {
819                        // If this is the destructor for a monitor it must be mutex
820                        if(isDtor) {
821                                Type* ty = decl->get_functionType()->get_parameters().front()->get_type();
822
823                                // If it's a copy, it's not a mutex
824                                ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
825                                if( ! rty ) return;
826
827                                // If we are not pointing directly to a type, it's not a mutex
828                                Type* base = rty->get_base();
829                                if( dynamic_cast< ReferenceType * >( base ) ) return;
830                                if( dynamic_cast< PointerType * >( base ) ) return;
831
832                                // Check if its a struct
833                                StructInstType * baseStruct = dynamic_cast< StructInstType * >( base );
834                                if( !baseStruct ) return;
835
836                                // Check if its a monitor
837                                if(baseStruct->baseStruct->is_monitor() || baseStruct->baseStruct->is_thread())
838                                        SemanticError( decl, "destructors for structures declared as \"monitor\" must use mutex parameters\n" );
839                        }
840                        return;
841                }
[549c006]842
[ceedde6]843                // Monitors can't be constructed with mutual exclusion
844                if( CodeGen::isConstructor(decl->name) && !first ) SemanticError( decl, "constructors cannot have mutex parameters" );
[549c006]845
[ceedde6]846                // It makes no sense to have multiple mutex parameters for the destructor
[a16764a6]847                if( isDtor && mutexArgs.size() != 1 ) SemanticError( decl, "destructors can only have 1 mutex argument" );
[549c006]848
[ceedde6]849                // Make sure all the mutex arguments are monitors
[64adb03]850                for(auto arg : mutexArgs) {
851                        validate( arg );
852                }
853
[ceedde6]854                // Check if we need to instrument the body
[64adb03]855                CompoundStmt* body = decl->get_statements();
856                if( ! body ) return;
857
[ceedde6]858                // Do we have the required headers
[a16764a6]859                if( !monitor_decl || !guard_decl || !dtor_guard_decl )
[73abe95]860                        SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor.hfa>\n" );
[b32ada31]861
[ceedde6]862                // Instrument the body
[ab8c6a6]863                if ( isDtor && isThread( mutexArgs.front() ) ) {
864                        if( !thread_guard_decl ) {
865                                SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" );
866                        }
867                        addThreadDtorStatements( decl, body, mutexArgs );
868                }
869                else if ( isDtor ) {
870                        addDtorStatements( decl, body, mutexArgs );
[549c006]871                }
872                else {
[ab8c6a6]873                        addStatements( decl, body, mutexArgs );
[549c006]874                }
[64adb03]875        }
876
[2065609]877        void MutexKeyword::postvisit(StructDecl* decl) {
[102a58b]878
[ac2b598]879                if( decl->name == "$monitor" && decl->body ) {
[9243cc91]880                        assert( !monitor_decl );
881                        monitor_decl = decl;
882                }
[88d955f]883                else if( decl->name == "monitor_guard_t" && decl->body ) {
[ef42b143]884                        assert( !guard_decl );
885                        guard_decl = decl;
886                }
[88d955f]887                else if( decl->name == "monitor_dtor_guard_t" && decl->body ) {
[549c006]888                        assert( !dtor_guard_decl );
889                        dtor_guard_decl = decl;
890                }
[ab8c6a6]891                else if( decl->name == "thread_dtor_guard_t" && decl->body ) {
892                        assert( !thread_guard_decl );
893                        thread_guard_decl = decl;
894                }
[9243cc91]895        }
896
[db4d8e3]897        std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl, bool & first ) {
[64adb03]898                std::list<DeclarationWithType*> mutexArgs;
899
[db4d8e3]900                bool once = true;
[64adb03]901                for( auto arg : decl->get_functionType()->get_parameters()) {
902                        //Find mutex arguments
903                        Type* ty = arg->get_type();
[615a096]904                        if( ! ty->get_mutex() ) continue;
[64adb03]905
[db4d8e3]906                        if(once) {first = true;}
907                        once = false;
908
[64adb03]909                        //Append it to the list
910                        mutexArgs.push_back( arg );
911                }
912
913                return mutexArgs;
914        }
915
916        void MutexKeyword::validate( DeclarationWithType * arg ) {
917                Type* ty = arg->get_type();
918
919                //Makes sure it's not a copy
[870d1f0]920                ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
[a16764a6]921                if( ! rty ) SemanticError( arg, "Mutex argument must be of reference type " );
[64adb03]922
923                //Make sure the we are pointing directly to a type
[83a071f9]924                Type* base = rty->get_base();
[a16764a6]925                if( dynamic_cast< ReferenceType * >( base ) ) SemanticError( arg, "Mutex argument have exactly one level of indirection " );
926                if( dynamic_cast< PointerType * >( base ) ) SemanticError( arg, "Mutex argument have exactly one level of indirection " );
[64adb03]927
928                //Make sure that typed isn't mutex
[a16764a6]929                if( base->get_mutex() ) SemanticError( arg, "mutex keyword may only appear once per argument " );
[64adb03]930        }
931
[ab8c6a6]932        void MutexKeyword::addDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
[549c006]933                Type * arg_type = args.front()->get_type()->clone();
934                arg_type->set_mutex( false );
935
936                ObjectDecl * monitors = new ObjectDecl(
937                        "__monitor",
[ba3706f]938                        noStorageClasses,
[549c006]939                        LinkageSpec::Cforall,
940                        nullptr,
941                        new PointerType(
942                                noQualifiers,
943                                new StructInstType(
944                                        noQualifiers,
945                                        monitor_decl
946                                )
947                        ),
948                        new SingleInit( new UntypedExpr(
949                                new NameExpr( "get_monitor" ),
[b81fd95]950                                {  new CastExpr( new VariableExpr( args.front() ), arg_type, false ) }
[549c006]951                        ))
952                );
953
954                assert(generic_func);
955
956                //in reverse order :
[2bf7ef6]957                // monitor_dtor_guard_t __guard = { __monitors, func };
[549c006]958                body->push_front(
[ba3706f]959                        new DeclStmt( new ObjectDecl(
[549c006]960                                "__guard",
[ba3706f]961                                noStorageClasses,
[549c006]962                                LinkageSpec::Cforall,
963                                nullptr,
964                                new StructInstType(
965                                        noQualifiers,
966                                        dtor_guard_decl
967                                ),
968                                new ListInit(
969                                        {
970                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
[77a2994]971                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ),
972                                                new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) )
[549c006]973                                        },
974                                        noDesignators,
975                                        true
976                                )
977                        ))
978                );
979
[ac2b598]980                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
[ab8c6a6]981                body->push_front( new DeclStmt( monitors ) );
982        }
983
984        void MutexKeyword::addThreadDtorStatements(
985                        FunctionDecl*, CompoundStmt * body,
986                        const std::list<DeclarationWithType * > & args ) {
987                assert( args.size() == 1 );
988                DeclarationWithType * arg = args.front();
989                Type * arg_type = arg->get_type()->clone();
990                assert( arg_type->get_mutex() );
991                arg_type->set_mutex( false );
992
993                // thread_dtor_guard_t __guard = { this, intptr( 0 ) };
994                body->push_front(
995                        new DeclStmt( new ObjectDecl(
996                                "__guard",
997                                noStorageClasses,
998                                LinkageSpec::Cforall,
999                                nullptr,
1000                                new StructInstType(
1001                                        noQualifiers,
1002                                        thread_guard_decl
1003                                ),
1004                                new ListInit(
1005                                        {
1006                                                new SingleInit( new CastExpr( new VariableExpr( arg ), arg_type ) ),
1007                                                new SingleInit( new UntypedExpr(
1008                                                        new NameExpr( "intptr" ), {
1009                                                                new ConstantExpr( Constant::from_int( 0 ) ),
1010                                                        }
1011                                                ) ),
1012                                        },
1013                                        noDesignators,
1014                                        true
1015                                )
1016                        ))
1017                );
[549c006]1018        }
1019
[ab8c6a6]1020        void MutexKeyword::addStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
[9243cc91]1021                ObjectDecl * monitors = new ObjectDecl(
1022                        "__monitors",
[ba3706f]1023                        noStorageClasses,
[9243cc91]1024                        LinkageSpec::Cforall,
1025                        nullptr,
1026                        new ArrayType(
1027                                noQualifiers,
1028                                new PointerType(
1029                                        noQualifiers,
1030                                        new StructInstType(
1031                                                noQualifiers,
1032                                                monitor_decl
1033                                        )
1034                                ),
1035                                new ConstantExpr( Constant::from_ulong( args.size() ) ),
1036                                false,
1037                                false
1038                        ),
1039                        new ListInit(
[bd41764]1040                                map_range < std::list<Initializer*> > ( args, [](DeclarationWithType * var ){
[cb0e6de]1041                                        Type * type = var->get_type()->clone();
1042                                        type->set_mutex( false );
[9243cc91]1043                                        return new SingleInit( new UntypedExpr(
1044                                                new NameExpr( "get_monitor" ),
[b81fd95]1045                                                {  new CastExpr( new VariableExpr( var ), type, false ) }
[9243cc91]1046                                        ) );
1047                                })
1048                        )
1049                );
1050
[97e3296]1051                assert(generic_func);
1052
[2bf7ef6]1053                // in reverse order :
[97e3296]1054                // monitor_guard_t __guard = { __monitors, #, func };
[64adb03]1055                body->push_front(
[ba3706f]1056                        new DeclStmt( new ObjectDecl(
[64adb03]1057                                "__guard",
[ba3706f]1058                                noStorageClasses,
[64adb03]1059                                LinkageSpec::Cforall,
1060                                nullptr,
1061                                new StructInstType(
1062                                        noQualifiers,
[ef42b143]1063                                        guard_decl
[64adb03]1064                                ),
1065                                new ListInit(
1066                                        {
[9243cc91]1067                                                new SingleInit( new VariableExpr( monitors ) ),
[97e3296]1068                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ),
[b81fd95]1069                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
[ef42b143]1070                                        },
1071                                        noDesignators,
1072                                        true
[64adb03]1073                                )
1074                        ))
1075                );
1076
[ac2b598]1077                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
[ba3706f]1078                body->push_front( new DeclStmt( monitors) );
[64adb03]1079        }
[bd4d011]1080
1081        //=============================================================================================
1082        // General entry routine
1083        //=============================================================================================
[549c006]1084        void ThreadStarter::previsit( StructDecl * decl ) {
[ac2b598]1085                if( decl->name == "$thread" && decl->body ) {
[549c006]1086                        assert( !thread_decl );
1087                        thread_decl = decl;
1088                }
1089        }
1090
[2065609]1091        void ThreadStarter::postvisit(FunctionDecl * decl) {
[9f5ecf5]1092                if( ! CodeGen::isConstructor(decl->name) ) return;
[bd4d011]1093
[549c006]1094                Type * typeof_this = InitTweak::getTypeofThis(decl->type);
1095                StructInstType * ctored_type = dynamic_cast< StructInstType * >( typeof_this );
1096                if( ctored_type && ctored_type->baseStruct == thread_decl ) {
1097                        thread_ctor_seen = true;
1098                }
1099
[bd4d011]1100                DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
[ce8c12f]1101                auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
[bd4d011]1102                if( type && type->get_baseStruct()->is_thread() ) {
[549c006]1103                        if( !thread_decl || !thread_ctor_seen ) {
[73abe95]1104                                SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread.hfa>");
[549c006]1105                        }
1106
[bd4d011]1107                        addStartStatement( decl, param );
1108                }
1109        }
1110
1111        void ThreadStarter::addStartStatement( FunctionDecl * decl, DeclarationWithType * param ) {
1112                CompoundStmt * stmt = decl->get_statements();
1113
1114                if( ! stmt ) return;
1115
[bf2438c]1116                stmt->push_back(
[bd4d011]1117                        new ExprStmt(
1118                                new UntypedExpr(
1119                                        new NameExpr( "__thrd_start" ),
[09f357ec]1120                                        { new VariableExpr( param ), new NameExpr("main") }
[bd4d011]1121                                )
1122                        )
1123                );
1124        }
[68fe077a]1125};
[6b0b624]1126
1127// Local Variables: //
1128// mode: c //
1129// tab-width: 4 //
1130// End: //
[1c01c58]1131
Note: See TracBrowser for help on using the repository browser.