Changeset 96ddc62


Ignore:
Timestamp:
Jan 31, 2023, 2:06:18 PM (15 months ago)
Author:
caparsons <caparson@…>
Branches:
ADT, ast-experimental, master
Children:
a8e8c67
Parents:
9d0ff30
Message:

Added appropriate fwd decl hoisting to ensure there are no use before decl issues with the actor send operator

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Actors.cpp

    r9d0ff30 r96ddc62  
    2121#include "AST/TranslationUnit.hpp"
    2222#include "AST/Expr.hpp"
     23#include <algorithm>
    2324using namespace ast;
     25using namespace std;
    2426
    2527namespace Concurrency {
    2628
    2729struct CollectactorStructDecls : public ast::WithGuards {
    28     std::map<const StructDecl *, int> & actorStructDecls;
    29     std::map<const StructDecl *, int>  & messageStructDecls;
     30    unordered_set<const StructDecl *> & actorStructDecls;
     31    unordered_set<const StructDecl *>  & messageStructDecls;
    3032    const StructDecl ** requestDecl;
    3133    const EnumDecl ** allocationDecl;
     
    5153        if ( ! *actorDecl || ! *msgDecl ) return;
    5254        if ( insideStruct ) {
    53             if ( node->aggr() == *actorDecl ) {
    54                 actorStructDecls.insert({parentDecl, 1});
     55            if ( node->aggr() == *actorDecl ) { // C_TODO: see if we need to check for empty name
     56                actorStructDecls.insert( parentDecl );
    5557            } else if ( node->aggr() == *msgDecl ) {
    56                 messageStructDecls.insert({parentDecl, 1});
     58                messageStructDecls.insert( parentDecl );
    5759            }
    5860        }
     
    6062
    6163  public:
    62     CollectactorStructDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
     64    CollectactorStructDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    6365        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl )
    6466        : actorStructDecls( actorStructDecls ), messageStructDecls( messageStructDecls ), requestDecl( requestDecl ),
     
    6668};
    6769
     70// keeps track of all fwdDecls of message routines so that we can hoist them to right after the appropriate decls
     71class FwdDeclTable {
     72
     73    // tracks which decls we have seen so that we can hoist the FunctionDecl to the highest point possible
     74    struct FwdDeclData {
     75        const StructDecl * actorDecl;
     76        const StructDecl * msgDecl;
     77        FunctionDecl * fwdDecl;
     78        bool actorFound;
     79        bool msgFound;
     80
     81        bool readyToInsert() { return actorFound && msgFound; }
     82        bool foundActor() { actorFound = true; return readyToInsert(); }
     83        bool foundMsg() { msgFound = true; return readyToInsert(); }
     84
     85        FwdDeclData( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) :
     86            actorDecl(actorDecl), msgDecl(msgDecl), fwdDecl(fwdDecl), actorFound(false), msgFound(false) {}
     87    };
     88
     89    // map indexed by actor struct ptr
     90    // value is map of all FwdDeclData that contains said actor struct ptr
     91    // inner map is indexed by the message struct ptr of FwdDeclData
     92    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> actorMap;
     93
     94    // this map is the same except the outer map is indexed by message ptr and the inner is indexed by actor ptr
     95    unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> msgMap;
     96
     97    void insert( const StructDecl * decl, const StructDecl * otherDecl, unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map, FwdDeclData * data ) {
     98        auto iter = map.find( decl );
     99        if ( iter != map.end() ) { // if decl exists in map append data to existing inner map
     100            iter->second.emplace( make_pair( otherDecl, data ) );
     101        } else { // else create inner map for key
     102            map.emplace( make_pair( decl, unordered_map<const StructDecl *, FwdDeclData *>( { make_pair( otherDecl, data ) } ) ) ); // C_TODO: maybe emplace?
     103        }
     104    }
     105
     106  public:
     107    // insert decl into table so that we can fwd declare it later (average cost: O(1))
     108    void insertDecl( const StructDecl * actorDecl, const StructDecl * msgDecl, FunctionDecl * fwdDecl ) {
     109        FwdDeclData * declToInsert = new FwdDeclData( actorDecl, msgDecl, fwdDecl );
     110        insert( actorDecl, msgDecl, actorMap, declToInsert );
     111        insert( msgDecl, actorDecl, msgMap, declToInsert );
     112    }
     113
     114    // returns list of decls to insert after current struct decl
     115    // Over the entire pass the runtime of this routine is O(r) where r is the # of receive routines
     116    list<FunctionDecl *> updateDecl( const StructDecl * decl, bool isMsg ) {
     117        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & map = isMsg ? msgMap : actorMap;
     118        unordered_map<const StructDecl *, unordered_map<const StructDecl *, FwdDeclData *>> & otherMap =  isMsg ? actorMap : msgMap;
     119        auto iter = map.find( decl );
     120
     121        list<FunctionDecl *> toInsertAfter; // this is populated with decls that are ready to insert
     122        if ( iter == map.end() ) return toInsertAfter;
     123       
     124        unordered_map<const StructDecl *, FwdDeclData *> & currInnerMap = iter->second;
     125
     126        cout << "a" << endl;
     127        // iterate over inner map
     128        for ( auto innerIter = currInnerMap.begin(); innerIter != currInnerMap.end(); ) {
     129            cout << "b: " << decl->name << endl;
     130            FwdDeclData * currentDatum = innerIter->second;
     131            printf("P: %p\n", currentDatum->fwdDecl );
     132
     133            bool readyToInsert = isMsg ? currentDatum->foundMsg() : currentDatum->foundActor();
     134            if ( ! readyToInsert ) { ++innerIter; continue; }
     135           
     136            cout << "c" << endl;
     137            // readyToInsert is true so we are good to insert the forward decl of the message fn
     138            toInsertAfter.push_back( currentDatum->fwdDecl );
     139
     140            cout << "d" << endl;
     141
     142            const StructDecl * otherDecl = isMsg ? currentDatum->actorDecl : currentDatum->msgDecl;
     143
     144            // need to remove from other map before deleting
     145            // find inner map of FwdDeclData in other map ( other map is actor map if original is msg map and vice versa )
     146            auto otherMapIter = otherMap.find( otherDecl );
     147
     148            unordered_map<const StructDecl *, FwdDeclData *> & otherInnerMap = otherMapIter->second;
     149
     150            cout << "e" << endl;
     151            // find the FwdDeclData we need to remove in the other inner map
     152            auto otherInnerIter = otherInnerMap.find( decl );
     153
     154            cout << "f" << endl;
     155            // now we are safe to delete the FwdDeclData since we are done with it
     156            // have to delete before we invalidate the iterator
     157            delete currentDatum; // C_TODO: move down since this no longer iterator dependant
     158
     159            cout << "g" << endl;
     160            // remove references to deleted FwdDeclData from current inner map
     161            innerIter = currInnerMap.erase( innerIter ); // this does the increment so no explicit inc needed
     162
     163            cout << "h" << endl;
     164            // remove references to deleted FwdDeclData from other inner map
     165            otherInnerMap.erase( otherInnerIter );
     166           
     167            // if other inner map is now empty, remove key from other outer map
     168            if ( otherInnerMap.empty() )
     169                otherMap.erase( otherDecl );
     170        }
     171
     172        // if current inner map is now empty, remove key from outer map.
     173        // Have to do this after iterating for safety
     174        if ( currInnerMap.empty() )
     175            map.erase( decl );
     176
     177        return toInsertAfter;
     178    }
     179};
     180
    68181struct GenReceiveDecls : public ast::WithDeclsToAdd<> {
    69     std::map<const StructDecl *, int> & actorStructDecls;
    70     std::map<const StructDecl *, int>  & messageStructDecls;
     182    unordered_set<const StructDecl *> & actorStructDecls;
     183    unordered_set<const StructDecl *>  & messageStructDecls;
    71184    const StructDecl ** requestDecl;
    72185    const EnumDecl ** allocationDecl;
    73186    const StructDecl ** actorDecl;
    74187    const StructDecl ** msgDecl;
    75     std::vector<FunctionDecl *> & forwardDecls;
     188    FwdDeclTable & forwardDecls;
    76189
    77190        void postvisit( const FunctionDecl * decl ) {
     
    90203
    91204        // If the struct instances are derived actor and message types then generate the message send routine
    92         if ( actorStructDecls.count( arg1InstType->aggr() ) && messageStructDecls.count( arg2InstType->aggr() ) ) {
     205        auto actorIter = actorStructDecls.find( arg1InstType->aggr() );
     206        auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
     207        if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
    93208
    94209            // check that we have found all the decls we need from <actor.hfa>
     
    225340           
    226341            // forward decls to resolve use before decl problem for '|' routines
    227             forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
     342            forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
     343            // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
    228344
    229345            sendOperatorFunction->stmts = sendBody;
     
    233349
    234350  public:
    235     GenReceiveDecls( std::map<const StructDecl *, int> & actorStructDecls, std::map<const StructDecl *, int> & messageStructDecls,
     351    GenReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    236352        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
    237         std::vector<FunctionDecl *> & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     353        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    238354        requestDecl(requestDecl), allocationDecl(allocationDecl), actorDecl(actorDecl), msgDecl(msgDecl), forwardDecls(forwardDecls) {}
    239355};
    240356
    241357struct GenFwdDecls : public ast::WithDeclsToAdd<> {
    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             }
     358    unordered_set<const StructDecl *> & actorStructDecls;
     359    unordered_set<const StructDecl *>  & messageStructDecls;
     360    FwdDeclTable & forwardDecls;
     361
     362    void postvisit( const StructDecl * decl ) {
     363        list<FunctionDecl *> toAddAfter;
     364        auto actorIter = actorStructDecls.find( decl );
     365        if ( actorIter != actorStructDecls.end() ) { // this is a derived actor decl
     366            // get list of fwd decls that we can now insert
     367            toAddAfter = forwardDecls.updateDecl( decl, false );
     368
     369            // get rid of decl from actorStructDecls since we no longer need it
     370            actorStructDecls.erase( actorIter );
     371        } else {
     372            auto messageIter = messageStructDecls.find( decl );
     373            if ( messageIter == messageStructDecls.end() ) return;
     374
     375            toAddAfter = forwardDecls.updateDecl( decl, true );
     376
     377            // get rid of decl from messageStructDecls since we no longer need it
     378            messageStructDecls.erase( messageIter );
     379        }
     380
     381        // add the fwd decls to declsToAddAfter
     382        for ( FunctionDecl * func : toAddAfter ) {
     383            declsToAddAfter.push_back( func );
    268384        }
    269385    }
    270386
    271387  public:
    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) {}
     388    GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     389        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     390        forwardDecls(forwardDecls) {}
    275391};
    276392
    277393void implementActors( TranslationUnit & translationUnit ) {
    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;
     394    // unordered_maps to collect all derived actor and message types
     395    unordered_set<const StructDecl *> actorStructDecls;
     396    unordered_set<const StructDecl *> messageStructDecls;
     397    FwdDeclTable forwardDecls;
    282398
    283399    // for storing through the passes
Note: See TracChangeset for help on using the changeset viewer.