source: src/Concurrency/Corun.cpp @ 3d9d017

Last change on this file since 3d9d017 was 3d9d017, checked in by caparson <caparson@…>, 6 months ago

added cofor implementation

  • Property mode set to 100644
File size: 10.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Corun.cpp -- generate code needed by the actor system
8//
9// Author           : Colby Parsons
10// Created On       : Monday October 9 15:16:42 2023
11// Last Modified By : Colby Parsons
12// Last Modified On : Monday October 9 15:16:42 2023
13// Update Count     : 0
14//
15
16#include "AST/Decl.hpp"
17#include "AST/Expr.hpp"
18#include "AST/Pass.hpp"
19#include "AST/Stmt.hpp"
20#include "AST/TranslationUnit.hpp"
21#include "Common/UniqueName.h"
22using namespace ast;
23using namespace std;
24
25namespace Concurrency {
26
27struct 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>\n" );
60
61        if ( stmt->inits.size() != 1 )
62            SemanticError( stmt->location, "Cofor statements must have a single initializer in the loop control\n" );
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?\n" );
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?\n" );
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                {},                                                 // forall
116                {
117                    new ObjectDecl( loc,
118                        coforArgName,
119                        new ast::PointerType( new ast::VoidType() )
120                    )
121                },                                                  // params
122                {},                                                 // return
123                fnBody   // body
124            )
125        );
126        body->push_back( coforLambda );
127
128        // Generates:
129        // unsigned __CFA_cofor_num_procs = get_proc_count();
130        body->push_back( new DeclStmt( loc,
131                new ObjectDecl( loc,
132                    numProcsName,
133                    new BasicType( BasicType::Kind::UnsignedInt ),
134                    new SingleInit( loc, 
135                        new UntypedExpr( loc,
136                            new NameExpr( loc, "get_proc_count" ),
137                            {}
138                        )
139                    )
140                )
141            )
142        );
143
144        // Generates:
145        // unsigned __CFA_cofor_curr_procs = 0;
146        body->push_back( new DeclStmt( loc,
147                new ObjectDecl( loc,
148                    currProcsName,
149                    new BasicType( BasicType::Kind::UnsignedInt ),
150                    new SingleInit( loc, ConstantExpr::from_int( loc, 0 ) )
151                )
152            )
153        );
154
155        // Generates:
156        // unsigned cofor_runner __CFA_cofor_thread_array[nprocs];
157        body->push_back( new DeclStmt( loc,
158                new ObjectDecl( loc,
159                    thdArrName,
160                    new ast::ArrayType(
161                        new StructInstType( coforRunnerDecl ),
162                        new NameExpr( loc, numProcsName ),
163                        ast::FixedLen,
164                        ast::DynamicDim
165                    )
166                )
167            )
168        );
169
170        // Generates:
171        // start_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs, __CFA_cofor_lambda_ );
172        body->push_back( new ExprStmt( loc,
173            new UntypedExpr( loc,
174                new NameExpr( loc, "start_runners" ),
175                {
176                    new NameExpr( loc, thdArrName ),
177                    new NameExpr( loc, numProcsName ),
178                    new NameExpr( loc, fnName )
179                }
180            )
181        ));
182
183        // Generates:
184        // typeof(initializer) * __CFA_cofor_loop_temp = malloc();
185        CompoundStmt * forLoopBody = new CompoundStmt( loc );
186        forLoopBody->push_back( new DeclStmt( loc,
187                new ObjectDecl( loc,
188                    loopTempName,
189                    new PointerType( initType ),
190                    new SingleInit( loc, 
191                        new UntypedExpr( loc,
192                            new NameExpr( loc, "malloc" ),
193                            {}
194                        )
195                    )
196                )
197            )
198        );
199
200        // Generates:
201        // *__CFA_cofor_loop_temp = initializer;
202        forLoopBody->push_back( new ExprStmt( loc,
203            UntypedExpr::createAssign( loc,
204                UntypedExpr::createDeref( loc, new NameExpr( loc, loopTempName ) ),
205                new NameExpr( loc, declPtr->name )
206            )
207        ));
208
209        // Generates:
210        // send_work( __CFA_cofor_thread_array, __CFA_cofor_num_procs,
211        //     __CFA_cofor_curr_procs, __CFA_cofor_loop_temp );
212        forLoopBody->push_back( new ExprStmt( loc,
213            new UntypedExpr( loc,
214                new NameExpr( loc, "send_work" ),
215                {
216                    new NameExpr( loc, thdArrName ),
217                    new NameExpr( loc, numProcsName ),
218                    new NameExpr( loc, currProcsName ),
219                    new NameExpr( loc, loopTempName )
220                }
221            )
222        ));
223
224        body->push_back( new ForStmt( loc,
225            {},
226            deepCopy( stmt->cond ),
227            deepCopy( stmt->inc ),
228            forLoopBody
229        ));
230
231        // Generates:
232        // end_runners( __CFA_cofor_thread_array, __CFA_cofor_num_procs );
233        body->push_back( new ExprStmt( loc,
234            new UntypedExpr( loc,
235                new NameExpr( loc, "end_runners" ),
236                {
237                    new NameExpr( loc, thdArrName ),
238                    new NameExpr( loc, numProcsName )
239                }
240            )
241        ));
242
243        return body;
244    }
245
246    // codegen for corun statements
247    Stmt * postvisit( const CorunStmt * stmt ) {
248        if ( !runnerBlockDecl || !coforRunnerDecl )
249            SemanticError( stmt->location, "To use corun statements add #include <cofor.hfa>\n" );
250
251        if ( !stmt->stmt )
252            return nullptr;
253
254        const CodeLocation & loc = stmt->location;
255        const string fnName = CorunFnNamer.newName();
256        const string objName = RunnerBlockNamer.newName();
257
258        // Generates:
259        // void __CFA_corun_lambda_() { ... stmt->stmt ... }
260        Stmt * runnerLambda = new DeclStmt( loc,
261            new FunctionDecl( loc,
262                fnName,                                             // name
263                {},                                                 // forall
264                {},                                                 // params
265                {},                                                 // return
266                new CompoundStmt( loc, { deepCopy(stmt->stmt) } )   // body
267            )
268        );
269
270        // Generates:
271        // runner_block __CFA_corun_block_;
272        Stmt * objDecl = new DeclStmt( loc,
273            new ObjectDecl( loc,
274                objName,
275                new StructInstType( runnerBlockDecl )
276            )
277        );
278
279        // Generates:
280        // __CFA_corun_block_{ __CFA_corun_lambda_ };
281        Stmt * threadStart = new ExprStmt( loc,
282            new UntypedExpr ( loc,
283                new NameExpr( loc, "?{}" ),
284                {
285                    new NameExpr( loc, objName ),
286                    new NameExpr( loc, fnName )
287                }
288            )
289        );
290
291        stmtsToAddBefore.push_back( runnerLambda );
292        stmtsToAddBefore.push_back( objDecl );
293
294        return threadStart;
295    }
296};
297
298void implementCorun( TranslationUnit & translationUnit ) {
299    Pass<CorunKeyword>::run( translationUnit );
300}
301
302} // namespace Concurrency
Note: See TracBrowser for help on using the repository browser.