Changes in src/Concurrency/Corun.cpp [fc1a3e2:7a780ad]
- File:
-
- 1 edited
-
src/Concurrency/Corun.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Concurrency/Corun.cpp
rfc1a3e2 r7a780ad 26 26 27 27 struct 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) decls44 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 statements57 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 body73 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 ), ExplicitCast98 )99 )100 )101 )102 ));103 104 // push rest of cofor body into loop lambda105 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, // name115 {116 new ObjectDecl( loc,117 coforArgName,118 new ast::PointerType( new ast::VoidType() )119 )120 }, // params121 {}, // return122 fnBody // body123 )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::DynamicDim164 )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 forLoopBody228 ));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 statements246 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, // name262 {}, // params263 {}, // return264 new CompoundStmt( loc, { deepCopy(stmt->stmt) } ) // body265 )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 }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 294 }; 295 295 296 296 void implementCorun( TranslationUnit & translationUnit ) { 297 Pass<CorunKeyword>::run( translationUnit );297 Pass<CorunKeyword>::run( translationUnit ); 298 298 } 299 299
Note:
See TracChangeset
for help on using the changeset viewer.