Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Corun.cpp

    rfc1a3e2 r7a780ad  
    2626
    2727struct CorunKeyword : public WithDeclsToAdd<>, public WithStmtsToAdd<> {
    28         UniqueName CorunFnNamer = "__CFA_corun_lambda_"s;
    29         UniqueName CoforFnNamer = "__CFA_cofor_lambda_"s;
    30         // UniqueName CoforFnVarNamer = "__CFA_cofor_lambda_var"s;
    31         UniqueName RunnerBlockNamer = "__CFA_corun_block_"s;
    32 
    33         string coforArgName = "__CFA_cofor_lambda_arg";
    34         string numProcsName = "__CFA_cofor_num_procs";
    35         string currProcsName = "__CFA_cofor_curr_procs";
    36         string thdArrName = "__CFA_cofor_thread_array";
    37         string loopTempName = "__CFA_cofor_loop_temp";
    38 
    39 
    40         const StructDecl * runnerBlockDecl = nullptr;
    41         const StructDecl * coforRunnerDecl = nullptr;
    42 
    43         // Finds runner_block (corun task) and cofor_runner (cofor task) decls
    44         void previsit( const StructDecl * decl ) {
    45                 if ( !decl->body ) {
    46                         return;
    47                 } else if ( "runner_block" == decl->name ) {
    48                         assert( !runnerBlockDecl );
    49                         runnerBlockDecl = decl;
    50                 } else if ( "cofor_runner" == decl->name ) {
    51                         assert( !coforRunnerDecl );
    52                         coforRunnerDecl = decl;
    53                 }
    54         }
    55 
    56         // codegen for cofor statements
    57         Stmt * postvisit( const CoforStmt * stmt ) {
    58                 if ( !runnerBlockDecl || !coforRunnerDecl )
    59                         SemanticError( stmt->location, "To use cofor statements add #include <cofor.hfa>" );
    60 
    61                 if ( stmt->inits.size() != 1 )
    62                         SemanticError( stmt->location, "Cofor statements must have a single initializer in the loop control" );
    63 
    64                 if ( !stmt->body )
    65                         return nullptr;
    66 
    67                 const CodeLocation & loc = stmt->location;
    68                 const string fnName = CoforFnNamer.newName();
    69 
    70                 CompoundStmt * body = new CompoundStmt( loc );
    71 
    72                 // push back cofor initializer to generated body
    73                 body->push_back( deepCopy( stmt->inits.at(0) ) );
    74 
    75                 CompoundStmt * fnBody = new CompoundStmt( loc );
    76 
    77                 const DeclStmt * declStmtPtr = dynamic_cast<const DeclStmt *>(stmt->inits.at(0).get());
    78                 if ( ! declStmtPtr )
    79                         SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl statement?" );
    80 
    81                 const Decl * declPtr = dynamic_cast<const Decl *>(declStmtPtr->decl.get());
    82                 if ( ! declPtr )
    83                         SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl?" );
    84 
    85                 Type * initType = new TypeofType( new NameExpr( loc, declPtr->name ) );
    86 
    87                 // Generates:
    88                 // typeof(init) __CFA_cofor_lambda_var = *((typeof(init) *)val);
    89                 fnBody->push_back( new DeclStmt( loc,
    90                         new ObjectDecl( loc,
    91                                 declPtr->name,
    92                                 initType,
    93                                 new SingleInit( loc,
    94                                         UntypedExpr::createDeref( loc,
    95                                                 new CastExpr( loc,
    96                                                         new NameExpr( loc, coforArgName ),
    97                                                         new PointerType( initType ), ExplicitCast
    98                                                 )
    99                                         )
    100                                 )
    101                         )
    102                 ));
    103 
    104                 // push rest of cofor body into loop lambda
    105                 fnBody->push_back( deepCopy( stmt->body ) );
    106 
    107                 // Generates:
    108                 // void __CFA_cofor_lambda_() {
    109                 //    typeof(init) __CFA_cofor_lambda_var = *((typeof(init) *)val);
    110                 //    stmt->body;
    111                 // }
    112                 Stmt * coforLambda = new DeclStmt( loc,
    113                         new FunctionDecl( loc,
    114                                 fnName,                                             // name
    115                                 {
    116                                         new ObjectDecl( loc,
    117                                                 coforArgName,
    118                                                 new ast::PointerType( new ast::VoidType() )
    119                                         )
    120                                 },                                                  // params
    121                                 {},                                                 // return
    122                                 fnBody   // body
    123                         )
    124                 );
    125                 body->push_back( coforLambda );
    126 
    127                 // Generates:
    128                 // unsigned __CFA_cofor_num_procs = get_proc_count();
    129                 body->push_back( new DeclStmt( loc,
    130                                 new ObjectDecl( loc,
    131                                         numProcsName,
    132                                         new BasicType( BasicKind::UnsignedInt ),
    133                                         new SingleInit( loc,
    134                                                 new UntypedExpr( loc,
    135                                                         new NameExpr( loc, "get_proc_count" ),
    136                                                         {}
    137                                                 )
    138                                         )
    139                                 )
    140                         )
    141                 );
    142 
    143                 // Generates:
    144                 // unsigned __CFA_cofor_curr_procs = 0;
    145                 body->push_back( new DeclStmt( loc,
    146                                 new ObjectDecl( loc,
    147                                         currProcsName,
    148                                         new BasicType( BasicKind::UnsignedInt ),
    149                                         new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
    150                                 )
    151                         )
    152                 );
    153 
    154                 // Generates:
    155                 // unsigned cofor_runner __CFA_cofor_thread_array[nprocs];
    156                 body->push_back( new DeclStmt( loc,
    157                                 new ObjectDecl( loc,
    158                                         thdArrName,
    159                                         new ast::ArrayType(
    160                                                 new StructInstType( coforRunnerDecl ),
    161                                                 new NameExpr( loc, numProcsName ),
    162                                                 ast::FixedLen,
    163                                                 ast::DynamicDim
    164                                         )
    165                                 )
    166                         )
    167                 );
    168 
    169                 // Generates:
    170                 // start_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs, __CFA_cofor_lambda_ );
    171                 body->push_back( new ExprStmt( loc,
    172                         new UntypedExpr( loc,
    173                                 new NameExpr( loc, "start_runners" ),
    174                                 {
    175                                         new NameExpr( loc, thdArrName ),
    176                                         new NameExpr( loc, numProcsName ),
    177                                         new NameExpr( loc, fnName )
    178                                 }
    179                         )
    180                 ));
    181 
    182                 // Generates:
    183                 // typeof(initializer) * __CFA_cofor_loop_temp = malloc();
    184                 CompoundStmt * forLoopBody = new CompoundStmt( loc );
    185                 forLoopBody->push_back( new DeclStmt( loc,
    186                                 new ObjectDecl( loc,
    187                                         loopTempName,
    188                                         new PointerType( initType ),
    189                                         new SingleInit( loc,
    190                                                 new UntypedExpr( loc,
    191                                                         new NameExpr( loc, "malloc" ),
    192                                                         {}
    193                                                 )
    194                                         )
    195                                 )
    196                         )
    197                 );
    198 
    199                 // Generates:
    200                 // *__CFA_cofor_loop_temp = initializer;
    201                 forLoopBody->push_back( new ExprStmt( loc,
    202                         UntypedExpr::createAssign( loc,
    203                                 UntypedExpr::createDeref( loc, new NameExpr( loc, loopTempName ) ),
    204                                 new NameExpr( loc, declPtr->name )
    205                         )
    206                 ));
    207 
    208                 // Generates:
    209                 // send_work( __CFA_cofor_thread_array, __CFA_cofor_num_procs,
    210                 //     __CFA_cofor_curr_procs, __CFA_cofor_loop_temp );
    211                 forLoopBody->push_back( new ExprStmt( loc,
    212                         new UntypedExpr( loc,
    213                                 new NameExpr( loc, "send_work" ),
    214                                 {
    215                                         new NameExpr( loc, thdArrName ),
    216                                         new NameExpr( loc, numProcsName ),
    217                                         new NameExpr( loc, currProcsName ),
    218                                         new NameExpr( loc, loopTempName )
    219                                 }
    220                         )
    221                 ));
    222 
    223                 body->push_back( new ForStmt( loc,
    224                         {},
    225                         deepCopy( stmt->cond ),
    226                         deepCopy( stmt->inc ),
    227                         forLoopBody
    228                 ));
    229 
    230                 // Generates:
    231                 // end_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs );
    232                 body->push_back( new ExprStmt( loc,
    233                         new UntypedExpr( loc,
    234                                 new NameExpr( loc, "end_runners" ),
    235                                 {
    236                                         new NameExpr( loc, thdArrName ),
    237                                         new NameExpr( loc, numProcsName )
    238                                 }
    239                         )
    240                 ));
    241 
    242                 return body;
    243         }
    244 
    245         // codegen for corun statements
    246         Stmt * postvisit( const CorunStmt * stmt ) {
    247                 if ( !runnerBlockDecl || !coforRunnerDecl )
    248                         SemanticError( stmt->location, "To use corun statements add #include <cofor.hfa>" );
    249 
    250                 if ( !stmt->stmt )
    251                         return nullptr;
    252 
    253                 const CodeLocation & loc = stmt->location;
    254                 const string fnName = CorunFnNamer.newName();
    255                 const string objName = RunnerBlockNamer.newName();
    256 
    257                 // Generates:
    258                 // void __CFA_corun_lambda_() { ... stmt->stmt ... }
    259                 Stmt * runnerLambda = new DeclStmt( loc,
    260                         new FunctionDecl( loc,
    261                                 fnName,                                             // name
    262                                 {},                                                 // params
    263                                 {},                                                 // return
    264                                 new CompoundStmt( loc, { deepCopy(stmt->stmt) } )   // body
    265                         )
    266                 );
    267 
    268                 // Generates:
    269                 // runner_block __CFA_corun_block_;
    270                 Stmt * objDecl = new DeclStmt( loc,
    271                         new ObjectDecl( loc,
    272                                 objName,
    273                                 new StructInstType( runnerBlockDecl )
    274                         )
    275                 );
    276 
    277                 // Generates:
    278                 // __CFA_corun_block_{ __CFA_corun_lambda_ };
    279                 Stmt * threadStart = new ExprStmt( loc,
    280                         new UntypedExpr ( loc,
    281                                 new NameExpr( loc, "?{}" ),
    282                                 {
    283                                         new NameExpr( loc, objName ),
    284                                         new NameExpr( loc, fnName )
    285                                 }
    286                         )
    287                 );
    288 
    289                 stmtsToAddBefore.push_back( runnerLambda );
    290                 stmtsToAddBefore.push_back( objDecl );
    291 
    292                 return threadStart;
    293         }
     28    UniqueName CorunFnNamer = "__CFA_corun_lambda_"s;
     29    UniqueName CoforFnNamer = "__CFA_cofor_lambda_"s;
     30    // UniqueName CoforFnVarNamer = "__CFA_cofor_lambda_var"s;
     31    UniqueName RunnerBlockNamer = "__CFA_corun_block_"s;
     32   
     33    string coforArgName = "__CFA_cofor_lambda_arg";
     34    string numProcsName = "__CFA_cofor_num_procs";
     35    string currProcsName = "__CFA_cofor_curr_procs";
     36    string thdArrName = "__CFA_cofor_thread_array";
     37    string loopTempName = "__CFA_cofor_loop_temp";
     38   
     39
     40    const StructDecl * runnerBlockDecl = nullptr;
     41    const StructDecl * coforRunnerDecl = nullptr;
     42
     43    // Finds runner_block (corun task) and cofor_runner (cofor task) decls
     44    void previsit( const StructDecl * decl ) {
     45        if ( !decl->body ) {
     46            return;
     47        } else if ( "runner_block" == decl->name ) {
     48            assert( !runnerBlockDecl );
     49            runnerBlockDecl = decl;
     50        } else if ( "cofor_runner" == decl->name ) {
     51            assert( !coforRunnerDecl );
     52            coforRunnerDecl = decl;
     53        }
     54    }
     55
     56    // codegen for cofor statements
     57    Stmt * postvisit( const CoforStmt * stmt ) {
     58        if ( !runnerBlockDecl || !coforRunnerDecl )
     59            SemanticError( stmt->location, "To use cofor statements add #include <cofor.hfa>" );
     60
     61        if ( stmt->inits.size() != 1 )
     62            SemanticError( stmt->location, "Cofor statements must have a single initializer in the loop control" );
     63
     64        if ( !stmt->body )
     65            return nullptr;
     66
     67        const CodeLocation & loc = stmt->location;
     68        const string fnName = CoforFnNamer.newName();
     69
     70        CompoundStmt * body = new CompoundStmt( loc );
     71
     72        // push back cofor initializer to generated body
     73        body->push_back( deepCopy( stmt->inits.at(0) ) );
     74
     75        CompoundStmt * fnBody = new CompoundStmt( loc );
     76
     77        const DeclStmt * declStmtPtr = dynamic_cast<const DeclStmt *>(stmt->inits.at(0).get());
     78        if ( ! declStmtPtr )
     79            SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl statement?" );
     80
     81        const Decl * declPtr = dynamic_cast<const Decl *>(declStmtPtr->decl.get());
     82        if ( ! declPtr )
     83            SemanticError( stmt->location, "Cofor statement initializer is somehow not a decl?" );
     84
     85        Type * initType = new TypeofType( new NameExpr( loc, declPtr->name ) );
     86
     87        // Generates:
     88        // typeof(init) __CFA_cofor_lambda_var = *((typeof(init) *)val);
     89        fnBody->push_back( new DeclStmt( loc,
     90            new ObjectDecl( loc,
     91                declPtr->name,
     92                initType,
     93                new SingleInit( loc,
     94                    UntypedExpr::createDeref( loc,
     95                        new CastExpr( loc,
     96                            new NameExpr( loc, coforArgName ),
     97                            new PointerType( initType ), ExplicitCast
     98                        )
     99                    )
     100                )
     101            )
     102        ));
     103
     104        // push rest of cofor body into loop lambda
     105        fnBody->push_back( deepCopy( stmt->body ) );
     106
     107        // Generates:
     108        // void __CFA_cofor_lambda_() {
     109        //    typeof(init) __CFA_cofor_lambda_var = *((typeof(init) *)val);
     110        //    stmt->body;
     111        // }
     112        Stmt * coforLambda = new DeclStmt( loc,
     113            new FunctionDecl( loc,
     114                fnName,                                             // name
     115                {
     116                    new ObjectDecl( loc,
     117                        coforArgName,
     118                        new ast::PointerType( new ast::VoidType() )
     119                    )
     120                },                                                  // params
     121                {},                                                 // return
     122                fnBody   // body
     123            )
     124        );
     125        body->push_back( coforLambda );
     126
     127        // Generates:
     128        // unsigned __CFA_cofor_num_procs = get_proc_count();
     129        body->push_back( new DeclStmt( loc,
     130                new ObjectDecl( loc,
     131                    numProcsName,
     132                    new BasicType( BasicKind::UnsignedInt ),
     133                    new SingleInit( loc,
     134                        new UntypedExpr( loc,
     135                            new NameExpr( loc, "get_proc_count" ),
     136                            {}
     137                        )
     138                    )
     139                )
     140            )
     141        );
     142
     143        // Generates:
     144        // unsigned __CFA_cofor_curr_procs = 0;
     145        body->push_back( new DeclStmt( loc,
     146                new ObjectDecl( loc,
     147                    currProcsName,
     148                    new BasicType( BasicKind::UnsignedInt ),
     149                    new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
     150                )
     151            )
     152        );
     153
     154        // Generates:
     155        // unsigned cofor_runner __CFA_cofor_thread_array[nprocs];
     156        body->push_back( new DeclStmt( loc,
     157                new ObjectDecl( loc,
     158                    thdArrName,
     159                    new ast::ArrayType(
     160                        new StructInstType( coforRunnerDecl ),
     161                        new NameExpr( loc, numProcsName ),
     162                        ast::FixedLen,
     163                        ast::DynamicDim
     164                    )
     165                )
     166            )
     167        );
     168
     169        // Generates:
     170        // start_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs, __CFA_cofor_lambda_ );
     171        body->push_back( new ExprStmt( loc,
     172            new UntypedExpr( loc,
     173                new NameExpr( loc, "start_runners" ),
     174                {
     175                    new NameExpr( loc, thdArrName ),
     176                    new NameExpr( loc, numProcsName ),
     177                    new NameExpr( loc, fnName )
     178                }
     179            )
     180        ));
     181
     182        // Generates:
     183        // typeof(initializer) * __CFA_cofor_loop_temp = malloc();
     184        CompoundStmt * forLoopBody = new CompoundStmt( loc );
     185        forLoopBody->push_back( new DeclStmt( loc,
     186                new ObjectDecl( loc,
     187                    loopTempName,
     188                    new PointerType( initType ),
     189                    new SingleInit( loc,
     190                        new UntypedExpr( loc,
     191                            new NameExpr( loc, "malloc" ),
     192                            {}
     193                        )
     194                    )
     195                )
     196            )
     197        );
     198
     199        // Generates:
     200        // *__CFA_cofor_loop_temp = initializer;
     201        forLoopBody->push_back( new ExprStmt( loc,
     202            UntypedExpr::createAssign( loc,
     203                UntypedExpr::createDeref( loc, new NameExpr( loc, loopTempName ) ),
     204                new NameExpr( loc, declPtr->name )
     205            )
     206        ));
     207
     208        // Generates:
     209        // send_work( __CFA_cofor_thread_array, __CFA_cofor_num_procs,
     210        //     __CFA_cofor_curr_procs, __CFA_cofor_loop_temp );
     211        forLoopBody->push_back( new ExprStmt( loc,
     212            new UntypedExpr( loc,
     213                new NameExpr( loc, "send_work" ),
     214                {
     215                    new NameExpr( loc, thdArrName ),
     216                    new NameExpr( loc, numProcsName ),
     217                    new NameExpr( loc, currProcsName ),
     218                    new NameExpr( loc, loopTempName )
     219                }
     220            )
     221        ));
     222
     223        body->push_back( new ForStmt( loc,
     224            {},
     225            deepCopy( stmt->cond ),
     226            deepCopy( stmt->inc ),
     227            forLoopBody
     228        ));
     229
     230        // Generates:
     231        // end_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs );
     232        body->push_back( new ExprStmt( loc,
     233            new UntypedExpr( loc,
     234                new NameExpr( loc, "end_runners" ),
     235                {
     236                    new NameExpr( loc, thdArrName ),
     237                    new NameExpr( loc, numProcsName )
     238                }
     239            )
     240        ));
     241
     242        return body;
     243    }
     244
     245    // codegen for corun statements
     246    Stmt * postvisit( const CorunStmt * stmt ) {
     247        if ( !runnerBlockDecl || !coforRunnerDecl )
     248            SemanticError( stmt->location, "To use corun statements add #include <cofor.hfa>" );
     249
     250        if ( !stmt->stmt )
     251            return nullptr;
     252
     253        const CodeLocation & loc = stmt->location;
     254        const string fnName = CorunFnNamer.newName();
     255        const string objName = RunnerBlockNamer.newName();
     256
     257        // Generates:
     258        // void __CFA_corun_lambda_() { ... stmt->stmt ... }
     259        Stmt * runnerLambda = new DeclStmt( loc,
     260            new FunctionDecl( loc,
     261                fnName,                                             // name
     262                {},                                                 // params
     263                {},                                                 // return
     264                new CompoundStmt( loc, { deepCopy(stmt->stmt) } )   // body
     265            )
     266        );
     267
     268        // Generates:
     269        // runner_block __CFA_corun_block_;
     270        Stmt * objDecl = new DeclStmt( loc,
     271            new ObjectDecl( loc,
     272                objName,
     273                new StructInstType( runnerBlockDecl )
     274            )
     275        );
     276
     277        // Generates:
     278        // __CFA_corun_block_{ __CFA_corun_lambda_ };
     279        Stmt * threadStart = new ExprStmt( loc,
     280            new UntypedExpr ( loc,
     281                new NameExpr( loc, "?{}" ),
     282                {
     283                    new NameExpr( loc, objName ),
     284                    new NameExpr( loc, fnName )
     285                }
     286            )
     287        );
     288
     289        stmtsToAddBefore.push_back( runnerLambda );
     290        stmtsToAddBefore.push_back( objDecl );
     291
     292        return threadStart;
     293    }
    294294};
    295295
    296296void implementCorun( TranslationUnit & translationUnit ) {
    297         Pass<CorunKeyword>::run( translationUnit );
     297    Pass<CorunKeyword>::run( translationUnit );
    298298}
    299299
Note: See TracChangeset for help on using the changeset viewer.