Inferno
0.2
|
00001 00002 #include "steps/state_out.hpp" 00003 #include "tree/cpptree.hpp" 00004 #include "tree/sctree.hpp" 00005 #include "common/common.hpp" 00006 #include "sr/soft_patterns.hpp" 00007 #include "tree/typeof.hpp" 00008 #include "tree/misc.hpp" 00009 #include "inferno_patterns.hpp" 00010 00011 00012 using namespace CPPTree; 00013 using namespace SCTree; 00014 using namespace Steps; 00015 00016 // TOOD go through step impls and use inline decls of leaf nodes, to reduce wordiness 00017 00018 GotoAfterWait::GotoAfterWait() 00019 { 00020 // This step could have been tricky: we'd have needed 3 cases: 00021 // 1. { *, wait, !goto, * } 00022 // 2. { *, wait } // not covered by previous case because !goto needs to match a statement 00023 // 3. eg if() wait // not directly inside a compound block 00024 // we use the but-not pattern, in which we principally search for anything->wait, but exclude 00025 // the only case that needs excluding which is a compound like in case 1 above but without 00026 // notting the goto. Cases 2 and 3 work because the excluded compound does not match. 00027 // Overall, a good example of but-not 00028 MakeTreePtr<Compound> sx_comp, r_comp; 00029 MakeTreePtr< Star<Declaration> > sx_decls; 00030 MakeTreePtr< Star<Statement> > sx_pre, sx_post; 00031 MakeTreePtr<Wait> wait; 00032 MakeTreePtr< NotMatch<Statement> > notmatch; 00033 MakeTreePtr< MatchAll<Statement> > all; 00034 MakeTreePtr< AnyNode<Statement> > anynode; 00035 MakeTreePtr< Overlay<Statement> > over; 00036 MakeTreePtr<Goto> sx_goto, r_goto; 00037 MakeTreePtr<Label> r_label; 00038 MakeTreePtr<BuildLabelIdentifier> r_labelid("YIELD"); 00039 00040 all->patterns = (anynode, notmatch); 00041 anynode->terminus = over; 00042 over->through = wait; 00043 notmatch->pattern = sx_comp; 00044 sx_comp->members = sx_decls; 00045 sx_comp->statements = (sx_pre, wait, sx_goto, sx_post); 00046 00047 over->overlay = r_comp; 00048 //r_comp->members = (); 00049 r_comp->statements = (wait, r_goto, r_label); 00050 r_goto->destination = r_labelid; 00051 r_label->identifier = r_labelid; 00052 00053 Configure( all ); 00054 } 00055 /* 00056 GotoAfterWait::GotoAfterWait() 00057 { 00058 // TODO will miss a yield at the very end 00059 MakeTreePtr<Compound> s_comp, r_comp; 00060 MakeTreePtr< Star<Declaration> > decls; 00061 MakeTreePtr< Star<Statement> > pre, post; 00062 MakeTreePtr<Wait> wait; 00063 MakeTreePtr< NotMatch<Statement> > notmatch; 00064 MakeTreePtr<Goto> sx_goto, r_goto; 00065 MakeTreePtr<Label> r_label; 00066 MakeTreePtr<BuildLabelIdentifier> r_labelid("YIELD"); 00067 00068 s_comp->members = (decls); 00069 s_comp->statements = (pre, wait, notmatch, post); 00070 notmatch->pattern = sx_goto; 00071 00072 r_comp->members = (decls); 00073 r_comp->statements = (pre, wait, r_goto, r_label, notmatch, post); 00074 r_goto->destination = r_labelid; 00075 r_label->identifier = r_labelid; 00076 00077 Configure( s_comp, r_comp ); 00078 } 00079 */ 00080 00081 NormaliseConditionalGotos::NormaliseConditionalGotos() 00082 { 00083 MakeTreePtr< If > iif; 00084 MakeTreePtr< Expression > cond; 00085 MakeTreePtr< Compound > s_comp, r_comp, sx_comp; 00086 MakeTreePtr< Goto > then_goto, s_else_goto, r_goto, sx_goto;// TODO sx_goto could be any departure, like Return or Cease etc 00087 MakeTreePtr< Star<Declaration> > decls; 00088 MakeTreePtr< Star<Statement> > pre, post, sx_post; 00089 MakeTreePtr< Multiplexor > mult; 00090 MakeTreePtr< Label > label; 00091 MakeTreePtr< BuildLabelIdentifier > label_id("PROCEED"); 00092 MakeTreePtr< MatchAll<Statement> > s_all; 00093 MakeTreePtr< NotMatch<Statement> > sx_not; 00094 00095 s_all->patterns = (s_comp, sx_not); 00096 sx_not->pattern = sx_comp; 00097 iif->condition = cond; 00098 iif->body = then_goto; 00099 iif->else_body = MakeTreePtr<Nop>(); 00100 s_comp->members = ( decls ); 00101 s_comp->statements = ( pre, iif, post ); 00102 sx_comp->statements = ( pre, iif, sx_goto, sx_post ); 00103 00104 label->identifier = label_id; 00105 r_goto->destination = label_id; 00106 r_comp->members = ( decls ); 00107 r_comp->statements = ( pre, iif, r_goto, label, post ); 00108 00109 Configure( s_all, r_comp ); 00110 } 00111 00112 00113 CompactGotos::CompactGotos() 00114 { 00115 MakeTreePtr< If > s_if; 00116 MakeTreePtr< Expression > cond; 00117 MakeTreePtr< Compound > s_comp, r_comp; 00118 MakeTreePtr< Goto > s_then_goto, s_else_goto, r_goto; 00119 MakeTreePtr< Star<Declaration> > decls; 00120 MakeTreePtr< Star<Statement> > pre, post; 00121 MakeTreePtr< Multiplexor > mult; 00122 00123 s_then_goto->destination = MakeTreePtr<Expression>(); 00124 s_else_goto->destination = MakeTreePtr<Expression>(); 00125 s_if->condition = cond; 00126 s_if->body = s_then_goto; 00127 s_if->else_body = MakeTreePtr<Nop>(); // standed conditional branch has no else clause - our "else" is the next statement 00128 s_comp->members = ( decls ); 00129 s_comp->statements = ( pre, s_if, s_else_goto, post ); 00130 00131 mult->operands = (cond, s_then_goto->destination, s_else_goto->destination); 00132 r_goto->destination = mult; 00133 r_comp->statements = ( pre, r_goto, post ); 00134 r_comp->members = ( decls ); 00135 00136 Configure( s_comp, r_comp ); 00137 } 00138 00139 00140 AddGotoBeforeLabel::AddGotoBeforeLabel() // TODO really slow!!11 00141 { 00142 MakeTreePtr< If > s_if; 00143 MakeTreePtr< Expression > cond; 00144 MakeTreePtr< Compound > s_comp, r_comp, sx_comp; 00145 MakeTreePtr< Goto > r_goto; 00146 MakeTreePtr< Star<Declaration> > decls; 00147 MakeTreePtr< Star<Statement> > pre, post, sx_pre, sx_post; 00148 MakeTreePtr< Multiplexor > mult; 00149 MakeTreePtr< Label > label; 00150 MakeTreePtr< LabelIdentifier > label_id; 00151 MakeTreePtr< MatchAll<Compound> > s_all; 00152 MakeTreePtr< NotMatch<Compound> > s_not; 00153 00154 s_all->patterns = (s_comp, s_not); 00155 s_not->pattern = sx_comp; 00156 s_comp->members = ( decls ); 00157 s_comp->statements = ( pre, label, post ); 00158 label->identifier = label_id; 00159 sx_comp->members = ( decls ); 00160 sx_comp->statements = ( sx_pre, MakeTreePtr<Goto>(), label, sx_post ); 00161 00162 r_comp->members = ( decls ); 00163 r_comp->statements = ( pre, r_goto, label, post ); 00164 r_goto->destination = label_id; 00165 00166 Configure( s_all, r_comp ); 00167 } 00168 00169 00170 static TreePtr<Statement> MakeResetAssignmentPattern() 00171 { 00172 MakeTreePtr<Assign> ass; 00173 MakeTreePtr< TransformOf<InstanceIdentifier> > decl( &GetDeclaration::instance ); 00174 decl->pattern = MakeTreePtr<LocalVariable>(); 00175 ass->operands = (decl, MakeTreePtr<Literal>()); 00176 return ass; 00177 } 00178 00179 00180 EnsureBootstrap::EnsureBootstrap() 00181 { 00182 MakeTreePtr<Instance> fn; 00183 MakeTreePtr<Thread> thread; 00184 MakeTreePtr< Overlay<Compound> > over; 00185 MakeTreePtr< MatchAll<Compound> > s_all; 00186 MakeTreePtr< NotMatch<Compound> > s_not; 00187 MakeTreePtr<Compound> s_body, r_body, sx_body; 00188 MakeTreePtr< Star<Declaration> > decls; 00189 MakeTreePtr< Star<Statement> > pre, sx_pre, post; 00190 MakeTreePtr<Goto> r_goto; 00191 MakeTreePtr<Label> r_label; 00192 MakeTreePtr<BuildLabelIdentifier> r_labelid("BOOTSTRAP"); 00193 MakeTreePtr< NotMatch<Statement> > stop; 00194 MakeTreePtr<Goto> sx_goto; 00195 00196 fn->type = thread; 00197 fn->initialiser = over; 00198 over->through = s_all; 00199 s_all->patterns = (s_not, s_body); 00200 s_not->pattern = sx_body; 00201 // only exclude if there is a goto; a goto to anywhere will suffice to boot the state machine 00202 sx_body->members = (MakeTreePtr< Star<Declaration> >()); 00203 sx_body->statements = (sx_pre, sx_goto, MakeTreePtr< Star<Statement> >()); 00204 sx_pre->pattern = MakeResetAssignmentPattern(); 00205 sx_goto->destination = MakeTreePtr<LabelIdentifier>(); // must be a hard goto to exclude - otherwise might 00206 // have calculations in it which is no good for bootstrapping 00207 over->overlay = r_body; 00208 s_body->members = decls; 00209 s_body->statements = (pre, stop, post); 00210 pre->pattern = MakeResetAssignmentPattern(); 00211 stop->pattern = MakeResetAssignmentPattern(); 00212 r_label->identifier = r_labelid; 00213 r_goto->destination = r_labelid; 00214 r_body->members = decls; 00215 r_body->statements = (pre, r_goto, r_label, stop, post); 00216 00217 Configure( fn ); 00218 } 00219 00220 00221 AddStateLabelVar::AddStateLabelVar() 00222 { 00223 MakeTreePtr<Compound> s_comp, r_comp, lr_compound; 00224 MakeTreePtr< Star<Declaration> > decls; 00225 MakeTreePtr< Star<Statement> > pre, post; 00226 MakeTreePtr<Goto> ls_goto, lr_goto, sx_goto; 00227 MakeTreePtr<Assign> lr_assign; 00228 MakeTreePtr<Automatic> state_var; 00229 MakeTreePtr< NotMatch<Expression> > sx_not, lsx_not; 00230 MakeTreePtr< BuildInstanceIdentifier > state_var_id("state"); 00231 00232 ls_goto->destination = lsx_not; 00233 lsx_not->pattern = state_var_id; // MakeTreePtr<InstanceIdentifier>(); 00234 00235 lr_compound->statements = (lr_assign, lr_goto); 00236 lr_assign->operands = (state_var_id, lsx_not); 00237 lr_goto->destination = state_var_id; 00238 00239 MakeTreePtr< SlaveSearchReplace<Statement> > r_slave( r_comp, ls_goto, lr_compound ); 00240 00241 s_comp->members = (decls); 00242 s_comp->statements = (pre, sx_goto, post); 00243 sx_goto->destination = sx_not; 00244 sx_not->pattern = MakeTreePtr<InstanceIdentifier>(); 00245 00246 r_comp->members = (state_var, decls); 00247 r_comp->statements = (pre, sx_goto, post); 00248 state_var->identifier = state_var_id; 00249 state_var->type = MakeTreePtr<Labeley>(); 00250 state_var->initialiser = MakeTreePtr<Uninitialised>(); 00251 00252 Configure( s_comp, r_slave ); 00253 } 00254 00255 00256 EnsureSuperLoop::EnsureSuperLoop() 00257 { 00258 MakeTreePtr<Instance> fn; 00259 MakeTreePtr<Thread> thread; 00260 MakeTreePtr< Overlay<Compound> > over; 00261 MakeTreePtr< MatchAll<Compound> > s_all; 00262 MakeTreePtr< NotMatch<Statement> > sx_not, s_limit; 00263 MakeTreePtr< Stuff<Compound> > sx_stuff; 00264 MakeTreePtr< Goto > sx_goto, first_goto; 00265 MakeTreePtr<Compound> s_body, r_body, r_loop_body; 00266 MakeTreePtr< Star<Statement> > pre, post; 00267 MakeTreePtr< Star<Declaration> > decls; 00268 MakeTreePtr<Do> r_loop; 00269 00270 fn->type = thread; 00271 fn->initialiser = over; 00272 over->through = s_all; 00273 s_all->patterns = (sx_stuff, s_body); 00274 sx_stuff->terminus = sx_goto; 00275 sx_stuff->recurse_restriction = sx_not; 00276 sx_not->pattern = MakeTreePtr<Do>(); 00277 s_body->members = (decls); 00278 s_body->statements = (pre, first_goto, post); 00279 pre->pattern = s_limit; 00280 s_limit->pattern = MakeTreePtr<Goto>(); 00281 00282 over->overlay = r_body; 00283 r_body->members = (decls); 00284 r_body->statements = (pre, r_loop); 00285 r_loop->body = r_loop_body; 00286 r_loop_body->statements = (first_goto, post); 00287 r_loop->condition = MakeTreePtr<True>(); 00288 00289 Configure( fn ); 00290 } 00291 00292 ShareGotos::ShareGotos() 00293 { 00294 MakeTreePtr<Do> loop; 00295 MakeTreePtr< Overlay<Compound> > over; 00296 MakeTreePtr<Compound> s_body, r_body; 00297 MakeTreePtr< Star<Declaration> > decls; 00298 MakeTreePtr< Star<Statement> > pre, post; 00299 MakeTreePtr< Goto > first_goto, r_goto; 00300 MakeTreePtr<Label> r_label; 00301 MakeTreePtr<BuildLabelIdentifier> r_labelid("ITERATE"); 00302 00303 loop->body = over; 00304 loop->condition = MakeTreePtr<SpecificInteger>(1); 00305 over->through = s_body; 00306 s_body->members = (decls); 00307 s_body->statements = (first_goto, pre, first_goto, post); 00308 00309 over->overlay = r_body; 00310 r_body->members = (decls); 00311 r_body->statements = (first_goto, pre, r_goto, post, r_label); 00312 r_label->identifier = r_labelid; 00313 r_goto->destination = r_labelid; 00314 00315 Configure( loop ); 00316 } 00317 00318 00319 // Something to get the size of the Collection matched by a Star as a SpecificInteger 00320 struct BuildContainerSize : SoftReplacePattern, 00321 Special<Integer> 00322 { 00323 SPECIAL_NODE_FUNCTIONS 00324 shared_ptr< StarBase > container; 00325 private: 00326 virtual TreePtr<Node> DuplicateSubtree( const CompareReplace *sr ) 00327 { 00328 ASSERT( container ); 00329 TreePtr<Node> n = sr->BuildReplace( container ); 00330 ASSERT( n ); 00331 ContainerInterface *n_container = dynamic_cast<ContainerInterface *>(n.get()); 00332 ASSERT( n_container ); 00333 int size = n_container->size(); 00334 TreePtr<SpecificInteger> si = MakeTreePtr<SpecificInteger>(size); 00335 return si; 00336 } 00337 }; 00338 00339 00340 struct IsLabelReached : SoftSearchPattern, Special<LabelIdentifier> 00341 { 00342 SPECIAL_NODE_FUNCTIONS 00343 virtual void FlushCache() 00344 { 00345 cache.clear(); 00346 } 00347 // x is nominally the label id, at the position of this node 00348 // y is nominally the goto expression, coupled in 00349 virtual bool DecidedCompare( const CompareReplace *sr, 00350 const TreePtrInterface &xx, 00351 bool can_key, 00352 Conjecture &conj ) 00353 { 00354 INDENT; 00355 ASSERT( pattern ); 00356 if( can_key ) 00357 return true; // Want to wait for our pattern to get keyed before we do the search, so wait for restricting pass 00358 TreePtr<Node> n = sr->coupling_keys.GetCoupled( pattern ); // TODO a templates version that returns same type as pattern, so we don't need to convert here? 00359 if( !n ) 00360 n = pattern; 00361 TreePtr<Expression> y = dynamic_pointer_cast<Expression>( n ); 00362 ASSERT( y )("IsLabelReached saw pattern coupled to ")(*n)(" but an Expression is needed\n"); 00363 ASSERT( xx ); 00364 TreePtr<Node> nxx = xx; 00365 TreePtr<LabelIdentifier> x = dynamic_pointer_cast<LabelIdentifier>( nxx ); 00366 ASSERT( x )("IsLabelReached at ")(*xx)(" but is of type LabelIdentifier\n"); 00367 TRACE("Can label id ")(*x)(" reach expression ")(*y)("?\n"); 00368 00369 Set< TreePtr<InstanceIdentifier> > uf; 00370 bool r = CanReachExpr(sr, &uf, x, y); 00371 TRACE("I reakon ")(*x)(r?" does ":" does not ")("reach ")(*y)("\n"); 00372 return r; 00373 } 00374 TreePtr<Expression> pattern; 00375 00376 private: 00377 bool CanReachExpr( const CompareReplace *sr, 00378 Set< TreePtr<InstanceIdentifier> > *f, 00379 TreePtr<LabelIdentifier> x, 00380 TreePtr<Expression> y ) // y is expression. Can it yield label x? 00381 { 00382 INDENT; 00383 bool r = false; 00384 if( TreePtr<LabelIdentifier> liy = dynamic_pointer_cast<LabelIdentifier>(y) ) 00385 r = liy->IsLocalMatch( x.get() ); // y is x, so yes 00386 else if( TreePtr<InstanceIdentifier> iiy = dynamic_pointer_cast<InstanceIdentifier>( y ) ) 00387 r = CanReachVar( sr, f, x, iiy ); 00388 else if( TreePtr<Ternop> ty = dynamic_pointer_cast<Ternop>( y ) ) 00389 r = CanReachExpr(sr, f, x, ty->operands[1]) || 00390 CanReachExpr(sr, f, x, ty->operands[2]); // only the choices, not the condition 00391 else if( TreePtr<Comma> cy = dynamic_pointer_cast<Comma>( y ) ) 00392 r = CanReachExpr(sr, f, x, ty->operands[1]); // second operand 00393 else if( TreePtr<Subscript> sy = dynamic_pointer_cast<Subscript>( y ) ) // subscript as r-value 00394 r = CanReachExpr(sr, f, x, sy->operands[0]); // first operand 00395 else if( dynamic_pointer_cast<Dereference>( y ) ) 00396 ASSERTFAIL("IsLabelReached used on expression that is read from memory, cannot figure out the answer\n"); 00397 00398 TRACE("I reakon ")(*x)(" at %p", x.get())(r?" does ":" does not ")("reach ")(*y)("\n"); 00399 return r; 00400 } 00401 00402 bool CanReachVar( const CompareReplace *sr, 00403 Set< TreePtr<InstanceIdentifier> > *f, 00404 TreePtr<LabelIdentifier> x, 00405 TreePtr<InstanceIdentifier> y ) // y is instance identifier. Can expression x be assigned to it? 00406 { 00407 INDENT; 00408 Reaching rr( x, y ); 00409 if( cache.IsExist(rr) ) 00410 { 00411 TRACE("cache hit yeah yeah\n"); 00412 return cache[rr]; 00413 } 00414 bool r = false; 00415 Walk e( *sr->pcontext ); 00416 00417 if( f->IsExist(y) ) 00418 return false; // already processing this identifier, so we have a loop 00419 // so don't recurse further 00420 00421 f->insert(y); 00422 00423 TRACE("Looking for assignment like ")(*y)(" = ")(*x)("\n"); 00424 00425 FOREACH( TreePtr<Node> n, e ) 00426 { 00427 if( TreePtr<Assign> a = dynamic_pointer_cast<Assign>(n) ) 00428 { 00429 TreePtr<Expression> lhs = a->operands[0]; 00430 if( TreePtr<Subscript> slhs = dynamic_pointer_cast<Subscript>( lhs ) ) // subscript as l-value 00431 lhs = slhs->operands[0]; 00432 TRACE("Examining assignment: ")(*lhs)(" = ")(*a->operands[1])("\n"); 00433 if( lhs == y ) 00434 { 00435 if( CanReachExpr( sr, f, x, a->operands[1] ) ) 00436 { 00437 r = true; 00438 break; // early out, since we have the info we need 00439 } 00440 } 00441 } 00442 } 00443 00444 f->erase(y); 00445 return r; 00446 } 00447 00448 struct Reaching 00449 { 00450 Reaching( TreePtr<LabelIdentifier> f, TreePtr<InstanceIdentifier> t ) : from(f), to(t) {} 00451 const TreePtr<LabelIdentifier> from; 00452 const TreePtr<InstanceIdentifier> to; 00453 bool operator<( const Reaching &other ) const 00454 { 00455 return from==other.from ? to<other.to : from<other.from; 00456 } 00457 }; 00458 Map<Reaching, bool> cache; 00459 }; 00460 00461 00462 InsertSwitch::InsertSwitch() 00463 { 00464 MakeTreePtr<Instance> fn; 00465 MakeTreePtr<InstanceIdentifier> fn_id; 00466 MakeTreePtr<Callable> sub; 00467 MakeTreePtr< Overlay<Compound> > func_over, over, l_over; 00468 MakeTreePtr< Compound > ls_func_comp, lr_func_comp, s_func_comp, r_func_comp, s_comp, r_comp, r_switch_comp, l_comp, ls_switch_comp, lr_switch_comp; 00469 MakeTreePtr< Star<Declaration> > func_decls, decls, l_enum_vals; 00470 MakeTreePtr< Star<Statement> > func_pre, func_post, pre, body, l_func_pre, l_func_post, l_pre, l_post; 00471 MakeTreePtr< Stuff<Statement> > stuff, l_stuff; // TODO these are parallel stuffs, which is bad. Use two first-level slaves 00472 // and modify S&R to allow couplings between them. This means running slaves 00473 // in a post-pass and doing existing passes across all same-level slaves 00474 MakeTreePtr<Goto> s_first_goto; 00475 MakeTreePtr<Label> ls_label; 00476 MakeTreePtr<Switch> r_switch, l_switch; 00477 MakeTreePtr<Enum> r_enum, ls_enum, lr_enum; 00478 MakeTreePtr< NotMatch<Statement> > s_prenot, s_postnot, xs_rr; 00479 MakeTreePtr<BuildTypeIdentifier> r_enum_id("%sStates"); 00480 MakeTreePtr<Static> lr_state_decl; 00481 MakeTreePtr<BuildInstanceIdentifier> lr_state_id("STATE_%s"); 00482 MakeTreePtr<Case> lr_case; 00483 MakeTreePtr<Signed> lr_int; 00484 MakeTreePtr<BuildContainerSize> lr_count; 00485 MakeTreePtr<IsLabelReached> ls_label_id; 00486 MakeTreePtr<InstanceIdentifier> var_id; 00487 MakeTreePtr<Instance> var_decl, l_var_decl; 00488 MakeTreePtr< Overlay<Type> > var_over; 00489 MakeTreePtr<Label> xs_pre_label; 00490 MakeTreePtr<IsLabelReached> xs_pre_reach; 00491 MakeTreePtr< MatchAll<Node> > ll_all; 00492 MakeTreePtr< NotMatch<Node> > lls_not1, lls_not2; 00493 MakeTreePtr< AnyNode<Node> > ll_any; 00494 MakeTreePtr< Overlay<Node> > ll_over; 00495 MakeTreePtr<Goto> lls_goto; 00496 MakeTreePtr<Label> lls_label; 00497 00498 fn->type = sub; 00499 fn->initialiser = func_over; 00500 fn->identifier = fn_id; 00501 func_over->through = s_func_comp; 00502 s_func_comp->members = (func_decls, var_decl); 00503 var_decl->type = var_over; 00504 var_decl->identifier = var_id; 00505 var_over->through = MakeTreePtr<Labeley>(); 00506 s_func_comp->statements = (func_pre, stuff, func_post); 00507 stuff->terminus = over; 00508 stuff->recurse_restriction = xs_rr; // TODO Add support for elsewhere restriction in stuff node, restrict for no reaches 00509 xs_rr->pattern = MakeTreePtr<Switch>(); // stop it doing a second switch inside one we just created 00510 over->through = s_comp; 00511 s_comp->members = (decls); 00512 s_comp->statements = (pre, s_first_goto, body); 00513 pre->pattern = s_prenot; 00514 s_prenot->pattern = xs_pre_label; 00515 xs_pre_label->identifier = xs_pre_reach; 00516 xs_pre_reach->pattern = var_id; 00517 s_first_goto->destination = var_id; 00518 00519 r_func_comp->members = (func_decls, r_enum, var_decl); 00520 var_over->overlay = r_enum_id; 00521 r_enum->identifier = r_enum_id; 00522 r_enum_id->sources = (fn_id); 00523 r_func_comp->statements = (func_pre, stuff, func_post); 00524 over->overlay = r_comp; 00525 r_comp->members = (decls); 00526 r_comp->statements = (pre, r_switch); 00527 r_switch->body = r_switch_comp; 00528 r_switch_comp->statements = (body); 00529 r_switch->condition = var_id; 00530 00531 MakeTreePtr< SlaveSearchReplace<Compound> > lr_sub_slave( lr_func_comp, ll_all ); 00532 MakeTreePtr< SlaveCompareReplace<Compound> > r_slave( r_func_comp, ls_func_comp, lr_sub_slave ); 00533 func_over->overlay = r_slave; 00534 ls_func_comp->members = (func_decls, ls_enum, l_var_decl); 00535 ls_enum->members = (l_enum_vals); 00536 ls_enum->identifier = r_enum_id; // need to match id, not enum itself, because enum's members will change during slave 00537 ls_func_comp->statements = (l_func_pre, l_stuff, l_func_post); 00538 l_stuff->terminus = l_comp; 00539 l_comp->members = (decls); 00540 l_comp->statements = (pre, l_switch); 00541 l_switch->body = l_over; 00542 l_switch->condition = s_first_goto->destination; 00543 l_over->through = ls_switch_comp; 00544 ls_switch_comp->statements = (l_pre, ls_label, l_post); 00545 ls_label->identifier = ls_label_id; 00546 ls_label_id->pattern = var_id; 00547 00548 lr_func_comp->members = (func_decls, lr_enum, l_var_decl); 00549 lr_enum->members = (l_enum_vals, lr_state_decl); 00550 lr_enum->identifier = r_enum_id; 00551 lr_state_decl->constancy = MakeTreePtr<Const>(); 00552 lr_state_decl->identifier = lr_state_id; 00553 lr_state_decl->type = lr_int; 00554 lr_state_decl->initialiser = lr_count; 00555 lr_count->container = l_enum_vals; 00556 lr_int->width = MakeTreePtr<SpecificInteger>(32); // TODO should be a common place for getting default types 00557 lr_state_id->sources = (ls_label->identifier); 00558 lr_func_comp->statements = (l_func_pre, l_stuff, l_func_post); 00559 l_over->overlay = lr_switch_comp; 00560 lr_switch_comp->statements = (l_pre, lr_case, /*ls_label,*/ l_post); 00561 // TODO retain the label for direct gotos, BUT we are spinning at 1st slave because we think the 00562 // label is still a state, because we think it reaches state var, because the LABEL->STATE_LABEL change 00563 // is not being seen by IsLabelReached, because this is done by 2nd slave and stays in temps until 00564 // the master's SingleCompareReplace() completes. Uh-oh! 00565 // Only fix after fixing S&R to ensure slave output goes into context 00566 lr_case->value = lr_state_id; 00567 00568 ll_all->patterns = (ll_any, lls_not1, lls_not2); 00569 ll_any->terminus = ll_over; 00570 ll_over->through = ls_label_id; 00571 ll_over->overlay = lr_state_id; 00572 lls_not1->pattern = lls_goto; 00573 lls_goto->destination = ls_label_id; // leave gotos alone in the body 00574 lls_not2->pattern = lls_label; 00575 lls_label->identifier = ls_label_id; // leave labels alone in the body 00576 00577 Configure( fn ); 00578 } 00579 00580 00581 SwitchCleanUp::SwitchCleanUp() 00582 { 00583 MakeTreePtr<Compound> r_comp, s_body, r_body; 00584 MakeTreePtr<Switch> s_switch, r_switch; 00585 MakeTreePtr< Star<Declaration> > decls; 00586 MakeTreePtr< Star<Statement> > main, tail; 00587 MakeTreePtr<Label> label; 00588 MakeTreePtr<Expression> cond; 00589 MakeTreePtr< NotMatch<Statement> > sx_not_tail, sx_not_main; 00590 MakeTreePtr< MatchAny<Statement> > sx_any_tail; 00591 00592 s_switch->condition = cond; 00593 s_switch->body = s_body; 00594 s_body->members = decls; 00595 s_body->statements = (main, label, tail); 00596 main->pattern = sx_not_main; 00597 sx_not_main->pattern = MakeTreePtr<Break>(); 00598 tail->pattern = sx_not_tail; 00599 sx_not_tail->pattern = sx_any_tail; 00600 sx_any_tail->patterns = (MakeTreePtr<Break>(), MakeTreePtr<Case>()); 00601 00602 r_comp->statements = (r_switch, label, tail); 00603 r_switch->condition = cond; 00604 r_switch->body = r_body; 00605 r_body->members = decls; 00606 r_body->statements = (main); 00607 00608 Configure( s_switch, r_comp ); 00609 } 00610 00611 00612 InferBreak::InferBreak() 00613 { 00614 MakeTreePtr<Goto> ls_goto; 00615 MakeTreePtr<Label> label; 00616 MakeTreePtr<LabelIdentifier> label_id; 00617 MakeTreePtr< Star<Declaration> > decls; 00618 MakeTreePtr< Star<Statement> > pre, post; 00619 MakeTreePtr<Breakable> breakable; 00620 MakeTreePtr<Break> lr_break; 00621 MakeTreePtr<Compound> s_comp, r_comp; 00622 00623 ls_goto->destination = label_id; 00624 00625 MakeTreePtr< SlaveSearchReplace<Breakable> > slave( breakable, ls_goto, lr_break ); // todo restrict to not go through more breakables 00626 00627 s_comp->members = decls; 00628 s_comp->statements = (pre, breakable, label, post); 00629 label->identifier = label_id; 00630 00631 r_comp->members = decls; 00632 r_comp->statements = (pre, slave, post); 00633 00634 Configure( s_comp, r_comp ); 00635 } 00636 00637 00638 FixFallthrough::FixFallthrough() 00639 { 00640 // don't actually need a switch statement here, just look in the body, pattern contains Case statements 00641 MakeTreePtr<Compound> s_comp, r_comp; 00642 MakeTreePtr< Star<Declaration> > decls; 00643 MakeTreePtr< Star<Statement> > pre, cb1, cb2, post; 00644 MakeTreePtr<Case> case1, case2; 00645 MakeTreePtr<Break> breakk; 00646 MakeTreePtr< NotMatch<Statement> > s_not1, s_not2; 00647 00648 s_comp->members = (decls); 00649 s_comp->statements = (pre, case1, cb1, case2, cb2, breakk, post); 00650 r_comp->members = (decls); 00651 r_comp->statements = (pre, case1, cb1, cb2, breakk, case2, cb2, breakk, post); 00652 cb1->pattern = s_not1; 00653 s_not1->pattern = MakeTreePtr<Break>(); 00654 cb2->pattern = s_not2; 00655 s_not2->pattern = MakeTreePtr<Case>(); 00656 00657 Configure( s_comp, r_comp ); 00658 } 00659 00660 #if 1 00661 MakeFallThroughMachine::MakeFallThroughMachine() 00662 { 00663 MakeTreePtr<Scope> module; 00664 MakeTreePtr< Insert<Declaration> > insert; 00665 MakeTreePtr< GreenGrass<Type> > gg; 00666 MakeTreePtr<Field> func, m_func; 00667 MakeTreePtr<InstanceIdentifier> func_id; 00668 MakeTreePtr<Thread> thread; 00669 MakeTreePtr< Overlay<Compound> > func_over; 00670 MakeTreePtr<Compound> s_func_comp, r_func_comp; 00671 MakeTreePtr< Star<Declaration> > func_decls, module_decls; 00672 MakeTreePtr< Star<Statement> > func_stmts; 00673 MakeTreePtr< Star<Base> > bases; 00674 MakeTreePtr<Enum> r_module_enum; 00675 MakeTreePtr<BuildTypeIdentifier> r_enum_id("%sStates"); 00676 MakeTreePtr< MatchAll<Scope> > m_all; 00677 MakeTreePtr< Stuff<Scope> > m_stuff_inst; 00678 MakeTreePtr< Stuff<Initialiser> > m_stuff_label; 00679 MakeTreePtr< Overlay<Type> > m_over; 00680 MakeTreePtr< Stuff<Type> > m_stuff; 00681 MakeTreePtr<Instance> m_inst; 00682 MakeTreePtr<InstanceIdentifier> m_inst_id, var_id; 00683 MakeTreePtr<TypeIdentifier> module_id; 00684 MakeTreePtr<Label> m_label; 00685 MakeTreePtr<IsLabelReached> m_ilr; 00686 MakeTreePtr< Compound > l_func_comp, lr_comp, ls_comp, lr_if_comp; 00687 MakeTreePtr< Star<Declaration> > l_func_decls, l_enum_vals, l_decls, l_module_decls; 00688 MakeTreePtr< Star<Statement> > l_func_pre, l_func_post, l_pre, l_block, l_post, l_stmts, l_dead_gotos; 00689 MakeTreePtr<Switch> l_switch; 00690 MakeTreePtr<Enum> l_enum; 00691 MakeTreePtr< Insert<Declaration> > l_insert; 00692 MakeTreePtr< NotMatch<Statement> > xs_rr; 00693 MakeTreePtr<Static> lr_state_decl; 00694 MakeTreePtr<BuildInstanceIdentifier> lr_state_id("%s_STATE_%s"); 00695 MakeTreePtr<Case> lr_case; 00696 MakeTreePtr<Signed> lr_int; 00697 MakeTreePtr<BuildContainerSize> lr_count; 00698 MakeTreePtr<LabelIdentifier> ls_label_id; 00699 MakeTreePtr<Instance> var_decl, l_var_decl; 00700 MakeTreePtr< MatchAll<Node> > ll_all; 00701 MakeTreePtr< NotMatch<Node> > lls_not1, lls_not2; 00702 MakeTreePtr< AnyNode<Node> > ll_any; 00703 MakeTreePtr< Overlay<Node> > ll_over; 00704 MakeTreePtr<Goto> lls_goto; 00705 MakeTreePtr<Label> lls_label; 00706 MakeTreePtr<Goto> ls_goto; 00707 MakeTreePtr<Label> ls_label; 00708 MakeTreePtr<If> lr_if; 00709 MakeTreePtr<Equal> lr_equal; 00710 MakeTreePtr<Loop> l_loop; 00711 MakeTreePtr< Overlay<Statement> > l_over; 00712 MakeTreePtr< NotMatch<Statement> > l_not; 00713 MakeTreePtr< Stuff<Scope> > m_stuff_func; 00714 MakeTreePtr<Scope> l_module; 00715 MakeTreePtr<Field> l_func; 00716 00717 ll_all->patterns = (ll_any, lls_not1, lls_not2); // TODO don't think we need the nots 00718 ll_any->terminus = ll_over; 00719 ll_over->through = ls_label_id; 00720 ll_over->overlay = lr_state_id; 00721 lls_not1->pattern = lls_goto; 00722 lls_goto->destination = ls_label_id; // leave gotos alone in the body 00723 lls_not2->pattern = lls_label; 00724 lls_label->identifier = ls_label_id; // leave labels alone in the body 00725 00726 MakeTreePtr< SlaveSearchReplace<Scope> > slavell( l_module, ll_all ); 00727 00728 m_all->patterns = (m_stuff_func, m_stuff_inst); 00729 m_stuff_func->terminus = m_func; 00730 m_func->identifier = func_id; 00731 m_func->initialiser = m_stuff_label; 00732 m_stuff_label->terminus = m_label; 00733 m_label->identifier = m_ilr; 00734 m_ilr->pattern = m_inst_id; 00735 m_stuff_inst->terminus = m_inst; 00736 m_inst->identifier = m_inst_id; 00737 m_inst->type = m_stuff; 00738 m_stuff->terminus = m_over; 00739 m_over->through = MakeTreePtr<Labeley>(); 00740 m_over->overlay = r_enum_id; 00741 00742 MakeTreePtr< SlaveCompareReplace<Scope> > slavem( module, m_all ); 00743 00744 l_func->identifier = func_id; 00745 l_func->initialiser = l_func_comp; 00746 l_func_comp->members = (func_decls); 00747 l_func_comp->statements = (l_func_pre, l_loop, l_func_post); 00748 l_loop->body = l_over; 00749 l_over->through = ls_comp; 00750 ls_comp->members = (l_decls); 00751 ls_comp->statements = (l_pre, ls_goto, ls_label, l_block, l_post, l_dead_gotos); 00752 ls_goto->destination = var_id; 00753 ls_label->identifier = ls_label_id; 00754 l_enum->members = (l_enum_vals, l_insert); 00755 l_enum->identifier = r_enum_id; 00756 l_block->pattern = l_not; 00757 l_not->pattern = MakeTreePtr<Goto>(); 00758 l_post->pattern = MakeTreePtr<If>(); 00759 l_dead_gotos->pattern = MakeTreePtr<Goto>(); 00760 l_module->members = (l_module_decls, l_enum, l_func); 00761 l_over->overlay = lr_comp; 00762 l_insert->insert = (lr_state_decl); 00763 lr_state_decl->constancy = MakeTreePtr<Const>(); 00764 lr_state_decl->identifier = lr_state_id; 00765 lr_state_decl->type = lr_int; 00766 lr_state_decl->initialiser = lr_count; 00767 lr_count->container = l_enum_vals; 00768 lr_int->width = MakeTreePtr<SpecificInteger>(32); // TODO should be a common place for getting default types 00769 lr_state_id->sources = (func_id, ls_label->identifier); 00770 lr_comp->members = (l_decls); 00771 lr_comp->statements = (l_pre, lr_if, l_post); // do final block first 00772 lr_if->condition = lr_equal; 00773 lr_if->body = lr_if_comp; 00774 lr_if->else_body = MakeTreePtr<Nop>(); 00775 lr_equal->operands = (ls_label_id, var_id); 00776 //lr_if_comp->members = (); 00777 lr_if_comp->statements = l_block; 00778 00779 MakeTreePtr< SlaveCompareReplace<Scope> > slavel( slavem, l_module, slavell ); 00780 00781 //s_module->bases = (bases); 00782 //s_module->identifier = module_id; 00783 func->type = gg; 00784 gg->through = thread; 00785 func->identifier = func_id; 00786 module->members = (module_decls, func, insert); 00787 insert->insert = (r_module_enum); 00788 //r_module->bases = (bases); 00789 //r_module->identifier = module_id; 00790 r_module_enum->identifier = r_enum_id; 00791 r_enum_id->sources = (func_id); 00792 //r_module_enum->members = (); 00793 00794 Configure( module, slavel ); 00795 } 00796 #else 00797 MakeFallThroughMachine::MakeFallThroughMachine() 00798 { 00799 MakeTreePtr<Instance> fn; 00800 MakeTreePtr<InstanceIdentifier> fn_id; 00801 MakeTreePtr<Callable> sub; 00802 MakeTreePtr< Overlay<Compound> > func_over, over; 00803 MakeTreePtr< Compound > ls_func_comp, lr_func_comp, s_func_comp, r_func_comp, s_comp, r_comp, r_switch_comp, lr_comp, ls_comp, lr_if_comp; 00804 MakeTreePtr< Star<Declaration> > func_decls, l_func_decls, decls, l_enum_vals, l_decls; 00805 MakeTreePtr< Star<Statement> > func_pre, func_post, stmts, body, l_func_pre, l_func_post, l_pre, l_block, l_post, l_stmts; 00806 MakeTreePtr< Stuff<Statement> > stuff; 00807 MakeTreePtr<Goto> s_first_goto; 00808 MakeTreePtr<Switch> r_switch, l_switch; 00809 MakeTreePtr<Enum> r_enum, ls_enum, lr_enum; 00810 MakeTreePtr< NotMatch<Statement> > s_prenot, s_postnot, xs_rr; 00811 MakeTreePtr<BuildTypeIdentifier> r_enum_id("%sStates"); 00812 MakeTreePtr<Static> lr_state_decl; 00813 MakeTreePtr<BuildInstanceIdentifier> lr_state_id("STATE_%s"); 00814 MakeTreePtr<Case> lr_case; 00815 MakeTreePtr<Signed> lr_int; 00816 MakeTreePtr<BuildContainerSize> lr_count; 00817 MakeTreePtr<LabelIdentifier> ls_label_id; 00818 MakeTreePtr<InstanceIdentifier> var_id; 00819 MakeTreePtr<Instance> var_decl, l_var_decl; 00820 MakeTreePtr< Overlay<Type> > var_over; 00821 MakeTreePtr<Label> xs_pre_label; 00822 MakeTreePtr<IsLabelReached> xs_pre_reach; 00823 MakeTreePtr< MatchAll<Node> > ll_all; 00824 MakeTreePtr< NotMatch<Node> > lls_not1, lls_not2; 00825 MakeTreePtr< AnyNode<Node> > ll_any; 00826 MakeTreePtr< Overlay<Node> > ll_over; 00827 MakeTreePtr<Goto> lls_goto; 00828 MakeTreePtr<Label> lls_label; 00829 MakeTreePtr<Goto> ls_goto; 00830 MakeTreePtr<Label> ls_label; 00831 MakeTreePtr<If> lr_if; 00832 MakeTreePtr<Equal> lr_equal; 00833 MakeTreePtr<Loop> l_loop; 00834 MakeTreePtr< Overlay<Statement> > l_over; 00835 MakeTreePtr< NotMatch<Statement> > l_not; 00836 MakeTreePtr< MatchAny<Statement> > l_any; 00837 00838 MakeTreePtr< SlaveSearchReplace<Compound> > lr_sub_slave( lr_func_comp, ll_all ); 00839 MakeTreePtr< SlaveCompareReplace<Compound> > r_slave( r_func_comp, ls_func_comp, lr_sub_slave ); 00840 00841 fn->type = sub; 00842 fn->initialiser = func_over; 00843 fn->identifier = fn_id; 00844 00845 func_over->through = s_func_comp; 00846 s_func_comp->members = (func_decls, var_decl); 00847 s_func_comp->statements = (stmts); 00848 var_decl->type = var_over; 00849 var_decl->identifier = var_id; 00850 var_over->through = MakeTreePtr<Labeley>(); 00851 var_over->overlay = r_enum_id; 00852 00853 func_over->overlay = r_slave; 00854 r_func_comp->members = (func_decls, r_enum, var_decl); 00855 r_func_comp->statements = (stmts); 00856 r_enum->identifier = r_enum_id; 00857 r_enum_id->sources = (fn_id); 00858 00859 ls_func_comp->members = (func_decls, ls_enum, l_var_decl); 00860 ls_func_comp->statements = (l_func_pre, l_loop, l_func_post); 00861 ls_enum->members = (l_enum_vals); 00862 ls_enum->identifier = r_enum_id; // need to match id, not enum itself, because enum's members will change during slave 00863 l_loop->body = l_over; 00864 l_over->through = ls_comp; 00865 ls_comp->members = (l_decls); 00866 ls_comp->statements = (l_pre, ls_goto, ls_label, l_block, l_post); 00867 ls_goto->destination = var_id; 00868 ls_label->identifier = ls_label_id; 00869 l_block->pattern = l_not; 00870 l_not->pattern = l_any; 00871 l_any->patterns = (MakeTreePtr<Goto>(), MakeTreePtr<If>()); 00872 l_post->pattern = MakeTreePtr<If>(); 00873 00874 lr_func_comp->members = (func_decls, lr_enum, l_var_decl); 00875 lr_func_comp->statements = (l_func_pre, l_loop, l_func_post); // do final block first 00876 l_over->overlay = lr_comp; 00877 lr_enum->members = (l_enum_vals, lr_state_decl); 00878 lr_enum->identifier = r_enum_id; 00879 lr_state_decl->constancy = MakeTreePtr<Const>(); 00880 lr_state_decl->identifier = lr_state_id; 00881 lr_state_decl->type = lr_int; 00882 lr_state_decl->initialiser = lr_count; 00883 lr_count->container = l_enum_vals; 00884 lr_int->width = MakeTreePtr<SpecificInteger>(32); // TODO should be a common place for getting default types 00885 lr_state_id->sources = (ls_label->identifier); 00886 lr_comp->members = (l_decls); 00887 lr_comp->statements = (l_pre, lr_if, l_post); // do final block first 00888 lr_if->condition = lr_equal; 00889 lr_if->body = lr_if_comp; 00890 lr_if->else_body = MakeTreePtr<Nop>(); 00891 lr_equal->operands = (ls_label_id, var_id); 00892 //lr_if_comp->members = (); 00893 lr_if_comp->statements = l_block; 00894 00895 ll_all->patterns = (ll_any, lls_not1, lls_not2); // TODO don't think we need the nots 00896 ll_any->terminus = ll_over; 00897 ll_over->through = ls_label_id; 00898 ll_over->overlay = lr_state_id; 00899 lls_not1->pattern = lls_goto; 00900 lls_goto->destination = ls_label_id; // leave gotos alone in the body 00901 lls_not2->pattern = lls_label; 00902 lls_label->identifier = ls_label_id; // leave labels alone in the body 00903 00904 Configure( fn ); 00905 } 00906 #endif 00907 00908 00909 00910 AddYieldFlag::AddYieldFlag() 00911 { 00912 MakeTreePtr<Instance> fn; 00913 MakeTreePtr<InstanceIdentifier> fn_id; 00914 MakeTreePtr<Callable> sub; 00915 MakeTreePtr<Compound> s_func_comp, r_func_comp, s_comp, r_comp, ms_comp, mr_comp, msx_comp; 00916 MakeTreePtr< Star<Declaration> > enums, decls, func_decls, m_decls, msx_decls; 00917 MakeTreePtr<Instance> var_decl; 00918 MakeTreePtr<InstanceIdentifier> var_id; 00919 MakeTreePtr<TypeIdentifier> enum_id; 00920 MakeTreePtr< Star<Statement> > func_pre, m_pre, msx_pre, m_post, msx_post, stmts; 00921 MakeTreePtr< Star<If> > l_pre, l_post; 00922 MakeTreePtr<Loop> loop; 00923 MakeTreePtr<If> ls_if, lr_if, ms_if, mr_if; 00924 MakeTreePtr<Wait> m_wait; 00925 MakeTreePtr<Enum> enum_decl; 00926 MakeTreePtr<Equal> l_equal; 00927 MakeTreePtr<LogicalAnd> lr_and; 00928 MakeTreePtr<LogicalNot> lr_not; 00929 MakeTreePtr< Overlay<Compound> > func_over, over; 00930 MakeTreePtr<Temporary> r_flag_decl; 00931 MakeTreePtr<Assign> r_flag_init, mr_assign, msx_assign; 00932 MakeTreePtr<BuildInstanceIdentifier> r_flag_id("yield_flag"); 00933 MakeTreePtr< MatchAll<Compound> > ms_all; 00934 MakeTreePtr< NotMatch<Compound> > ms_not; 00935 00936 MakeTreePtr< SlaveSearchReplace<Compound> > slavem( r_func_comp, ms_all, mr_comp ); 00937 MakeTreePtr< SlaveSearchReplace<Compound> > slave( r_comp, ls_if, lr_if ); 00938 00939 fn->type = sub; 00940 fn->initialiser = func_over; 00941 fn->identifier = fn_id; 00942 func_over->through = s_func_comp; 00943 s_func_comp->members = (func_decls); 00944 s_func_comp->statements = (func_pre, loop); 00945 loop->body = over; 00946 over->through = s_comp; 00947 s_comp->members = decls; 00948 s_comp->statements = (stmts); 00949 stmts->pattern = MakeTreePtr<If>(); // anti-spin 00950 func_over->overlay = slavem; 00951 r_func_comp->members = (func_decls); 00952 r_flag_init->operands = (r_flag_id, MakeTreePtr<False>()); 00953 r_func_comp->statements = (func_pre, loop); 00954 r_flag_decl->identifier = r_flag_id; 00955 r_flag_decl->type = MakeTreePtr<Boolean>(); 00956 r_flag_decl->initialiser = MakeTreePtr<Uninitialised>(); 00957 over->overlay = slave; 00958 r_comp->members = (decls, r_flag_decl); 00959 r_comp->statements = (r_flag_init, stmts); 00960 00961 ls_if->condition = l_equal; 00962 l_equal->operands = (MakeTreePtr<InstanceIdentifier>(), MakeTreePtr<InstanceIdentifier>()); 00963 // TODO yield_id should be of type enum_id? 00964 lr_if->condition = lr_and; 00965 lr_and->operands = (l_equal, lr_not); 00966 lr_not->operands = (r_flag_id); 00967 00968 ms_all->patterns = (ms_comp, ms_not); 00969 ms_comp->members = (m_decls); 00970 ms_comp->statements = (m_pre, m_wait, m_post); 00971 ms_not->pattern = msx_comp; 00972 msx_comp->members = msx_decls; 00973 msx_comp->statements = (msx_pre, msx_assign, msx_post); 00974 msx_assign->operands = (r_flag_id, MakeTreePtr<Bool>()); 00975 00976 mr_comp->members = (m_decls); 00977 mr_comp->statements = (m_pre, m_wait, mr_assign, m_post); 00978 mr_assign->operands = (r_flag_id, MakeTreePtr<True>()); 00979 00980 Configure( fn ); 00981 } 00982 00983 AddInferredYield::AddInferredYield() 00984 { 00985 MakeTreePtr<Instance> fn; 00986 MakeTreePtr<InstanceIdentifier> fn_id; 00987 MakeTreePtr<Thread> thread; // Must be SC_THREAD since we introduce new yield here, only makes sense in SC_THREAD 00988 MakeTreePtr<Compound> func_comp, s_comp, sx_comp, r_comp; 00989 MakeTreePtr< Star<Declaration> > func_decls; 00990 MakeTreePtr< Star<Statement> > func_pre, stmts, sx_pre; 00991 MakeTreePtr< Overlay<Statement> > over; 00992 MakeTreePtr<LocalVariable> flag_decl; 00993 MakeTreePtr<InstanceIdentifier> flag_id; 00994 MakeTreePtr<WaitDelta> r_yield; 00995 MakeTreePtr<Loop> loop; 00996 MakeTreePtr<If> r_if, sx_if; 00997 MakeTreePtr< MatchAll<Compound> > s_all; 00998 MakeTreePtr< NotMatch<Compound> > s_notmatch; 00999 MakeTreePtr< LogicalNot > r_not, sx_not; 01000 MakeTreePtr< Assign > assign; 01001 01002 fn->type = thread; 01003 fn->initialiser = func_comp; 01004 fn->identifier = fn_id; 01005 func_comp->members = (func_decls); 01006 flag_decl->type = MakeTreePtr<Boolean>(); 01007 flag_decl->initialiser = MakeTreePtr<Uninitialised>(); 01008 flag_decl->identifier = flag_id; 01009 func_comp->statements = (func_pre, loop); 01010 loop->body = over; 01011 over->through = s_all; 01012 s_all->patterns = (s_comp, s_notmatch); 01013 s_comp->members = (flag_decl); 01014 s_comp->statements = (stmts); 01015 s_notmatch->pattern = sx_comp; 01016 sx_comp->members = (flag_decl); 01017 sx_comp->statements = (sx_pre, sx_if); 01018 sx_if->condition = sx_not; 01019 sx_not->operands = (flag_id); 01020 01021 over->overlay = r_comp; 01022 r_comp->members = (flag_decl); 01023 r_comp->statements = (stmts, r_if); 01024 r_if->condition = r_not; 01025 r_not->operands = (flag_id); 01026 r_if->body = r_yield; 01027 r_if->else_body = MakeTreePtr<Nop>(); 01028 01029 Configure( fn ); 01030 } 01031 01032 01033 MoveInitIntoSuperLoop::MoveInitIntoSuperLoop() 01034 { 01035 MakeTreePtr<Instance> fn; 01036 MakeTreePtr<InstanceIdentifier> fn_id; 01037 MakeTreePtr<Thread> thread; // Must be SC_THREAD since we introduce SC stuff 01038 MakeTreePtr< Star<Declaration> > func_decls; 01039 MakeTreePtr< Star<Statement> > inits, stmts; 01040 MakeTreePtr<Loop> loop; 01041 MakeTreePtr<Compound> s_func_comp, r_func_comp, s_comp, r_comp, r_if_comp; 01042 MakeTreePtr<If> r_if; 01043 MakeTreePtr<Equal> r_equal; 01044 MakeTreePtr< Overlay<Compound> > func_over, over; 01045 MakeTreePtr<Statement> first_init; 01046 01047 fn->type = thread; 01048 fn->initialiser = func_over; 01049 fn->identifier = fn_id; 01050 func_over->through = s_func_comp; 01051 s_func_comp->members = (func_decls); 01052 s_func_comp->statements = (first_init, inits, loop); 01053 loop->body = over; 01054 over->through = s_comp; 01055 // s_comp->members = (); 01056 s_comp->statements = (stmts); 01057 01058 func_over->overlay = r_func_comp; 01059 r_func_comp->members = (func_decls); 01060 r_func_comp->statements = (loop); 01061 over->overlay = r_comp; 01062 // r_comp->members = (); 01063 r_comp->statements = (r_if, stmts); 01064 r_if->condition = r_equal; 01065 r_equal->operands = ( MakeTreePtr<DeltaCount>(), MakeTreePtr<SpecificInteger>(0) ); 01066 r_if->body = r_if_comp; 01067 // r_if_comp->members = (); 01068 r_if_comp->statements = (first_init, inits);//, MakeTreePtr<WaitDelta>()); 01069 r_if->else_body = MakeTreePtr<Nop>(); 01070 01071 Configure( fn ); 01072 } 01073 01074 01075 // rotate loops to avoid inferred yields when an explicit yield already exists 01076 LoopRotation::LoopRotation() 01077 { 01078 MakeTreePtr<Instance> fn, s_var_decl; 01079 MakeTreePtr<InstanceIdentifier> fn_id, s_var_id, s_cur_enum_id, s_outer_enum_id; 01080 MakeTreePtr<Thread> thread; // Must be SC_THREAD since we introduce SC stuff 01081 MakeTreePtr< Star<Declaration> > func_decls, decls, s_enums; 01082 MakeTreePtr<Static> s_cur_enum, s_outer_enum; 01083 MakeTreePtr< Star<Statement> > inits, stmts, pre, post, prepre, prepost, postpre, postpost; 01084 MakeTreePtr<Loop> loop; 01085 MakeTreePtr<Compound> func_comp, s_comp_loop, s_comp_yield, r_comp, r_if_comp, sx_comp; 01086 MakeTreePtr<If> loop_top, loop_bottom, yield, outer_bottom, outer_top; 01087 MakeTreePtr< Star<If> > loop_body, pre_yield, post_yield; 01088 MakeTreePtr<Equal> r_equal; 01089 MakeTreePtr< Overlay<Compound> > func_over, over; 01090 MakeTreePtr< MatchAll<Compound> > s_all; 01091 MakeTreePtr<Enum> s_enum; 01092 MakeTreePtr<TypeIdentifier> s_enum_id; 01093 MakeTreePtr< Stuff<Expression> > loop_top_stuff, outer_top_stuff; 01094 MakeTreePtr<Equal> loop_top_equal, outer_top_equal; 01095 MakeTreePtr< Stuff<Statement> > loop_bottom_stuff_enum, outer_bottom_stuff_enum, 01096 loop_bottom_stuff_noyield, yield_stuff, outer_bottom_stuff_noyield; 01097 MakeTreePtr< MatchAll<Statement> > loop_bottom_matchall, outer_bottom_matchall; 01098 MakeTreePtr< NotMatch<Statement> > loop_bottom_notmatch, outer_bottom_notmatch; 01099 MakeTreePtr< NotMatch<Compound> > s_notmatch; 01100 MakeTreePtr< MatchAny<If> > inner_state; 01101 01102 fn->type = thread; 01103 fn->initialiser = func_comp; 01104 fn->identifier = fn_id; 01105 func_comp->members = (func_decls, /*s_enum,*/ s_var_decl); // enum removed because it is class member, not local to the function 01106 s_enum->identifier = s_enum_id; 01107 s_enum->members = (s_enums, s_cur_enum); 01108 s_cur_enum->identifier = s_cur_enum_id; 01109 s_outer_enum->identifier = s_outer_enum_id; 01110 s_var_decl->type = s_enum_id; 01111 s_var_decl->identifier = s_var_id; 01112 func_comp->statements = (inits, loop); 01113 loop->body = over; 01114 over->through = s_all; 01115 s_all->patterns = (s_comp_loop, s_comp_yield, s_notmatch); 01116 s_comp_loop->members = (decls); 01117 // Search for a loop. Assume that a state enum value in a body means "could transition to the state" and one in 01118 // the condition means "acts on the state". If we see the latter with the former blow it somewhere, we call 01119 // it a loop and assume the upward branch is normally takner as with C compilers. 01120 s_comp_loop->statements = (pre, loop_top, loop_body, loop_bottom, post); 01121 loop_top->condition = loop_top_stuff; 01122 loop_top_stuff->terminus = loop_top_equal; 01123 loop_top_equal->operands = (s_var_id, s_cur_enum_id); 01124 loop_bottom->body = loop_bottom_matchall; 01125 loop_bottom_matchall->patterns = (loop_bottom_stuff_enum, loop_bottom_notmatch); 01126 loop_bottom_stuff_enum->terminus = s_cur_enum_id; 01127 loop_bottom_notmatch->pattern = loop_bottom_stuff_noyield; 01128 loop_bottom_stuff_noyield->terminus = MakeTreePtr<Wait>(); 01129 s_comp_yield->members = (decls); 01130 01131 // We need to restruct to loops that contain a yield anywhere but the bottom - these are the ones 01132 // that would benefit from loop rotation. 01133 s_comp_yield->statements = (pre, pre_yield, yield, post_yield, loop_bottom, post); 01134 yield->body = yield_stuff; 01135 yield_stuff->terminus = MakeTreePtr<Wait>(); 01136 01137 // This part is to make sure we operate on the outermost loop first - look for another loop surrounding 01138 // the current one, if it does not end in a yield, then do not transform. This way the outer loop will 01139 // keep getting hits until the yield is at the bottom, then inner loops can have a go. 01140 s_notmatch->pattern = sx_comp; 01141 sx_comp->members = (decls); 01142 sx_comp->statements = (prepre, outer_top, postpre, inner_state, prepost, outer_bottom, postpost); 01143 outer_top->condition = outer_top_stuff; 01144 outer_top_stuff->terminus = outer_top_equal; 01145 outer_top_equal->operands = (s_var_id, s_outer_enum_id); 01146 outer_bottom->body = outer_bottom_matchall; 01147 outer_bottom_matchall->patterns = (outer_bottom_stuff_enum, outer_bottom_notmatch); 01148 outer_bottom_stuff_enum->terminus = s_outer_enum_id; 01149 outer_bottom_notmatch->pattern = outer_bottom_stuff_noyield; 01150 outer_bottom_stuff_noyield->terminus = MakeTreePtr<Wait>(); 01151 inner_state->patterns = (loop_top, loop_bottom); // outer loop can share top or bottom state with inner loop; but not both, so at least one must be here 01152 01153 over->overlay = r_comp; 01154 r_comp->members = (decls); 01155 r_comp->statements = (pre, loop_bottom, loop_top, loop_body, post); // rotated version of s_comp_loop 01156 01157 Configure( fn ); 01158 } 01159 01160