Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Actors.cpp

    rccf1d99 r34ed17b  
    2121#include "AST/TranslationUnit.hpp"
    2222#include "AST/Expr.hpp"
    23 #include <algorithm>
    2423using namespace ast;
    25 using namespace std;
    2624
    2725namespace Concurrency {
    2826
    2927struct CollectactorStructDecls : public ast::WithGuards {
    30     unordered_set<const StructDecl *> & actorStructDecls;
    31     unordered_set<const StructDecl *>  & messageStructDecls;
     28    std::map<const StructDecl *, int> & actorStructDecls;
     29    std::map<const StructDecl *, int>  & messageStructDecls;
    3230    const StructDecl ** requestDecl;
    3331    const EnumDecl ** allocationDecl;
     
    3634    StructDecl * parentDecl;
    3735    bool insideStruct = false;
    38     bool namedDecl = false;
    39 
    40     // finds and sets a ptr to the Allocation enum, which is needed in the next pass
     36
    4137    void previsit( const EnumDecl * decl ) {
    4238        if( decl->name == "Allocation" ) *allocationDecl = decl;
    4339    }
    4440
    45     // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
    4641    void previsit( const StructDecl * decl ) {
    4742        GuardValue(insideStruct);
     
    5045        if( decl->name == "actor" ) *actorDecl = decl;
    5146        if( decl->name == "message" ) *msgDecl = decl;
    52         if( decl->name == "request" ) *requestDecl = decl;
     47        if( decl->name == "request" ) *requestDecl = decl;       
    5348        }
    5449
    55     // this catches structs of the form:
    56     //     struct dummy_actor { actor a; };
    57     // since they should be:
    58     //     struct dummy_actor { inline actor; };
    59     void previsit ( const ObjectDecl * decl ) {
    60         if ( insideStruct && ! decl->name.empty() ) {
    61             GuardValue(namedDecl);
    62             namedDecl = true;
    63         }
    64     }
    65 
    66     // this collects the valid actor and message struct decl pts
    6750    void postvisit( const StructInstType * node ) {
    6851        if ( ! *actorDecl || ! *msgDecl ) return;
    69         if ( insideStruct && !namedDecl ) {
     52        if ( insideStruct ) {
    7053            if ( node->aggr() == *actorDecl ) {
    71                 actorStructDecls.insert( parentDecl );
     54                actorStructDecls.insert({parentDecl, 1});
    7255            } else if ( node->aggr() == *msgDecl ) {
    73                 messageStructDecls.insert( parentDecl );
     56                messageStructDecls.insert({parentDecl, 1});
    7457            }
    7558        }
     
    7760
    7861  public:
    79     CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     62    CollectactorStructDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
    8063        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl )
    8164        : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ),
     
    8366};
    8467
    85 // keeps track of all fwdDecls of message routines so that we can hoist them to right after the appropriate decls
    86 class FwdDeclTable {
    87 
    88     // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
    89     struct FwdDeclData {
    90         const StructDecl * actorDecl;
    91         const StructDecl * msgDecl;
    92         FunctionDecl * fwdDecl;
    93         bool actorFound;
    94         bool msgFound;
    95 
    96         bool readyToInsert() { return actorFound && msgFound; }
    97         bool foundActor() { actorFound = true; return readyToInsert(); }
    98         bool foundMsg() { msgFound = true; return readyToInsert(); }
    99 
    100         FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
    101             actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
    102     };
    103 
    104     // map indexed by actor struct ptr
    105     // value is map of all FwdDeclData that contains said actor struct ptr
    106     // inner map is indexed by the message struct ptr of FwdDeclData
    107     unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
    108 
    109     // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
    110     unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
    111 
    112     void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
    113         auto iter = map.find( decl );
    114         if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
    115             iter->second.emplace( make_pair( otherDecl, data ) );
    116         } else { // else create inner map for key
    117             map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
    118         }
    119     }
    120 
    121   public:
    122     // insert decl into table so that we can fwd declare it later (average cost: O(1))
    123     void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
    124         FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
    125         insert( actorDecl, msgDecl, actorMap, declToInsert );
    126         insert( msgDecl, actorDecl, msgMap, declToInsert );
    127     }
    128 
    129     // returns list of decls to insert after current struct decl
    130     // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
    131     list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
    132         unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
    133         unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
    134         auto iter = map.find( decl );
    135         list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
    136         if ( iter == map.end() ) return toInsertAfter;
    137        
    138         // iterate over inner map
    139         unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
    140         for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
    141             FwdDeclData * currentDatum = innerIter->second;
    142             bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
    143             if ( ! readyToInsert ) { ++innerIter; continue; }
    144            
    145             // readyToInsert is true so we are good to insert the forward decl of the message fn
    146             toInsertAfter.push_back( currentDatum->fwdDecl );
    147 
    148             // need to remove from other map before deleting
    149             // find inner map in other map ( other map is actor map if original is msg map and vice versa )
    150             const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
    151             auto otherMapIter = otherMap.find( otherDecl );
    152 
    153             unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
    154 
    155             // find the FwdDeclData we need to remove in the other inner map
    156             auto otherInnerIter = otherInnerMap.find( decl );
    157 
    158             // remove references to deleted FwdDeclData from current inner map
    159             innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
    160 
    161             // remove references to deleted FwdDeclData from other inner map
    162             otherInnerMap.erase( otherInnerIter );
    163            
    164             // if other inner map is now empty, remove key from other outer map
    165             if ( otherInnerMap.empty() )
    166                 otherMap.erase( otherDecl );
    167 
    168             // now we are safe to delete the FwdDeclData since we are done with it
    169             // and we have removed all references to it from our data structures
    170             delete currentDatum;
    171         }
    172 
    173         // if current inner map is now empty, remove key from outer map.
    174         // Have to do this after iterating for safety
    175         if ( currInnerMap.empty() )
    176             map.erase( decl );
    177 
    178         return toInsertAfter;
    179     }
    180 };
    181 
    182 #define __ALLOC 0 // C_TODO: complete swap to no-alloc version
    183 
    18468struct GenReceiveDecls : public ast::WithDeclsToAdd<> {
    185     unordered_set<const StructDecl *> & actorStructDecls;
    186     unordered_set<const StructDecl *>  & messageStructDecls;
     69    std::map<const StructDecl *, int> & actorStructDecls;
     70    std::map<const StructDecl *, int>  & messageStructDecls;
    18771    const StructDecl ** requestDecl;
    18872    const EnumDecl ** allocationDecl;
    18973    const StructDecl ** actorDecl;
    19074    const StructDecl ** msgDecl;
    191     FwdDeclTable & forwardDecls;
     75    std::vector<FunctionDecl *> & forwardDecls;
    19276
    19377        void postvisit( const FunctionDecl * decl ) {
     
    20690
    20791        // If the struct instances are derived actor and message types then generate the message send routine
    208         auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
    209         auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
    210         if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
     92        if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
    21193
    21294            // check that we have found all the decls we need from <actor.hfa>
     
    225107                    return receiver;
    226108                }
    227             */ // C_TODO: update this with new no alloc version
     109            */
    228110            CompoundStmt * sendBody = new CompoundStmt( decl->location );
    229111
    230             #if __ALLOC
    231112            // Generates: request * new_req = alloc();
    232113            sendBody->push_back( new DeclStmt(
     
    239120                )
    240121            ));
    241             #else
    242             // Generates: request new_req;
    243             sendBody->push_back( new DeclStmt(
    244                 decl->location,
    245                 new ObjectDecl(
    246                     decl->location,
    247                     "new_req",
    248                     new StructInstType( *requestDecl )
    249                 )
    250             ));
    251             #endif
    252122           
    253123            // Function type is: Allocation (*)( derived_actor &, derived_msg & )
     
    290160            ));
    291161
    292             #if __ALLOC
    293162            // Generates: (*new_req){ &receiver, &msg, fn };
    294163            sendBody->push_back( new ExprStmt(
     
    320189                                )
    321190                        ));
    322             #else
    323             // Generates: new_req{ &receiver, &msg, fn };
    324             sendBody->push_back( new ExprStmt(
    325                 decl->location,
    326                                 new UntypedExpr (
    327                     decl->location,
    328                                         new NameExpr( decl->location, "?{}" ),
    329                                         {
    330                                                 new NameExpr( decl->location, "new_req" ),
    331                         new AddressExpr( new NameExpr( decl->location, "receiver" ) ),
    332                         new AddressExpr( new NameExpr( decl->location, "msg" ) ),
    333                         new NameExpr( decl->location, "fn" )
    334                                         }
    335                                 )
    336                         ));
    337 
    338             // Generates: send( receiver, new_req );
    339             sendBody->push_back( new ExprStmt(
    340                 decl->location,
    341                                 new UntypedExpr (
    342                     decl->location,
    343                                         new NameExpr( decl->location, "send" ),
    344                                         {
    345                                                 {
    346                             new NameExpr( decl->location, "receiver" ),
    347                             new NameExpr( decl->location, "new_req" )
    348                         }
    349                                         }
    350                                 )
    351                         ));
    352             #endif
    353191           
    354192            // Generates: return receiver;
     
    387225           
    388226            // forward decls to resolve use before decl problem for '|' routines
    389             forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
    390             // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
     227            forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
    391228
    392229            sendOperatorFunction->stmts = sendBody;
     
    396233
    397234  public:
    398     GenReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     235    GenReceiveDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
    399236        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
    400         FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     237        std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    401238        requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
    402239};
    403240
    404241struct GenFwdDecls : public ast::WithDeclsToAdd<> {
    405     unordered_set<const StructDecl *> & actorStructDecls;
    406     unordered_set<const StructDecl *>  & messageStructDecls;
    407     FwdDeclTable & forwardDecls;
    408 
    409     void postvisit( const StructDecl * decl ) {
    410         list<FunctionDecl *> toAddAfter;
    411         auto actorIter = actorStructDecls.find( decl );
    412         if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
    413             // get list of fwd decls that we can now insert
    414             toAddAfter = forwardDecls.updateDecl( decl, false );
    415 
    416             // get rid of decl from actorStructDecls since we no longer need it
    417             actorStructDecls.erase( actorIter );
    418         } else {
    419             auto messageIter = messageStructDecls.find( decl );
    420             if ( messageIter == messageStructDecls.end() ) return;
    421 
    422             toAddAfter = forwardDecls.updateDecl( decl, true );
    423 
    424             // get rid of decl from messageStructDecls since we no longer need it
    425             messageStructDecls.erase( messageIter );
    426         }
    427 
    428         // add the fwd decls to declsToAddAfter
    429         for ( FunctionDecl * func : toAddAfter ) {
    430             declsToAddAfter.push_back( func );
     242    std::map<const StructDecl *, int> & actorStructDecls;
     243    std::map<const StructDecl *, int>  & messageStructDecls;
     244    std::vector<FunctionDecl *> & forwardDecls;
     245    bool done;
     246
     247    void postvisit( const FunctionDecl * decl ) {
     248        if ( done ) return;
     249        // return if not of the form receive( param1, param2 ) or if it is a forward decl
     250        if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
     251
     252        // the params should be references
     253        const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
     254        const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
     255        if ( !derivedActorRef || !derivedMsgRef ) return;
     256
     257        // the references should be to struct instances
     258        const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
     259        const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
     260        if ( !arg1InstType || !arg2InstType ) return;
     261
     262        // If the struct instances are derived actor and message types then generate the message send routine
     263        if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
     264            done = true;
     265            for ( const auto & func : forwardDecls ) {
     266                declsToAddBefore.push_back( func );
     267            }
    431268        }
    432269    }
    433270
    434271  public:
    435     GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    436         FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    437         forwardDecls(forwardDecls) {}
     272    GenFwdDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
     273        std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     274        forwardDecls(forwardDecls), done(false) {}
    438275};
    439276
    440277void implementActors( TranslationUnit & translationUnit ) {
    441     // unordered_maps to collect all derived actor and message types
    442     unordered_set<const StructDecl *> actorStructDecls;
    443     unordered_set<const StructDecl *> messageStructDecls;
    444     FwdDeclTable forwardDecls;
     278    // maps to collect all derived actor and message types
     279    std::map<const StructDecl *, int> actorStructDecls;
     280    std::map<const StructDecl *, int> messageStructDecls;
     281    std::vector<FunctionDecl *> forwardDecls;
    445282
    446283    // for storing through the passes
Note: See TracChangeset for help on using the changeset viewer.