Ignore:
Timestamp:
Apr 6, 2020, 4:46:28 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
e3bc51c
Parents:
71d6bd8 (diff), 057298e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into new-ast

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Keywords.cc

    r71d6bd8 r7030dab  
    1111// Last Modified By :
    1212// Last Modified On :
    13 // Update Count     : 5
     13// Update Count     : 10
    1414//
    1515
    1616#include "Concurrency/Keywords.h"
    1717
    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
     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 "ControlStruct/LabelGenerator.h" // for LebelGenerator
     26#include "InitTweak/InitTweak.h"          // for getPointerBase
     27#include "SynTree/LinkageSpec.h"          // for Cforall
     28#include "SynTree/Constant.h"             // for Constant
     29#include "SynTree/Declaration.h"          // for StructDecl, FunctionDecl, ObjectDecl
     30#include "SynTree/Expression.h"           // for VariableExpr, ConstantExpr, Untype...
     31#include "SynTree/Initializer.h"          // for SingleInit, ListInit, Initializer ...
     32#include "SynTree/Label.h"                // for Label
     33#include "SynTree/Statement.h"            // for CompoundStmt, DeclStmt, ExprStmt
     34#include "SynTree/Type.h"                 // for StructInstType, Type, PointerType
     35#include "SynTree/Visitor.h"              // for Visitor, acceptAll
    3536
    3637class Attribute;
     
    5354          public:
    5455
    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                ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, AggregateDecl::Aggregate cast_target ) :
    5657                  type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ), cast_target( cast_target ) {}
    5758
     
    5960
    6061                Declaration * postmutate( StructDecl * decl );
     62                DeclarationWithType * postmutate( FunctionDecl * decl );
    6163
    6264                void handle( StructDecl * );
     
    7577                const std::string context_error;
    7678                bool needs_main;
    77                 KeywordCastExpr::Target cast_target;
    78 
    79                 StructDecl* type_decl = nullptr;
     79                AggregateDecl::Aggregate cast_target;
     80
     81                StructDecl   * type_decl = nullptr;
     82                FunctionDecl * dtor_decl = nullptr;
    8083        };
    8184
     
    8689        //      int data;                                  int data;
    8790        //      a_struct_t more_data;                      a_struct_t more_data;
    88         //                                =>             thread_desc __thrd_d;
     91        //                                =>             $thread __thrd_d;
    8992        // };                                        };
    90         //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
     93        //                                           static inline $thread * get_thread( MyThread * this ) { return &this->__thrd_d; }
    9194        //
    9295        class ThreadKeyword final : public ConcurrentSueKeyword {
     
    9497
    9598                ThreadKeyword() : ConcurrentSueKeyword(
    96                         "thread_desc",
     99                        "$thread",
    97100                        "__thrd",
    98101                        "get_thread",
    99                         "thread keyword requires threads to be in scope, add #include <thread.hfa>",
     102                        "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
    100103                        true,
    101                         KeywordCastExpr::Thread
     104                        AggregateDecl::Thread
    102105                )
    103106                {}
     
    118121        //      int data;                                  int data;
    119122        //      a_struct_t more_data;                      a_struct_t more_data;
    120         //                                =>             coroutine_desc __cor_d;
     123        //                                =>             $coroutine __cor_d;
    121124        // };                                        };
    122         //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
     125        //                                           static inline $coroutine * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
    123126        //
    124127        class CoroutineKeyword final : public ConcurrentSueKeyword {
     
    126129
    127130                CoroutineKeyword() : ConcurrentSueKeyword(
    128                         "coroutine_desc",
     131                        "$coroutine",
    129132                        "__cor",
    130133                        "get_coroutine",
    131                         "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>",
     134                        "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
    132135                        true,
    133                         KeywordCastExpr::Coroutine
     136                        AggregateDecl::Coroutine
    134137                )
    135138                {}
     
    144147                }
    145148        };
     149
     150
    146151
    147152        //-----------------------------------------------------------------------------
     
    150155        //      int data;                                  int data;
    151156        //      a_struct_t more_data;                      a_struct_t more_data;
    152         //                                =>             monitor_desc __mon_d;
     157        //                                =>             $monitor __mon_d;
    153158        // };                                        };
    154         //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
     159        //                                           static inline $monitor * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
    155160        //
    156161        class MonitorKeyword final : public ConcurrentSueKeyword {
     
    158163
    159164                MonitorKeyword() : ConcurrentSueKeyword(
    160                         "monitor_desc",
     165                        "$monitor",
    161166                        "__mon",
    162167                        "get_monitor",
    163                         "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>",
     168                        "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
    164169                        false,
    165                         KeywordCastExpr::Monitor
     170                        AggregateDecl::Monitor
    166171                )
    167172                {}
     
    178183
    179184        //-----------------------------------------------------------------------------
     185        //Handles generator type declarations :
     186        // generator MyGenerator {                   struct MyGenerator {
     187        //      int data;                                  int data;
     188        //      a_struct_t more_data;                      a_struct_t more_data;
     189        //                                =>             int __gen_next;
     190        // };                                        };
     191        //
     192        class GeneratorKeyword final : public ConcurrentSueKeyword {
     193          public:
     194
     195                GeneratorKeyword() : ConcurrentSueKeyword(
     196                        "$generator",
     197                        "__generator_state",
     198                        "get_generator",
     199                        "Unable to find builtin type $generator\n",
     200                        true,
     201                        AggregateDecl::Generator
     202                )
     203                {}
     204
     205                virtual ~GeneratorKeyword() {}
     206
     207                virtual bool is_target( StructDecl * decl ) override final { return decl->is_generator(); }
     208
     209                static void implement( std::list< Declaration * > & translationUnit ) {
     210                        PassVisitor< GeneratorKeyword > impl;
     211                        mutateAll( translationUnit, impl );
     212                }
     213        };
     214
     215
     216        //-----------------------------------------------------------------------------
     217        class SuspendKeyword final : public WithStmtsToAdd, public WithGuards {
     218        public:
     219                SuspendKeyword() = default;
     220                virtual ~SuspendKeyword() = default;
     221
     222                void  premutate( FunctionDecl * );
     223                DeclarationWithType * postmutate( FunctionDecl * );
     224
     225                Statement * postmutate( SuspendStmt * );
     226
     227                static void implement( std::list< Declaration * > & translationUnit ) {
     228                        PassVisitor< SuspendKeyword > impl;
     229                        mutateAll( translationUnit, impl );
     230                }
     231
     232        private:
     233                DeclarationWithType * is_main( FunctionDecl * );
     234                bool is_real_suspend( FunctionDecl * );
     235
     236                Statement * make_generator_suspend( SuspendStmt * );
     237                Statement * make_coroutine_suspend( SuspendStmt * );
     238
     239                struct LabelPair {
     240                        Label obj;
     241                        int   idx;
     242                };
     243
     244                LabelPair make_label() {
     245                        labels.push_back( gen.newLabel("generator") );
     246                        return { labels.back(), int(labels.size()) };
     247                }
     248
     249                DeclarationWithType * in_generator = nullptr;
     250                FunctionDecl * decl_suspend = nullptr;
     251                std::vector<Label> labels;
     252                ControlStruct::LabelGenerator & gen = *ControlStruct::LabelGenerator::getGenerator();
     253        };
     254
     255        //-----------------------------------------------------------------------------
    180256        //Handles mutex routines definitions :
    181257        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
    182         //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     258        //                                                                       $monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    183259        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
    184260        //    /*Some code*/                                       =>           /*Some code*/
     
    219295        //Handles mutex routines definitions :
    220296        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
    221         //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     297        //                                                                       $monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    222298        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
    223299        //    /*Some code*/                                       =>           /*Some code*/
     
    249325                CoroutineKeyword        ::implement( translationUnit );
    250326                MonitorKeyword  ::implement( translationUnit );
     327                GeneratorKeyword  ::implement( translationUnit );
     328                SuspendKeyword    ::implement( translationUnit );
    251329        }
    252330
     
    284362        }
    285363
     364        DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) {
     365                if( !type_decl ) return decl;
     366                if( !CodeGen::isDestructor( decl->name ) ) return decl;
     367
     368                auto params = decl->type->parameters;
     369                if( params.size() != 1 ) return decl;
     370
     371                auto type = dynamic_cast<ReferenceType*>( params.front()->get_type() );
     372                if( !type ) return decl;
     373
     374                auto stype = dynamic_cast<StructInstType*>( type->base );
     375                if( !stype ) return decl;
     376                if( stype->baseStruct != type_decl ) return decl;
     377
     378                if( !dtor_decl ) dtor_decl = decl;
     379                return decl;
     380        }
     381
    286382        Expression * ConcurrentSueKeyword::postmutate( KeywordCastExpr * cast ) {
    287383                if ( cast_target == cast->target ) {
    288                         // convert (thread &)t to (thread_desc &)*get_thread(t), etc.
     384                        // convert (thread &)t to ($thread &)*get_thread(t), etc.
    289385                        if( !type_decl ) SemanticError( cast, context_error );
    290                         Expression * arg = cast->arg;
    291                         cast->arg = nullptr;
    292                         delete cast;
    293                         return new CastExpr(
    294                                 UntypedExpr::createDeref(
    295                                         new UntypedExpr( new NameExpr( getter_name ), { arg } )
    296                                 ),
    297                                 new ReferenceType(
    298                                         noQualifiers,
    299                                         new StructInstType( noQualifiers, type_decl ) )
    300                                 );
     386                        if( !dtor_decl ) SemanticError( cast, context_error );
     387                        assert( cast->result == nullptr );
     388                        cast->set_result( new ReferenceType( noQualifiers, new StructInstType( noQualifiers, type_decl ) ) );
     389                        cast->concrete_target.field  = field_name;
     390                        cast->concrete_target.getter = getter_name;
    301391                }
    302392                return cast;
     
    308398
    309399                if( !type_decl ) SemanticError( decl, context_error );
     400                if( !dtor_decl ) SemanticError( decl, context_error );
    310401
    311402                FunctionDecl * func = forwardDeclare( decl );
     
    362453                        get_type,
    363454                        nullptr,
    364                         noAttributes,
     455                        { new Attribute("const") },
    365456                        Type::Inline
    366457                );
     
    431522
    432523                declsToAddAfter.push_back( get_decl );
    433 
    434                 // get_decl->fixUniqueId();
    435         }
     524        }
     525
     526        //=============================================================================================
     527        // Suspend keyword implementation
     528        //=============================================================================================
     529        DeclarationWithType * SuspendKeyword::is_main( FunctionDecl * func) {
     530                if(func->name != "main") return nullptr;
     531                if(func->type->parameters.size() != 1) return nullptr;
     532
     533                auto param = func->type->parameters.front();
     534
     535                auto type  = dynamic_cast<ReferenceType * >(param->get_type());
     536                if(!type) return nullptr;
     537
     538                auto obj   = dynamic_cast<StructInstType *>(type->base);
     539                if(!obj) return nullptr;
     540
     541                if(!obj->baseStruct->is_generator()) return nullptr;
     542
     543                return param;
     544        }
     545
     546        bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) {
     547                if(isMangled(func->linkage)) return false; // the real suspend isn't mangled
     548                if(func->name != "__cfactx_suspend") return false; // the real suspend has a specific name
     549                if(func->type->parameters.size() != 0) return false; // Too many parameters
     550                if(func->type->returnVals.size() != 0) return false; // Too many return values
     551
     552                return true;
     553        }
     554
     555        void SuspendKeyword::premutate( FunctionDecl * func ) {
     556                GuardValue(in_generator);
     557                in_generator = nullptr;
     558
     559                // Is this the real suspend?
     560                if(is_real_suspend(func)) {
     561                        decl_suspend = decl_suspend ? decl_suspend : func;
     562                        return;
     563                }
     564
     565                // Is this the main of a generator?
     566                auto param = is_main( func );
     567                if(!param) return;
     568
     569                if(func->type->returnVals.size() != 0) SemanticError(func->location, "Generator main must return void");
     570
     571                in_generator = param;
     572                GuardValue(labels);
     573                labels.clear();
     574        }
     575
     576        DeclarationWithType * SuspendKeyword::postmutate( FunctionDecl * func ) {
     577                if( !func->statements ) return func; // Not the actual definition, don't do anything
     578                if( !in_generator     ) return func; // Not in a generator, don't do anything
     579                if( labels.empty()    ) return func; // Generator has no states, nothing to do, could throw a warning
     580
     581                // This is a generator main, we need to add the following code to the top
     582                // static void * __generator_labels[] = {&&s0, &&s1, ...};
     583                // goto * __generator_labels[gen.__generator_state];
     584                const auto & loc = func->location;
     585
     586                const auto first_label = gen.newLabel("generator");
     587
     588                // for each label add to declaration
     589                std::list<Initializer*> inits = { new SingleInit( new LabelAddressExpr( first_label ) ) };
     590                for(const auto & label : labels) {
     591                        inits.push_back(
     592                                new SingleInit(
     593                                        new LabelAddressExpr( label )
     594                                )
     595                        );
     596                }
     597                auto init = new ListInit(std::move(inits), noDesignators, true);
     598                labels.clear();
     599
     600                // create decl
     601                auto decl = new ObjectDecl(
     602                        "__generator_labels",
     603                        Type::StorageClasses( Type::Static ),
     604                        LinkageSpec::AutoGen,
     605                        nullptr,
     606                        new ArrayType(
     607                                Type::Qualifiers(),
     608                                new PointerType(
     609                                        Type::Qualifiers(),
     610                                        new VoidType( Type::Qualifiers() )
     611                                ),
     612                                nullptr,
     613                                false, false
     614                        ),
     615                        init
     616                );
     617
     618                // create the goto
     619                assert(in_generator);
     620
     621                auto go_decl = new ObjectDecl(
     622                        "__generator_label",
     623                        noStorageClasses,
     624                        LinkageSpec::AutoGen,
     625                        nullptr,
     626                        new PointerType(
     627                                Type::Qualifiers(),
     628                                new VoidType( Type::Qualifiers() )
     629                        ),
     630                        new SingleInit(
     631                                new UntypedExpr(
     632                                        new NameExpr("?[?]"),
     633                                        {
     634                                                new NameExpr("__generator_labels"),
     635                                                new UntypedMemberExpr(
     636                                                        new NameExpr("__generator_state"),
     637                                                        new VariableExpr( in_generator )
     638                                                )
     639                                        }
     640                                )
     641                        )
     642                );
     643                go_decl->location = loc;
     644
     645                auto go = new BranchStmt(
     646                        new VariableExpr( go_decl ),
     647                        BranchStmt::Goto
     648                );
     649                go->location = loc;
     650                go->computedTarget->location = loc;
     651
     652                auto noop = new NullStmt({ first_label });
     653                noop->location = loc;
     654
     655                // wrap everything in a nice compound
     656                auto body = new CompoundStmt({
     657                        new DeclStmt( decl ),
     658                        new DeclStmt( go_decl ),
     659                        go,
     660                        noop,
     661                        func->statements
     662                });
     663                body->location   = loc;
     664                func->statements = body;
     665
     666                return func;
     667        }
     668
     669        Statement * SuspendKeyword::postmutate( SuspendStmt * stmt ) {
     670                SuspendStmt::Type type = stmt->type;
     671                if(type == SuspendStmt::None) {
     672                        // This suspend has a implicit target, find it
     673                        type = in_generator ? SuspendStmt::Generator : SuspendStmt::Coroutine;
     674                }
     675
     676                // Check that the target makes sense
     677                if(!in_generator && type == SuspendStmt::Generator) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type.");
     678
     679                // Act appropriately
     680                switch(type) {
     681                        case SuspendStmt::Generator: return make_generator_suspend(stmt);
     682                        case SuspendStmt::Coroutine: return make_coroutine_suspend(stmt);
     683                        default: abort();
     684                }
     685        }
     686
     687        Statement * SuspendKeyword::make_generator_suspend( SuspendStmt * stmt ) {
     688                assert(in_generator);
     689                // Target code is :
     690                //   gen.__generator_state = X;
     691                //   { THEN }
     692                //   return;
     693                //   __gen_X:;
     694
     695                // Save the location and delete the old statement, we only need the location from this point on
     696                auto loc = stmt->location;
     697
     698                // Build the label and get its index
     699                auto label = make_label();
     700
     701                // Create the context saving statement
     702                auto save = new ExprStmt( new UntypedExpr(
     703                        new NameExpr( "?=?" ),
     704                        {
     705                                new UntypedMemberExpr(
     706                                        new NameExpr("__generator_state"),
     707                                        new VariableExpr( in_generator )
     708                                ),
     709                                new ConstantExpr(
     710                                        Constant::from_int( label.idx )
     711                                )
     712                        }
     713                ));
     714                assert(save->expr);
     715                save->location = loc;
     716                stmtsToAddBefore.push_back( save );
     717
     718                // if we have a then add it here
     719                auto then = stmt->then;
     720                stmt->then = nullptr;
     721                delete stmt;
     722                if(then) stmtsToAddBefore.push_back( then );
     723
     724                // Create the return statement
     725                auto ret = new ReturnStmt( nullptr );
     726                ret->location = loc;
     727                stmtsToAddBefore.push_back( ret );
     728
     729                // Create the null statement with the created label
     730                auto noop = new NullStmt({ label.obj });
     731                noop->location = loc;
     732
     733                // Return the null statement to take the place of the previous statement
     734                return noop;
     735        }
     736
     737        Statement * SuspendKeyword::make_coroutine_suspend( SuspendStmt * stmt ) {
     738                if(stmt->then) SemanticError( stmt->location, "Compound statement following coroutines is not implemented.");
     739
     740                // Save the location and delete the old statement, we only need the location from this point on
     741                auto loc = stmt->location;
     742                delete stmt;
     743
     744                // Create the call expression
     745                if(!decl_suspend) SemanticError( loc, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n");
     746                auto expr = new UntypedExpr( VariableExpr::functionPointer( decl_suspend ) );
     747                expr->location = loc;
     748
     749                // Change this statement into a regular expr
     750                assert(expr);
     751                auto nstmt = new ExprStmt( expr );
     752                nstmt->location = loc;
     753                return nstmt;
     754        }
     755
    436756
    437757        //=============================================================================================
     
    501821        void MutexKeyword::postvisit(StructDecl* decl) {
    502822
    503                 if( decl->name == "monitor_desc" && decl->body ) {
     823                if( decl->name == "$monitor" && decl->body ) {
    504824                        assert( !monitor_decl );
    505825                        monitor_decl = decl;
     
    597917                );
    598918
    599                 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     919                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    600920                body->push_front( new DeclStmt( monitors) );
    601921        }
     
    658978                );
    659979
    660                 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     980                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    661981                body->push_front( new DeclStmt( monitors) );
    662982        }
     
    666986        //=============================================================================================
    667987        void ThreadStarter::previsit( StructDecl * decl ) {
    668                 if( decl->name == "thread_desc" && decl->body ) {
     988                if( decl->name == "$thread" && decl->body ) {
    669989                        assert( !thread_decl );
    670990                        thread_decl = decl;
     
    7011021                                new UntypedExpr(
    7021022                                        new NameExpr( "__thrd_start" ),
    703                                         { new VariableExpr( param ) }
     1023                                        { new VariableExpr( param ), new NameExpr("main") }
    7041024                                )
    7051025                        )
Note: See TracChangeset for help on using the changeset viewer.