source: src/Concurrency/Corun.cpp@ 8d182b1

Last change on this file since 8d182b1 was 3d9d017, checked in by caparson <caparson@…>, 23 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.