Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Corun.cpp

    r7a780ad rfc1a3e2  
    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.