source: src/Concurrency/Corun.cpp @ 262a864

Last change on this file since 262a864 was ed96731, checked in by Andrew Beach <ajbeach@…>, 4 weeks 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.