source: src/Concurrency/Corun.cpp@ 5786403

Last change on this file since 5786403 was ed96731, checked in by Andrew Beach <ajbeach@…>, 10 months ago

With{Stmts,Decls}ToAdd how has an -X version like WithSymbolTableX. Although these -X versions might be useful can could possibly be removed in the future. (This is a therapy commit.)

  • Property mode set to 100644
File size: 8.0 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 : Peter A. Buhr
12// Last Modified On : Thu Dec 14 17:32:17 2023
13// Update Count : 1
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.hpp"
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>" );
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 }
294};
295
296void implementCorun( TranslationUnit & translationUnit ) {
297 Pass<CorunKeyword>::run( translationUnit );
298}
299
300} // namespace Concurrency
Note: See TracBrowser for help on using the repository browser.