source: src/Concurrency/Corun.cpp @ 7a780ad

Last change on this file since 7a780ad was 7a780ad, checked in by Andrew Beach <ajbeach@…>, 6 weeks ago

Moved ast::BasicType::Kind to ast::BasicKind? in its own hearder. This is more consistent with other utility enums (although we still use this as a enum class) and reduces what some files need to include. Also did a upgrade in a comment with MAX_INTEGER_TYPE, it is now part of the enum.

  • Property mode set to 100644
File size: 10.2 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.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>" );
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.