Ignore:
Timestamp:
Apr 19, 2024, 2:36:52 PM (3 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
ba97ebf
Parents:
b9b6efb
Message:

Style update. Focused on indentation and trailing whitespace.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Actors.cpp

    rb9b6efb rfc1a3e2  
    2828
    2929struct CollectactorStructDecls : public ast::WithGuards {
    30     unordered_set<const StructDecl *> & actorStructDecls;
    31     unordered_set<const StructDecl *>  & messageStructDecls;
    32     const StructDecl ** requestDecl;
    33     const EnumDecl ** allocationDecl;
    34     const StructDecl ** actorDecl;
    35     const StructDecl ** msgDecl;
    36     StructDecl * parentDecl;
    37     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
    41     void previsit( const EnumDecl * decl ) {
    42         if( decl->name == "allocation" ) *allocationDecl = decl;
    43     }
    44 
    45     // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
    46     void previsit( const StructDecl * decl ) {
    47         if ( !decl->body ) return;
    48         if ( decl->name == "actor" ) {
    49             actorStructDecls.insert( decl ); // skip inserting fwd decl
    50             *actorDecl = decl;
    51         } else if( decl->name == "message" ) {
    52             messageStructDecls.insert( decl ); // skip inserting fwd decl
    53             *msgDecl = decl;
    54         } else if( decl->name == "request" ) *requestDecl = decl;
    55         else {
    56             GuardValue(insideStruct);
    57             insideStruct = true;
    58             parentDecl = mutate( decl );
    59         }
    60         }
    61 
    62     // this catches structs of the form:
    63     //     struct dummy_actor { actor a; };
    64     // since they should be:
    65     //     struct dummy_actor { inline actor; };
    66     void previsit ( const ObjectDecl * decl ) {
    67         if ( insideStruct && ! decl->name.empty() ) {
    68             GuardValue(namedDecl);
    69             namedDecl = true;
    70         }
    71     }
    72 
    73     // this collects the derived actor and message struct decl ptrs
    74     void postvisit( const StructInstType * node ) {
    75         if ( ! *actorDecl || ! *msgDecl ) return;
    76         if ( insideStruct && !namedDecl ) {
    77             auto actorIter = actorStructDecls.find( node->aggr() );   
    78             if ( actorIter != actorStructDecls.end() ) {
    79                 actorStructDecls.insert( parentDecl );
    80                 return;
    81             }
    82             auto messageIter = messageStructDecls.find( node->aggr() );
    83             if ( messageIter != messageStructDecls.end() ) {
    84                 messageStructDecls.insert( parentDecl );
    85             }
    86         }
     30        unordered_set<const StructDecl *> & actorStructDecls;
     31        unordered_set<const StructDecl *>  & messageStructDecls;
     32        const StructDecl ** requestDecl;
     33        const EnumDecl ** allocationDecl;
     34        const StructDecl ** actorDecl;
     35        const StructDecl ** msgDecl;
     36        StructDecl * parentDecl;
     37        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
     41        void previsit( const EnumDecl * decl ) {
     42                if( decl->name == "allocation" ) *allocationDecl = decl;
     43        }
     44
     45        // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
     46        void previsit( const StructDecl * decl ) {
     47                if ( !decl->body ) return;
     48                if ( decl->name == "actor" ) {
     49                        actorStructDecls.insert( decl ); // skip inserting fwd decl
     50                        *actorDecl = decl;
     51                } else if( decl->name == "message" ) {
     52                        messageStructDecls.insert( decl ); // skip inserting fwd decl
     53                        *msgDecl = decl;
     54                } else if( decl->name == "request" ) *requestDecl = decl;
     55                else {
     56                        GuardValue(insideStruct);
     57                        insideStruct = true;
     58                        parentDecl = mutate( decl );
     59                }
     60        }
     61
     62        // this catches structs of the form:
     63        //     struct dummy_actor { actor a; };
     64        // since they should be:
     65        //     struct dummy_actor { inline actor; };
     66        void previsit ( const ObjectDecl * decl ) {
     67                if ( insideStruct && ! decl->name.empty() ) {
     68                        GuardValue(namedDecl);
     69                        namedDecl = true;
     70                }
     71        }
     72
     73        // this collects the derived actor and message struct decl ptrs
     74        void postvisit( const StructInstType * node ) {
     75                if ( ! *actorDecl || ! *msgDecl ) return;
     76                if ( insideStruct && !namedDecl ) {
     77                        auto actorIter = actorStructDecls.find( node->aggr() );
     78                        if ( actorIter != actorStructDecls.end() ) {
     79                                actorStructDecls.insert( parentDecl );
     80                                return;
     81                        }
     82                        auto messageIter = messageStructDecls.find( node->aggr() );
     83                        if ( messageIter != messageStructDecls.end() ) {
     84                                messageStructDecls.insert( parentDecl );
     85                        }
     86                }
    8787        }
    8888
    8989  public:
    90     CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    91         const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl )
    92         : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ),
    93         allocationDecl( allocationDecl ), actorDecl(actorDecl), msgDecl(msgDecl) {}
     90        CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     91                const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl )
     92                : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ),
     93                allocationDecl( allocationDecl ), actorDecl(actorDecl), msgDecl(msgDecl) {}
    9494};
    9595
     
    9797class FwdDeclTable {
    9898
    99     // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
    100     struct FwdDeclData {
    101         const StructDecl * actorDecl;
    102         const StructDecl * msgDecl;
    103         FunctionDecl * fwdDecl;
    104         bool actorFound;
    105         bool msgFound;
    106 
    107         bool readyToInsert() { return actorFound && msgFound; }
    108         bool foundActor() { actorFound = true; return readyToInsert(); }
    109         bool foundMsg() { msgFound = true; return readyToInsert(); }
    110 
    111         FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
    112             actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
    113     };
    114 
    115     // map indexed by actor struct ptr
    116     // value is map of all FwdDeclData that contains said actor struct ptr
    117     // inner map is indexed by the message struct ptr of FwdDeclData
    118     unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
    119 
    120     // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
    121     unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
    122 
    123     void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
    124         auto iter = map.find( decl );
    125         if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
    126             iter->second.emplace( make_pair( otherDecl, data ) );
    127         } else { // else create inner map for key
    128             map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
    129         }
    130     }
     99        // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
     100        struct FwdDeclData {
     101                const StructDecl * actorDecl;
     102                const StructDecl * msgDecl;
     103                FunctionDecl * fwdDecl;
     104                bool actorFound;
     105                bool msgFound;
     106
     107                bool readyToInsert() { return actorFound && msgFound; }
     108                bool foundActor() { actorFound = true; return readyToInsert(); }
     109                bool foundMsg() { msgFound = true; return readyToInsert(); }
     110
     111                FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
     112                        actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
     113        };
     114
     115        // map indexed by actor struct ptr
     116        // value is map of all FwdDeclData that contains said actor struct ptr
     117        // inner map is indexed by the message struct ptr of FwdDeclData
     118        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
     119
     120        // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
     121        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
     122
     123        void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
     124                auto iter = map.find( decl );
     125                if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
     126                        iter->second.emplace( make_pair( otherDecl, data ) );
     127                } else { // else create inner map for key
     128                        map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) );
     129                }
     130        }
    131131
    132132  public:
    133     // insert decl into table so that we can fwd declare it later (average cost: O(1))
    134     void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
    135         FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
    136         insert( actorDecl, msgDecl, actorMap, declToInsert );
    137         insert( msgDecl, actorDecl, msgMap, declToInsert );
    138     }
    139 
    140     // returns list of decls to insert after current struct decl
    141     // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
    142     list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
    143         unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
    144         unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
    145         auto iter = map.find( decl );
    146         list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
    147         if ( iter == map.end() ) return toInsertAfter;
    148        
    149         // iterate over inner map
    150         unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
    151         for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
    152             FwdDeclData * currentDatum = innerIter->second;
    153             bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
    154             if ( ! readyToInsert ) { ++innerIter; continue; }
    155            
    156             // readyToInsert is true so we are good to insert the forward decl of the message fn
    157             toInsertAfter.push_back( currentDatum->fwdDecl );
    158 
    159             // need to remove from other map before deleting
    160             // find inner map in other map ( other map is actor map if original is msg map and vice versa )
    161             const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
    162             auto otherMapIter = otherMap.find( otherDecl );
    163 
    164             unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
    165 
    166             // find the FwdDeclData we need to remove in the other inner map
    167             auto otherInnerIter = otherInnerMap.find( decl );
    168 
    169             // remove references to deleted FwdDeclData from current inner map
    170             innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
    171 
    172             // remove references to deleted FwdDeclData from other inner map
    173             otherInnerMap.erase( otherInnerIter );
    174            
    175             // if other inner map is now empty, remove key from other outer map
    176             if ( otherInnerMap.empty() )
    177                 otherMap.erase( otherDecl );
    178 
    179             // now we are safe to delete the FwdDeclData since we are done with it
    180             // and we have removed all references to it from our data structures
    181             delete currentDatum;
    182         }
    183 
    184         // if current inner map is now empty, remove key from outer map.
    185         // Have to do this after iterating for safety
    186         if ( currInnerMap.empty() )
    187             map.erase( decl );
    188 
    189         return toInsertAfter;
    190     }
     133        // insert decl into table so that we can fwd declare it later (average cost: O(1))
     134        void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
     135                FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
     136                insert( actorDecl, msgDecl, actorMap, declToInsert );
     137                insert( msgDecl, actorDecl, msgMap, declToInsert );
     138        }
     139
     140        // returns list of decls to insert after current struct decl
     141        // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
     142        list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
     143                unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
     144                unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
     145                auto iter = map.find( decl );
     146                list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
     147                if ( iter == map.end() ) return toInsertAfter;
     148
     149                // iterate over inner map
     150                unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
     151                for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
     152                        FwdDeclData * currentDatum = innerIter->second;
     153                        bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
     154                        if ( ! readyToInsert ) { ++innerIter; continue; }
     155
     156                        // readyToInsert is true so we are good to insert the forward decl of the message fn
     157                        toInsertAfter.push_back( currentDatum->fwdDecl );
     158
     159                        // need to remove from other map before deleting
     160                        // find inner map in other map ( other map is actor map if original is msg map and vice versa )
     161                        const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
     162                        auto otherMapIter = otherMap.find( otherDecl );
     163
     164                        unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
     165
     166                        // find the FwdDeclData we need to remove in the other inner map
     167                        auto otherInnerIter = otherInnerMap.find( decl );
     168
     169                        // remove references to deleted FwdDeclData from current inner map
     170                        innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
     171
     172                        // remove references to deleted FwdDeclData from other inner map
     173                        otherInnerMap.erase( otherInnerIter );
     174
     175                        // if other inner map is now empty, remove key from other outer map
     176                        if ( otherInnerMap.empty() )
     177                                otherMap.erase( otherDecl );
     178
     179                        // now we are safe to delete the FwdDeclData since we are done with it
     180                        // and we have removed all references to it from our data structures
     181                        delete currentDatum;
     182                }
     183
     184                // if current inner map is now empty, remove key from outer map.
     185                // Have to do this after iterating for safety
     186                if ( currInnerMap.empty() )
     187                        map.erase( decl );
     188
     189                return toInsertAfter;
     190        }
    191191};
    192192
    193193// generates the definitions of send operators for actors
    194 // collects data needed for next pass that does the circular defn resolution 
     194// collects data needed for next pass that does the circular defn resolution
    195195//     for message send operators (via table above)
    196196struct GenFuncsCreateTables : public ast::WithDeclsToAdd<> {
    197     unordered_set<const StructDecl *> & actorStructDecls;
    198     unordered_set<const StructDecl *>  & messageStructDecls;
    199     const StructDecl ** requestDecl;
    200     const EnumDecl ** allocationDecl;
    201     const StructDecl ** actorDecl;
    202     const StructDecl ** msgDecl;
    203     FwdDeclTable & forwardDecls;
    204 
    205     // generates the operator for actor message sends
     197        unordered_set<const StructDecl *> & actorStructDecls;
     198        unordered_set<const StructDecl *>  & messageStructDecls;
     199        const StructDecl ** requestDecl;
     200        const EnumDecl ** allocationDecl;
     201        const StructDecl ** actorDecl;
     202        const StructDecl ** msgDecl;
     203        FwdDeclTable & forwardDecls;
     204
     205        // generates the operator for actor message sends
    206206        void postvisit( const FunctionDecl * decl ) {
    207         // return if not of the form receive( param1, param2 ) or if it is a forward decl
    208         if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
    209 
    210         // the params should be references
    211         const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
    212         const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
    213         if ( !derivedActorRef || !derivedMsgRef ) return;
    214 
    215         // the references should be to struct instances
    216         const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
    217         const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
    218         if ( !arg1InstType || !arg2InstType ) return;
    219 
    220         // If the struct instances are derived actor and message types then generate the message send routine
    221         auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
    222         auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
    223         if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
    224             //////////////////////////////////////////////////////////////////////
    225             // The following generates this wrapper for all receive(derived_actor &, derived_msg &) functions
    226             /* base_actor and base_msg are output params
    227             static inline allocation __CFA_receive_wrap( derived_actor & receiver, derived_msg & msg, actor ** base_actor, message ** base_msg ) {
    228                 base_actor = &receiver;
    229                 base_msg = &msg;
    230                 return receive( receiver, msg );
    231             }
    232             */
    233             CompoundStmt * wrapBody = new CompoundStmt( decl->location );
    234 
    235             // generates: base_actor = &receiver;
    236             wrapBody->push_back( new ExprStmt( decl->location,
    237                 UntypedExpr::createAssign( decl->location,
    238                     UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_actor" ) ),
    239                     new AddressExpr( decl->location, new NameExpr( decl->location, "receiver" ) )
    240                 )
    241             ));
    242 
    243             // generates: base_msg = &msg;
    244             wrapBody->push_back( new ExprStmt( decl->location,
    245                 UntypedExpr::createAssign( decl->location,
    246                     UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_msg" ) ),
    247                     new AddressExpr( decl->location, new NameExpr( decl->location, "msg" ) )
    248                 )
    249             ));
    250 
    251             // generates: return receive( receiver, msg );
    252             wrapBody->push_back( new ReturnStmt( decl->location,
    253                 new UntypedExpr ( decl->location,
    254                     new NameExpr( decl->location, "receive" ),
    255                     {
    256                         new NameExpr( decl->location, "receiver" ),
    257                         new NameExpr( decl->location, "msg" )
    258                     }
    259                 )
    260             ));
    261 
    262             // create receive wrapper to extract base message and actor pointer
    263             // put it all together into the complete function decl from above
    264             FunctionDecl * receiveWrapper = new FunctionDecl(
    265                 decl->location,
    266                 "__CFA_receive_wrap",
    267                 {
    268                     new ObjectDecl(
    269                         decl->location,
    270                         "receiver",
    271                         ast::deepCopy( derivedActorRef )
    272                     ),
    273                     new ObjectDecl(
    274                         decl->location,
    275                         "msg",
    276                         ast::deepCopy( derivedMsgRef )
    277                     ),
    278                     new ObjectDecl(
    279                         decl->location,
    280                         "base_actor",
    281                         new PointerType( new PointerType( new StructInstType( *actorDecl ) ) )
    282                     ),
    283                     new ObjectDecl(
    284                         decl->location,
    285                         "base_msg",
    286                         new PointerType( new PointerType( new StructInstType( *msgDecl ) ) )
    287                     )
    288                 },                      // params
    289                 {
    290                     new ObjectDecl(
    291                         decl->location,
    292                         "__CFA_receive_wrap_ret",
    293                         new EnumInstType( *allocationDecl )
    294                     )
    295                 },
    296                 wrapBody,               // body
    297                 { Storage::Static },    // storage
    298                 Linkage::Cforall,       // linkage
    299                 {},                     // attributes
    300                 { Function::Inline }
    301             );
    302 
    303             declsToAddAfter.push_back( receiveWrapper );
    304 
    305             //////////////////////////////////////////////////////////////////////
    306             // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions
    307             /*
    308                 static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) {
    309                     request new_req;
    310                     allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
    311                     __receive_fn fn = (__receive_fn)my_work_fn;
    312                     new_req{ &receiver, &msg, fn };
    313                     send( receiver, new_req );
    314                     return receiver;
    315                 }
    316             */
    317             CompoundStmt * sendBody = new CompoundStmt( decl->location );
    318 
    319             // Generates: request new_req;
    320             sendBody->push_back( new DeclStmt(
    321                 decl->location,
    322                 new ObjectDecl(
    323                     decl->location,
    324                     "new_req",
    325                     new StructInstType( *requestDecl )
    326                 )
    327             ));
    328            
    329             // Function type is: allocation (*)( derived_actor &, derived_msg &, actor **, message ** )
    330             FunctionType * derivedReceive = new FunctionType();
    331             derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) );
    332             derivedReceive->params.push_back( ast::deepCopy( derivedMsgRef ) );
    333             derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
    334             derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
    335             derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
    336 
    337             // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg &, actor **, message ** ) = receive;
    338             sendBody->push_back( new DeclStmt(
    339                 decl->location,
    340                 new ObjectDecl(
    341                     decl->location,
    342                     "my_work_fn",
    343                     new PointerType( derivedReceive ),
    344                     new SingleInit( decl->location, new NameExpr( decl->location, "__CFA_receive_wrap" ) )
    345                 )
    346             ));
    347 
    348             // Function type is: allocation (*)( actor &, message & )
    349             FunctionType * genericReceive = new FunctionType();
    350             genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) );
    351             genericReceive->params.push_back( new ReferenceType( new StructInstType( *msgDecl ) ) );
    352             genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
    353             genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
    354             genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
    355 
    356             // Generates: allocation (*fn)( actor &, message & ) = (allocation (*)( actor &, message & ))my_work_fn;
    357             // More readable synonymous code:
    358             //     typedef allocation (*__receive_fn)(actor &, message &);
    359             //     __receive_fn fn = (__receive_fn)my_work_fn;
    360             sendBody->push_back( new DeclStmt(
    361                 decl->location,
    362                 new ObjectDecl(
    363                     decl->location,
    364                     "fn",
    365                     new PointerType( genericReceive ),
    366                     new SingleInit( decl->location,
    367                         new CastExpr( decl->location, new NameExpr( decl->location, "my_work_fn" ), new PointerType( genericReceive ), ExplicitCast )
    368                     )
    369                 )
    370             ));
    371 
    372             // Generates: new_req{ (actor *)&receiver, (message *)&msg, fn };
    373             sendBody->push_back( new ExprStmt(
    374                 decl->location,
     207                // return if not of the form receive( param1, param2 ) or if it is a forward decl
     208                if ( decl->name != "receive" || decl->params.size() != 2 || !decl->stmts ) return;
     209
     210                // the params should be references
     211                const ReferenceType * derivedActorRef = dynamic_cast<const ReferenceType *>(decl->params.at(0)->get_type());
     212                const ReferenceType * derivedMsgRef = dynamic_cast<const ReferenceType *>(decl->params.at(1)->get_type());
     213                if ( !derivedActorRef || !derivedMsgRef ) return;
     214
     215                // the references should be to struct instances
     216                const StructInstType * arg1InstType = dynamic_cast<const StructInstType *>(derivedActorRef->base.get());
     217                const StructInstType * arg2InstType = dynamic_cast<const StructInstType *>(derivedMsgRef->base.get());
     218                if ( !arg1InstType || !arg2InstType ) return;
     219
     220                // If the struct instances are derived actor and message types then generate the message send routine
     221                auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
     222                auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
     223                if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
     224                        //////////////////////////////////////////////////////////////////////
     225                        // The following generates this wrapper for all receive(derived_actor &, derived_msg &) functions
     226                        /* base_actor and base_msg are output params
     227                        static inline allocation __CFA_receive_wrap( derived_actor & receiver, derived_msg & msg, actor ** base_actor, message ** base_msg ) {
     228                                base_actor = &receiver;
     229                                base_msg = &msg;
     230                                return receive( receiver, msg );
     231                        }
     232                        */
     233                        CompoundStmt * wrapBody = new CompoundStmt( decl->location );
     234
     235                        // generates: base_actor = &receiver;
     236                        wrapBody->push_back( new ExprStmt( decl->location,
     237                                UntypedExpr::createAssign( decl->location,
     238                                        UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_actor" ) ),
     239                                        new AddressExpr( decl->location, new NameExpr( decl->location, "receiver" ) )
     240                                )
     241                        ));
     242
     243                        // generates: base_msg = &msg;
     244                        wrapBody->push_back( new ExprStmt( decl->location,
     245                                UntypedExpr::createAssign( decl->location,
     246                                        UntypedExpr::createDeref( decl->location, new NameExpr( decl->location, "base_msg" ) ),
     247                                        new AddressExpr( decl->location, new NameExpr( decl->location, "msg" ) )
     248                                )
     249                        ));
     250
     251                        // generates: return receive( receiver, msg );
     252                        wrapBody->push_back( new ReturnStmt( decl->location,
     253                                new UntypedExpr ( decl->location,
     254                                        new NameExpr( decl->location, "receive" ),
     255                                        {
     256                                                new NameExpr( decl->location, "receiver" ),
     257                                                new NameExpr( decl->location, "msg" )
     258                                        }
     259                                )
     260                        ));
     261
     262                        // create receive wrapper to extract base message and actor pointer
     263                        // put it all together into the complete function decl from above
     264                        FunctionDecl * receiveWrapper = new FunctionDecl(
     265                                decl->location,
     266                                "__CFA_receive_wrap",
     267                                {
     268                                        new ObjectDecl(
     269                                                decl->location,
     270                                                "receiver",
     271                                                ast::deepCopy( derivedActorRef )
     272                                        ),
     273                                        new ObjectDecl(
     274                                                decl->location,
     275                                                "msg",
     276                                                ast::deepCopy( derivedMsgRef )
     277                                        ),
     278                                        new ObjectDecl(
     279                                                decl->location,
     280                                                "base_actor",
     281                                                new PointerType( new PointerType( new StructInstType( *actorDecl ) ) )
     282                                        ),
     283                                        new ObjectDecl(
     284                                                decl->location,
     285                                                "base_msg",
     286                                                new PointerType( new PointerType( new StructInstType( *msgDecl ) ) )
     287                                        )
     288                                },                      // params
     289                                {
     290                                        new ObjectDecl(
     291                                                decl->location,
     292                                                "__CFA_receive_wrap_ret",
     293                                                new EnumInstType( *allocationDecl )
     294                                        )
     295                                },
     296                                wrapBody,               // body
     297                                { Storage::Static },    // storage
     298                                Linkage::Cforall,       // linkage
     299                                {},                     // attributes
     300                                { Function::Inline }
     301                        );
     302
     303                        declsToAddAfter.push_back( receiveWrapper );
     304
     305                        //////////////////////////////////////////////////////////////////////
     306                        // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions
     307                        /*
     308                                static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) {
     309                                        request new_req;
     310                                        allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
     311                                        __receive_fn fn = (__receive_fn)my_work_fn;
     312                                        new_req{ &receiver, &msg, fn };
     313                                        send( receiver, new_req );
     314                                        return receiver;
     315                                }
     316                        */
     317                        CompoundStmt * sendBody = new CompoundStmt( decl->location );
     318
     319                        // Generates: request new_req;
     320                        sendBody->push_back( new DeclStmt(
     321                                decl->location,
     322                                new ObjectDecl(
     323                                        decl->location,
     324                                        "new_req",
     325                                        new StructInstType( *requestDecl )
     326                                )
     327                        ));
     328
     329                        // Function type is: allocation (*)( derived_actor &, derived_msg &, actor **, message ** )
     330                        FunctionType * derivedReceive = new FunctionType();
     331                        derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) );
     332                        derivedReceive->params.push_back( ast::deepCopy( derivedMsgRef ) );
     333                        derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
     334                        derivedReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
     335                        derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
     336
     337                        // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg &, actor **, message ** ) = receive;
     338                        sendBody->push_back( new DeclStmt(
     339                                decl->location,
     340                                new ObjectDecl(
     341                                        decl->location,
     342                                        "my_work_fn",
     343                                        new PointerType( derivedReceive ),
     344                                        new SingleInit( decl->location, new NameExpr( decl->location, "__CFA_receive_wrap" ) )
     345                                )
     346                        ));
     347
     348                        // Function type is: allocation (*)( actor &, message & )
     349                        FunctionType * genericReceive = new FunctionType();
     350                        genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) );
     351                        genericReceive->params.push_back( new ReferenceType( new StructInstType( *msgDecl ) ) );
     352                        genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *actorDecl ) ) ) );
     353                        genericReceive->params.push_back( new PointerType( new PointerType( new StructInstType( *msgDecl ) ) ) );
     354                        genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
     355
     356                        // Generates: allocation (*fn)( actor &, message & ) = (allocation (*)( actor &, message & ))my_work_fn;
     357                        // More readable synonymous code:
     358                        //     typedef allocation (*__receive_fn)(actor &, message &);
     359                        //     __receive_fn fn = (__receive_fn)my_work_fn;
     360                        sendBody->push_back( new DeclStmt(
     361                                decl->location,
     362                                new ObjectDecl(
     363                                        decl->location,
     364                                        "fn",
     365                                        new PointerType( genericReceive ),
     366                                        new SingleInit( decl->location,
     367                                                new CastExpr( decl->location, new NameExpr( decl->location, "my_work_fn" ), new PointerType( genericReceive ), ExplicitCast )
     368                                        )
     369                                )
     370                        ));
     371
     372                        // Generates: new_req{ (actor *)&receiver, (message *)&msg, fn };
     373                        sendBody->push_back( new ExprStmt(
     374                                decl->location,
    375375                                new UntypedExpr (
    376                     decl->location,
     376                                        decl->location,
    377377                                        new NameExpr( decl->location, "?{}" ),
    378378                                        {
    379379                                                new NameExpr( decl->location, "new_req" ),
    380                         new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "receiver" ) ), new PointerType( new StructInstType( *actorDecl ) ), ExplicitCast ),
    381                         new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "msg" ) ), new PointerType( new StructInstType( *msgDecl ) ), ExplicitCast ),
    382                         new NameExpr( decl->location, "fn" )
     380                                                new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "receiver" ) ), new PointerType( new StructInstType( *actorDecl ) ), ExplicitCast ),
     381                                                new CastExpr( decl->location, new AddressExpr( new NameExpr( decl->location, "msg" ) ), new PointerType( new StructInstType( *msgDecl ) ), ExplicitCast ),
     382                                                new NameExpr( decl->location, "fn" )
    383383                                        }
    384384                                )
    385385                        ));
    386386
    387             // Generates: send( receiver, new_req );
    388             sendBody->push_back( new ExprStmt(
    389                 decl->location,
     387                        // Generates: send( receiver, new_req );
     388                        sendBody->push_back( new ExprStmt(
     389                                decl->location,
    390390                                new UntypedExpr (
    391                     decl->location,
     391                                        decl->location,
    392392                                        new NameExpr( decl->location, "send" ),
    393393                                        {
    394394                                                {
    395                             new NameExpr( decl->location, "receiver" ),
    396                             new NameExpr( decl->location, "new_req" )
    397                         }
     395                                                        new NameExpr( decl->location, "receiver" ),
     396                                                        new NameExpr( decl->location, "new_req" )
     397                                                }
    398398                                        }
    399399                                )
    400400                        ));
    401401
    402             // Generates: return receiver;
    403             sendBody->push_back( new ReturnStmt( decl->location, new NameExpr( decl->location, "receiver" ) ) );
    404 
    405             // put it all together into the complete function decl from above
    406             FunctionDecl * sendOperatorFunction = new FunctionDecl(
    407                 decl->location,
    408                 "?|?",
    409                 {
    410                     new ObjectDecl(
    411                         decl->location,
    412                         "receiver",
    413                         ast::deepCopy( derivedActorRef )
    414                     ),
    415                     new ObjectDecl(
    416                         decl->location,
    417                         "msg",
    418                         ast::deepCopy( derivedMsgRef )
    419                     )
    420                 },                      // params
    421                 {
    422                     new ObjectDecl(
    423                         decl->location,
    424                         "receiver_ret",
    425                         ast::deepCopy( derivedActorRef )
    426                     )
    427                 },
    428                 nullptr,               // body
    429                 { Storage::Static },    // storage
    430                 Linkage::Cforall,       // linkage
    431                 {},                     // attributes
    432                 { Function::Inline }
    433             );
    434 
    435             // forward decls to resolve use before decl problem for '|' routines
    436             forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
    437 
    438             sendOperatorFunction->stmts = sendBody;
    439             declsToAddAfter.push_back( sendOperatorFunction );
    440         }
     402                        // Generates: return receiver;
     403                        sendBody->push_back( new ReturnStmt( decl->location, new NameExpr( decl->location, "receiver" ) ) );
     404
     405                        // put it all together into the complete function decl from above
     406                        FunctionDecl * sendOperatorFunction = new FunctionDecl(
     407                                decl->location,
     408                                "?|?",
     409                                {
     410                                        new ObjectDecl(
     411                                                decl->location,
     412                                                "receiver",
     413                                                ast::deepCopy( derivedActorRef )
     414                                        ),
     415                                        new ObjectDecl(
     416                                                decl->location,
     417                                                "msg",
     418                                                ast::deepCopy( derivedMsgRef )
     419                                        )
     420                                },                      // params
     421                                {
     422                                        new ObjectDecl(
     423                                                decl->location,
     424                                                "receiver_ret",
     425                                                ast::deepCopy( derivedActorRef )
     426                                        )
     427                                },
     428                                nullptr,               // body
     429                                { Storage::Static },    // storage
     430                                Linkage::Cforall,       // linkage
     431                                {},                     // attributes
     432                                { Function::Inline }
     433                        );
     434
     435                        // forward decls to resolve use before decl problem for '|' routines
     436                        forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
     437
     438                        sendOperatorFunction->stmts = sendBody;
     439                        declsToAddAfter.push_back( sendOperatorFunction );
     440                }
    441441        }
    442442
    443443  public:
    444     GenFuncsCreateTables( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    445         const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
    446         FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    447         requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
     444        GenFuncsCreateTables( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     445                const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
     446                FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     447                requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
    448448};
    449449
     
    452452// generates the forward declarations of the send operator for actor routines
    453453struct FwdDeclOperator : public ast::WithDeclsToAdd<> {
    454     unordered_set<const StructDecl *> & actorStructDecls;
    455     unordered_set<const StructDecl *>  & messageStructDecls;
    456     FwdDeclTable & forwardDecls;
    457 
    458     // handles forward declaring the message operator
    459     void postvisit( const StructDecl * decl ) {
    460         list<FunctionDecl *> toAddAfter;
    461         auto actorIter = actorStructDecls.find( decl );
    462         if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
    463             // get list of fwd decls that we can now insert
    464             toAddAfter = forwardDecls.updateDecl( decl, false );
    465 
    466             // get rid of decl from actorStructDecls since we no longer need it
    467             actorStructDecls.erase( actorIter );
    468         } else {
    469             auto messageIter = messageStructDecls.find( decl );
    470             if ( messageIter == messageStructDecls.end() ) return;
    471 
    472             toAddAfter = forwardDecls.updateDecl( decl, true );
    473 
    474             // get rid of decl from messageStructDecls since we no longer need it
    475             messageStructDecls.erase( messageIter );
    476         }
    477 
    478         // add the fwd decls to declsToAddAfter
    479         for ( FunctionDecl * func : toAddAfter ) {
    480             declsToAddAfter.push_back( func );
    481         }
    482     }
     454        unordered_set<const StructDecl *> & actorStructDecls;
     455        unordered_set<const StructDecl *>  & messageStructDecls;
     456        FwdDeclTable & forwardDecls;
     457
     458        // handles forward declaring the message operator
     459        void postvisit( const StructDecl * decl ) {
     460                list<FunctionDecl *> toAddAfter;
     461                auto actorIter = actorStructDecls.find( decl );
     462                if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
     463                        // get list of fwd decls that we can now insert
     464                        toAddAfter = forwardDecls.updateDecl( decl, false );
     465
     466                        // get rid of decl from actorStructDecls since we no longer need it
     467                        actorStructDecls.erase( actorIter );
     468                } else {
     469                        auto messageIter = messageStructDecls.find( decl );
     470                        if ( messageIter == messageStructDecls.end() ) return;
     471
     472                        toAddAfter = forwardDecls.updateDecl( decl, true );
     473
     474                        // get rid of decl from messageStructDecls since we no longer need it
     475                        messageStructDecls.erase( messageIter );
     476                }
     477
     478                // add the fwd decls to declsToAddAfter
     479                for ( FunctionDecl * func : toAddAfter ) {
     480                        declsToAddAfter.push_back( func );
     481                }
     482        }
    483483
    484484  public:
    485     FwdDeclOperator( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    486         FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), forwardDecls(forwardDecls) {}
     485        FwdDeclOperator( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     486                FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), forwardDecls(forwardDecls) {}
    487487};
    488488
    489489void implementActors( TranslationUnit & translationUnit ) {
    490     // unordered_maps to collect all derived actor and message types
    491     unordered_set<const StructDecl *> actorStructDecls;
    492     unordered_set<const StructDecl *> messageStructDecls;
    493     FwdDeclTable forwardDecls;
    494 
    495     // for storing through the passes
    496     // these are populated with various important struct decls
    497     const StructDecl * requestDeclPtr = nullptr;
    498     const EnumDecl * allocationDeclPtr = nullptr;
    499     const StructDecl * actorDeclPtr = nullptr;
    500     const StructDecl * msgDeclPtr = nullptr;
    501 
    502     // double pointer to modify local ptrs above
    503     const StructDecl ** requestDecl = &requestDeclPtr;
    504     const EnumDecl ** allocationDecl = &allocationDeclPtr;
    505     const StructDecl ** actorDecl = &actorDeclPtr;
    506     const StructDecl ** msgDecl = &msgDeclPtr;
    507 
    508     // first pass collects ptrs to allocation enum, request type, and generic receive fn typedef
    509     // also populates maps of all derived actors and messages
    510     Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
    511         allocationDecl, actorDecl, msgDecl );
    512 
    513     // check that we have found all the decls we need from <actor.hfa>, if not no need to run the rest of this pass
    514     if ( !allocationDeclPtr || !requestDeclPtr || !actorDeclPtr || !msgDeclPtr )
    515         return;
    516 
    517     // second pass locates all receive() routines that overload the generic receive fn
    518     // it then generates the appropriate operator '|' send routines for the receive routines
    519     Pass<GenFuncsCreateTables>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
    520         allocationDecl, actorDecl, msgDecl, forwardDecls );
    521 
    522     // The third pass forward declares operator '|' send routines
    523     Pass<FwdDeclOperator>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );
     490        // unordered_maps to collect all derived actor and message types
     491        unordered_set<const StructDecl *> actorStructDecls;
     492        unordered_set<const StructDecl *> messageStructDecls;
     493        FwdDeclTable forwardDecls;
     494
     495        // for storing through the passes
     496        // these are populated with various important struct decls
     497        const StructDecl * requestDeclPtr = nullptr;
     498        const EnumDecl * allocationDeclPtr = nullptr;
     499        const StructDecl * actorDeclPtr = nullptr;
     500        const StructDecl * msgDeclPtr = nullptr;
     501
     502        // double pointer to modify local ptrs above
     503        const StructDecl ** requestDecl = &requestDeclPtr;
     504        const EnumDecl ** allocationDecl = &allocationDeclPtr;
     505        const StructDecl ** actorDecl = &actorDeclPtr;
     506        const StructDecl ** msgDecl = &msgDeclPtr;
     507
     508        // first pass collects ptrs to allocation enum, request type, and generic receive fn typedef
     509        // also populates maps of all derived actors and messages
     510        Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
     511                allocationDecl, actorDecl, msgDecl );
     512
     513        // check that we have found all the decls we need from <actor.hfa>, if not no need to run the rest of this pass
     514        if ( !allocationDeclPtr || !requestDeclPtr || !actorDeclPtr || !msgDeclPtr )
     515                return;
     516
     517        // second pass locates all receive() routines that overload the generic receive fn
     518        // it then generates the appropriate operator '|' send routines for the receive routines
     519        Pass<GenFuncsCreateTables>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
     520                allocationDecl, actorDecl, msgDecl, forwardDecls );
     521
     522        // The third pass forward declares operator '|' send routines
     523        Pass<FwdDeclOperator>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );
    524524}
    525 
    526525
    527526} // namespace Concurrency
Note: See TracChangeset for help on using the changeset viewer.