Inferno  0.2
generate_stacks.cpp
Go to the documentation of this file.
00001 /*
00002  * generate_stacks.cpp
00003  *
00004  *  Created on: 27 Oct 2009
00005  *      Author: jgraley
00006  */
00007 
00008 #include "steps/generate_stacks.hpp"
00009 #include "tree/cpptree.hpp"
00010 #include "common/common.hpp"
00011 #include "sr/soft_patterns.hpp"
00012 #include "tree/sctree.hpp"
00013 #include "inferno_patterns.hpp"
00014 
00015 using namespace CPPTree;
00016 using namespace Steps;
00017 using namespace SCTree;
00018 
00019 /// Place return at end of void functions, if not already there
00020 ExplicitiseReturn::ExplicitiseReturn()
00021 {
00022     MakeTreePtr< Instance > fi;
00023     MakeTreePtr<Compound> s_comp, sx_comp, r_comp;        
00024     MakeTreePtr< Star<Statement> > pre, sx_pre;
00025     MakeTreePtr< Star<Declaration> > decls;
00026     MakeTreePtr< Overlay<Compound> > over;
00027     MakeTreePtr<Return> sx_return, r_return;
00028     MakeTreePtr< MatchAny<Callable> > s_any;
00029     MakeTreePtr<Function> s_func;
00030     MakeTreePtr<Procedure> s_proc;
00031     MakeTreePtr< MatchAll<Compound> > s_all;
00032     MakeTreePtr< NotMatch<Compound> > s_not;
00033         
00034     fi->type = s_any;
00035     s_any->patterns = (s_func, s_proc, MakeTreePtr<Subroutine>() );
00036     s_proc->members = MakeTreePtr< Star<Declaration> >();
00037     s_func->members = MakeTreePtr< Star<Declaration> >();
00038     s_func->return_type = MakeTreePtr< Void >();
00039     fi->initialiser = over;
00040     s_comp->members = decls;
00041     s_comp->statements = (pre);
00042     over->through = s_all;
00043     s_all->patterns = (s_comp, s_not);
00044     s_not->pattern = sx_comp;
00045     sx_comp->members = decls;
00046     sx_comp->statements = (sx_pre, sx_return);
00047     
00048     over->overlay = r_comp;
00049     r_comp->members = decls;
00050     r_comp->statements = (pre, r_return);
00051     r_return->return_value = MakeTreePtr<Uninitialised>();
00052     
00053     Configure( fi );
00054 }    
00055 
00056 
00057 UseTempForReturnValue::UseTempForReturnValue()
00058 {
00059     // search for return statement in a compound (TODO don't think we need the outer compound)
00060     TreePtr<Return> s_return( new Return );
00061     TreePtr< MatchAll<Expression> > s_and( new MatchAll<Expression> );
00062     s_return->return_value = s_and;
00063     MakeTreePtr< TransformOf<Expression> > retval( &TypeOf::instance );
00064     MakeTreePtr<Type> type;
00065     retval->pattern = type;
00066     
00067     // Restrict the search to returns that have an automatic variable under them
00068     TreePtr< Stuff<Expression> > cs_stuff( new Stuff<Expression> ); // TODO the exclusion Stuff<GetDec<Automatic>> is too strong;
00069                                                                     // use Not<GetDec<Temp>>
00070     s_and->patterns = ( retval, cs_stuff );
00071     MakeTreePtr< TransformOf<InstanceIdentifier> > cs_id( &GetDeclaration::instance );
00072     cs_stuff->terminus = cs_id;
00073     TreePtr<Instance> cs_instance( new Automatic );
00074     cs_id->pattern = cs_instance;
00075     
00076     // replace with a new sub-compound, that declares a Temp, intialises it to the return value and returns it
00077     TreePtr<Compound> r_sub_comp( new Compound );
00078     TreePtr< Temporary > r_newvar( new Temporary );
00079     r_newvar->type = type;
00080     MakeTreePtr<BuildInstanceIdentifier> id("temp_retval");
00081     r_newvar->identifier = id;
00082     r_newvar->initialiser = MakeTreePtr<Uninitialised>();
00083     r_sub_comp->members = ( r_newvar );
00084     TreePtr<Assign> r_assign( new Assign );
00085     r_assign->operands.push_back( id );
00086     r_assign->operands.push_back( retval );
00087     r_sub_comp->statements.push_back( r_assign );
00088     TreePtr<Return> r_return( new Return );
00089     r_sub_comp->statements.push_back( r_return );
00090     r_return->return_value = id;
00091        
00092     Configure( s_return, r_sub_comp );
00093 }
00094 
00095 
00096 ReturnViaTemp::ReturnViaTemp()
00097 {
00098     MakeTreePtr<Scope> module;
00099     MakeTreePtr<Instance> func;
00100     MakeTreePtr< Star<Declaration> > decls;
00101     MakeTreePtr< Star<Base> > bases;
00102     MakeTreePtr<Function> cp;
00103     MakeTreePtr< NotMatch<Type> > return_type;
00104     MakeTreePtr<Void> sx_void;
00105     MakeTreePtr<Compound> s_body, r_body, lr_comp;
00106     MakeTreePtr< Star<Statement> > statements;
00107     MakeTreePtr< Star<Declaration> > locals;
00108     MakeTreePtr<InstanceIdentifier> func_id;
00109     MakeTreePtr<TypeIdentifier> module_id;
00110     MakeTreePtr< Star<Instance> > params;
00111     MakeTreePtr<Call> m_call;
00112     MakeTreePtr< Star<MapOperand> > m_operands;
00113     MakeTreePtr<Temporary> r_temp;
00114     MakeTreePtr<Assign> mr_assign, lr_assign;
00115     MakeTreePtr<BuildInstanceIdentifier> r_temp_id("%s_return");
00116     MakeTreePtr<Return> ls_return, lr_return;
00117     MakeTreePtr<Expression> l_return_value;
00118     MakeTreePtr<CompoundExpression> mr_comp;
00119     MakeTreePtr< GreenGrass<Call> > ms_gg;
00120     MakeTreePtr< Overlay<Type> > overcp;
00121     MakeTreePtr< Overlay<Initialiser> > overi;
00122     MakeTreePtr< Insert<Declaration> > insert;
00123     
00124     MakeTreePtr< SlaveSearchReplace<Compound> > slavel( r_body, ls_return, lr_comp );
00125     ls_return->return_value = l_return_value; // note this also pre-restricts away Return<Uninitialised>
00126     lr_comp->statements = (lr_assign, lr_return);
00127     lr_assign->operands = (r_temp_id, l_return_value);
00128     lr_return->return_value = MakeTreePtr<Uninitialised>(); // means no return value given
00129 
00130     ms_gg->through = m_call;
00131     m_call->callee = func_id;
00132     m_call->operands = (m_operands);
00133     mr_comp->statements = (m_call, r_temp_id);
00134     MakeTreePtr< SlaveSearchReplace<Scope> > slavem( module, ms_gg, mr_comp );
00135     
00136     module->members = (decls, func, insert);
00137     insert->insert = (r_temp);
00138     func->type = cp;
00139     func->initialiser = overi;
00140     overi->through = s_body;
00141     func->identifier = func_id;
00142     s_body->members = (locals);
00143     s_body->statements = (statements);
00144     cp->members = (params);  
00145     cp->return_type = overcp;
00146     overcp->through = return_type;
00147     return_type->pattern = sx_void;
00148     overi->overlay = slavel;
00149     r_body->members = (locals);
00150     r_body->statements = (statements);
00151     overcp->overlay = MakeTreePtr<Void>();
00152     r_temp->initialiser = MakeTreePtr<Uninitialised>();
00153     r_temp->type = return_type;
00154     r_temp->identifier = r_temp_id;
00155     r_temp_id->sources = (func_id);
00156     
00157     Configure( module, slavem );  
00158 }
00159 
00160 
00161 
00162 struct TempReturnAddress : Temporary
00163 {
00164     NODE_FUNCTIONS_FINAL
00165 };
00166 
00167 
00168 AddLinkAddress::AddLinkAddress()
00169 {
00170     MakeTreePtr<Scope> module;
00171     MakeTreePtr< Star<Declaration> > decls;    
00172     MakeTreePtr< Star<Base> > bases;    
00173     MakeTreePtr<Temporary> r_retaddr;
00174     MakeTreePtr<BuildInstanceIdentifier> r_retaddr_id("%s_link");
00175     MakeTreePtr<Automatic> lr_retaddr;
00176     MakeTreePtr<BuildInstanceIdentifier> lr_retaddr_id("link");
00177     MakeTreePtr<TempReturnAddress> lr_temp_retaddr;
00178     MakeTreePtr<BuildInstanceIdentifier> lr_temp_retaddr_id("temp_link");
00179     MakeTreePtr< NotMatch<Declaration> > s_nm, ls_nm;
00180     MakeTreePtr< GreenGrass<Declaration> > gg;
00181     MakeTreePtr<Instance> l_inst;
00182     MakeTreePtr< Overlay<Compound> > l_over;
00183     MakeTreePtr<Compound> ls_comp, lr_comp;
00184     MakeTreePtr< Star<Declaration> > l_decls;
00185     MakeTreePtr< Star<Statement> > l_stmts, msx_stmts;
00186     MakeTreePtr<Assign> msx_assign;
00187     MakeTreePtr<Call> ms_call, mr_call;
00188     MakeTreePtr<Compound> mr_comp, msx_comp;
00189     MakeTreePtr<Label> mr_label;
00190     MakeTreePtr<BuildLabelIdentifier> mr_labelid("LINK");
00191     MakeTreePtr< MatchAll<Statement> > m_all;
00192     MakeTreePtr< AnyNode<Statement> > m_any; // TODO rename AnyNode -> Blob
00193     MakeTreePtr< NotMatch<Statement> > ms_not;
00194     MakeTreePtr< Overlay<Statement> > m_over;
00195     MakeTreePtr< Overlay<Function> > l_func_over;
00196     MakeTreePtr<Function> ls_func, lr_func;
00197     MakeTreePtr<TypeIdentifier> ident;
00198     MakeTreePtr<InstanceIdentifier> l_inst_id;
00199     MakeTreePtr<Return> ll_return;
00200     MakeTreePtr<Compound> llr_comp, llsx_comp;
00201     MakeTreePtr<Assign> llr_assign, llsx_assign;
00202     MakeTreePtr< MatchAll<Statement> > ll_all;
00203     MakeTreePtr< AnyNode<Statement> > ll_any;
00204     MakeTreePtr< NotMatch<Statement> > lls_not;
00205     MakeTreePtr< Overlay<Statement> > ll_over;
00206     MakeTreePtr< GreenGrass<Statement> > m_gg, ll_gg;
00207     MakeTreePtr<MapOperand> mr_operand;
00208     MakeTreePtr< Insert<Declaration> > insert;
00209 
00210     ll_gg->through = ll_return;
00211     ll_over->overlay = llr_comp;        
00212     //llr_comp->members = ();
00213     llr_comp->statements = (llr_assign, ll_return);
00214     llr_assign->operands = (lr_temp_retaddr_id, lr_retaddr_id);
00215    
00216     MakeTreePtr< SlaveSearchReplace<Compound> > slavell( lr_comp, ll_gg, llr_comp );   
00217    
00218     m_gg->through = ms_call;
00219     ms_call->operands = (MakeTreePtr< Star<MapOperand> >());
00220     ms_call->callee = l_inst_id;
00221     mr_comp->statements = (mr_call, mr_label);  
00222     mr_call->operands = (ms_call->operands, mr_operand);
00223     mr_call->callee = l_inst_id;
00224     mr_operand->identifier = lr_retaddr_id;
00225     mr_operand->value = mr_labelid;
00226     mr_label->identifier = mr_labelid;    
00227     
00228     MakeTreePtr< SlaveSearchReplace<Scope> > slavem( module, m_gg, mr_comp );
00229     
00230     l_inst->type = l_func_over;
00231     l_func_over->through = ls_func;
00232     l_func_over->overlay = lr_func;    
00233     ls_func->return_type = MakeTreePtr<Void>();
00234     ls_func->members = MakeTreePtr< Star<Instance> >(); // Params OK here, just not in MergeFunctions
00235     lr_func->return_type = ls_func->return_type;
00236     lr_func->members = (ls_func->members, lr_retaddr);
00237     l_inst->initialiser = l_over;
00238     l_inst->identifier = l_inst_id;
00239     l_over->through = ls_comp;
00240     ls_comp->members = (l_decls);
00241     ls_comp->statements = (l_stmts);
00242     l_over->overlay = slavell;
00243     lr_comp->members = (l_decls, lr_temp_retaddr);
00244     lr_retaddr->identifier = lr_retaddr_id;
00245     lr_retaddr->type = MakeTreePtr<Labeley>();
00246     lr_retaddr->initialiser = MakeTreePtr<Uninitialised>();
00247     lr_temp_retaddr->identifier = lr_temp_retaddr_id;
00248     lr_temp_retaddr->type = MakeTreePtr<Labeley>();
00249     lr_temp_retaddr->initialiser = MakeTreePtr<Uninitialised>();
00250     lr_comp->statements = (l_stmts);
00251     
00252     module->members = (gg, decls, insert);
00253     insert->insert = (r_retaddr);
00254     gg->through = l_inst;
00255     r_retaddr->identifier = r_retaddr_id;
00256     r_retaddr->type = MakeTreePtr<Labeley>();
00257     r_retaddr->initialiser = MakeTreePtr<Uninitialised>();
00258     //r_retaddr->virt = MakeTreePtr<NonVirtual>();
00259     //r_retaddr->access = MakeTreePtr<Private>();
00260     //r_retaddr->constancy = MakeTreePtr<NonConst>();
00261     r_retaddr_id->sources = (l_inst_id);
00262     Configure( module, slavem );  
00263 }
00264 
00265 
00266 ParamsViaTemps::ParamsViaTemps()
00267 {
00268     MakeTreePtr<Scope> module;
00269     MakeTreePtr<Instance> func;
00270     MakeTreePtr< Star<Declaration> > decls;
00271     MakeTreePtr< Star<Base> > bases;
00272     MakeTreePtr<Function> s_cp, r_cp;
00273     MakeTreePtr<Type> return_type;
00274     MakeTreePtr<Compound> body, mr_comp;
00275     MakeTreePtr< Star<Statement> > statements;
00276     MakeTreePtr< Star<Declaration> > locals;
00277     MakeTreePtr<InstanceIdentifier> func_id, param_id;
00278     MakeTreePtr<TypeIdentifier> module_id;
00279     MakeTreePtr<Instance> s_param;
00280     MakeTreePtr< Star<Instance> > params;
00281     MakeTreePtr<Call> ms_call, mr_call;
00282     MakeTreePtr<MapOperand> ms_operand;
00283     MakeTreePtr< Star<MapOperand> > m_operands;
00284     MakeTreePtr<Automatic> r_param;
00285     MakeTreePtr<Type> param_type;
00286     MakeTreePtr<Temporary> r_temp;
00287     MakeTreePtr<Assign> mr_assign;
00288     MakeTreePtr<Expression> m_expr;
00289     MakeTreePtr<BuildInstanceIdentifier> r_temp_id("%s_%s");
00290     MakeTreePtr< Insert<Declaration> > insert;
00291     MakeTreePtr< Insert<Statement> > ins_param;    
00292     MakeTreePtr< Overlay<Type> > over;
00293     
00294     ms_call->callee = func_id;
00295     ms_call->operands = (m_operands, ms_operand);
00296     ms_operand->identifier = param_id;
00297     ms_operand->value = m_expr;
00298     mr_comp->statements = (mr_assign, mr_call);
00299     mr_assign->operands = (r_temp_id, m_expr);
00300     mr_call->callee = func_id;
00301     mr_call->operands = (m_operands);
00302     MakeTreePtr< SlaveSearchReplace<Scope> > slavem( module, ms_call, mr_comp );
00303     
00304     module->members = (decls, func, insert);
00305     func->type = over;
00306     over->through = s_cp;
00307     func->initialiser = body;
00308     func->identifier = func_id;
00309     body->members = (locals);
00310     body->statements = (ins_param, statements);
00311     s_cp->members = (params, s_param);  
00312     s_cp->return_type = return_type;
00313     s_param->identifier = param_id;
00314     s_param->type = param_type;
00315     over->overlay = r_cp;
00316     ins_param->insert = r_param;
00317     r_param->type = param_type;
00318     r_param->initialiser = r_temp_id;
00319     r_param->identifier = param_id;
00320     r_cp->members = (params);
00321     r_cp->return_type = return_type;
00322     insert->insert = (r_temp);
00323     r_temp->type = param_type;
00324     r_temp->initialiser = MakeTreePtr<Uninitialised>();
00325     r_temp->identifier = r_temp_id;
00326     r_temp_id->sources = (func_id, param_id);
00327     
00328     Configure( module, slavem );  
00329 }
00330 
00331 
00332 GenerateStacks::GenerateStacks()
00333 {
00334     // Search for a function and require it to have at least one automatic
00335     // variable using an and rule. Add a stack index variable (static) to the 
00336     // function. Increment at the beginning of the function body and decrement 
00337     // at the end. 
00338     //
00339     // Use a slave to find automatic variables in the function. Replace them
00340     // with arrays of the same type. Using another slave, add a decrement of
00341     // the stack pointer before any return statements.
00342     //
00343     // Using a sub-slave of the variable-finding slave, look for usages of 
00344     // the variable. Replace with an indexing operation into the array using
00345     // the stack index.    
00346     MakeTreePtr<Instance> fi, l_fi;
00347     MakeTreePtr< Overlay<Initialiser> > oinit;
00348     MakeTreePtr<Thread> sx_thread;
00349     MakeTreePtr<Method> sx_method;
00350     MakeTreePtr< MatchAny<Type> > sx_any;
00351     MakeTreePtr< NotMatch<Type> > s_not;
00352     MakeTreePtr< MatchAll<Initialiser> > s_and;
00353     MakeTreePtr<Compound> s_top_comp, r_top_comp, r_ret_comp, temp;
00354     MakeTreePtr< Star<Declaration> > top_decls;
00355     MakeTreePtr< Star<Statement> > top_pre;
00356     MakeTreePtr< Stuff<Initialiser> > stuff;
00357     MakeTreePtr< Stuff<Compound> > cs_stuff;
00358     MakeTreePtr< Overlay<Statement> > overlay;
00359     MakeTreePtr<Automatic> cs_instance, s_instance;
00360     MakeTreePtr<Field> r_index, r_instance;
00361     MakeTreePtr<Unsigned> r_index_type;
00362     MakeTreePtr<PostIncrement> r_inc;
00363     MakeTreePtr<PostDecrement> r_ret_dec;
00364     MakeTreePtr<InstanceIdentifier> s_identifier;
00365     MakeTreePtr<Array> r_array;
00366     MakeTreePtr<Return> ret;
00367     MakeTreePtr<Subscript> l_r_sub;
00368     MakeTreePtr< MatchAll<Node> > s_and3;
00369     MakeTreePtr<BuildInstanceIdentifier> r_index_identifier("%s_stack_index");
00370     MakeTreePtr<BuildInstanceIdentifier> r_identifier("%s_stack");
00371     MakeTreePtr< GreenGrass<Statement> > s_gg;
00372     MakeTreePtr<Assign> r_index_init;
00373     MakeTreePtr< Star<Declaration> > members;
00374     MakeTreePtr<Scope> module, l_module;
00375     MakeTreePtr< Star<Base> > bases, l_bases;
00376     MakeTreePtr<TypeIdentifier> module_id, l_module_id;
00377     MakeTreePtr<Compound> s_vcomp, r_vcomp;
00378     MakeTreePtr< Star<Declaration> > vdecls, l_members;
00379     MakeTreePtr< Star<Statement> > vstmts;
00380     MakeTreePtr<InstanceIdentifier> fi_id;
00381     MakeTreePtr< Insert<Declaration> > insert, l_insert;
00382 
00383     // Sub-slave replace with a subscript into the array
00384     l_r_sub->operands = ( r_identifier, r_index_identifier );
00385 
00386     MakeTreePtr< SlaveSearchReplace<Statement> > r_slave( r_vcomp, s_identifier, l_r_sub );
00387 
00388     // SlaveSearchReplace search to find automatic variables within the function
00389     stuff->terminus = overlay;
00390     overlay->through = s_vcomp;
00391     s_vcomp->members = (vdecls, s_instance);
00392     s_vcomp->statements = (vstmts);
00393     s_instance->identifier = s_identifier;
00394     s_instance->initialiser = MakeTreePtr<Uninitialised>(); 
00395     s_instance->type = MakeTreePtr<Type>();
00396 
00397     // SlaveSearchReplace replace to insert as a static array (TODO be a member of enclosing class)
00398     r_instance->constancy = MakeTreePtr<NonConst>();
00399     r_instance->initialiser = MakeTreePtr<Uninitialised>();
00400     overlay->overlay = r_slave;
00401     r_vcomp->members = (vdecls);
00402     r_vcomp->statements = (vstmts);
00403     r_identifier->sources = (s_identifier);
00404     r_instance->identifier = r_identifier;
00405     r_instance->type = r_array;
00406     r_instance->virt = MakeTreePtr<NonVirtual>();
00407     r_instance->access = MakeTreePtr<Private>();
00408     r_array->element = s_instance->type;
00409     r_array->size = MakeTreePtr<SpecificInteger>(10);
00410 
00411     // SlaveSearchReplace to find early returns in the function
00412     s_gg->through = ret;
00413 
00414     // SlaveSearchReplace replace with a decrement of the stack index coming before the return
00415     //r_ret_comp->members = ( r_ret_decls );
00416     r_ret_dec->operands = ( r_index_identifier );
00417     r_ret_comp->statements = ( r_ret_dec, ret );
00418 
00419     l_module->members = (l_members, l_fi, l_insert);
00420     l_insert->insert = (r_instance);
00421     l_fi->initialiser = stuff;
00422     l_fi->identifier = fi_id;
00423     
00424     MakeTreePtr< SlaveCompareReplace<Scope> > r_mid( module, l_module ); // stuff, stuff
00425 
00426     MakeTreePtr< SlaveSearchReplace<Statement> > r_slave3( r_top_comp, s_gg, r_ret_comp );
00427     temp->statements = (r_slave3);
00428     oinit->overlay = temp;//r_slave3; 
00429     
00430     // Master search - look for functions satisfying the construct limitation and get
00431     module->members = (fi, members, insert);
00432     insert->insert = (r_index);
00433     fi->identifier = fi_id;
00434     fi->type = s_not;
00435     s_not->pattern = sx_any;
00436     sx_any->patterns = (sx_thread, sx_method); // Do not provide stacks for these because they do not recurse
00437     fi->initialiser = oinit;   
00438     oinit->through = s_and;
00439     s_top_comp->members = ( top_decls );
00440     s_top_comp->statements = ( top_pre );
00441 
00442     // Construct limitation - restrict master search to functions that contain an automatic variable
00443     cs_stuff->terminus = cs_instance;
00444     s_and->patterns = ( s_top_comp, cs_stuff );
00445 
00446     // Master replace - insert index variable, inc and dec into function at top level
00447     // top-level decls
00448     r_top_comp->members = (top_decls);
00449     r_index->type = r_index_type;
00450     r_index_type->width = MakeTreePtr<SpecificInteger>(32);
00451     r_index_identifier->sources = (fi->identifier);
00452     r_index->identifier = r_index_identifier;
00453     r_index->constancy = MakeTreePtr<NonConst>();
00454     r_index->initialiser = MakeTreePtr<SpecificInteger>(0);
00455     //r_index->initialiser = MakeTreePtr<SpecificInteger>(0);
00456     r_index_init->operands = (r_index_identifier, MakeTreePtr<SpecificInteger>(0));
00457     r_index->virt = MakeTreePtr<NonVirtual>();
00458     r_index->access = MakeTreePtr<Private>();
00459 
00460     // top-level statements
00461     r_inc->operands = ( r_index_identifier );
00462     r_top_comp->statements = ( r_inc, top_pre );
00463 
00464     Configure( module, r_mid );
00465 }
00466 
00467 /*
00468 OLD VERSION
00469 GenerateStacks::GenerateStacks()
00470 {
00471     // Search for a function and require it to have at least one automatic
00472     // variable using an and rule. Add a stack index variable (static) to the 
00473     // function. Increment at the beginning of the function body and decrement 
00474     // at the end. 
00475     //
00476     // Use a slave to find automatic variables in the function. Replace them
00477     // with arrays of the same type. Using another slave, add a decrement of
00478     // the stack pointer before any return statements.
00479     //
00480     // Using a sub-slave of the variable-finding slave, look for usages of 
00481     // the variable. Replace with an indexing operation into the array using
00482     // the stack index.    
00483     MakeTreePtr<Instance> fi;
00484     MakeTreePtr< Overlay<Initialiser> > oinit;
00485     MakeTreePtr<Callable> s_func;
00486     MakeTreePtr< MatchAll<Initialiser> > s_and;
00487     MakeTreePtr<Compound> s_top_comp, r_top_comp, r_ret_comp, temp;
00488     MakeTreePtr< Star<Declaration> > top_decls;
00489     MakeTreePtr< Star<Statement> > top_pre;
00490     MakeTreePtr< Stuff<Statement> > stuff;
00491     MakeTreePtr< Stuff<Compound> > cs_stuff;
00492     MakeTreePtr< Overlay<Statement> > overlay;
00493     MakeTreePtr<Automatic> cs_instance, s_instance;
00494     MakeTreePtr<Static> r_index, r_instance;
00495     MakeTreePtr<Unsigned> r_index_type;
00496     MakeTreePtr<PostIncrement> r_inc;
00497     MakeTreePtr<PostDecrement> r_ret_dec;
00498     MakeTreePtr<InstanceIdentifier> s_identifier;
00499     MakeTreePtr<Array> r_array;
00500     MakeTreePtr<Return> ret;
00501     MakeTreePtr<Subscript> l_r_sub;
00502     MakeTreePtr< MatchAll<Node> > s_and3;
00503     MakeTreePtr<BuildInstanceIdentifier> r_index_identifier("%s_stack_index");
00504     MakeTreePtr<BuildInstanceIdentifier> r_identifier("%s_stack");
00505     MakeTreePtr< GreenGrass<Statement> > s_gg;
00506 
00507     // Master search - look for functions satisfying the construct limitation and get
00508     fi->identifier = MakeTreePtr<InstanceIdentifier>();
00509     fi->type = s_func;
00510     fi->initialiser = oinit;   
00511     oinit->through = s_and;
00512     s_top_comp->members = ( top_decls );
00513     s_top_comp->statements = ( top_pre );
00514 
00515     // Construct limitation - restrict master search to functions that contain an automatic variable
00516     cs_stuff->terminus = cs_instance;
00517     s_and->patterns = ( s_top_comp, cs_stuff );
00518 
00519     // Master replace - insert index variable, inc and dec into function at top level
00520     MakeTreePtr< SlaveSearchReplace<Statement> > r_slave( stuff, s_identifier, l_r_sub );
00521     MakeTreePtr< SlaveCompareReplace<Statement> > r_mid( r_top_comp, stuff, r_slave );
00522     MakeTreePtr< SlaveSearchReplace<Statement> > r_slave3( r_mid, s_gg, r_ret_comp );
00523     temp->statements = (r_slave3);
00524     oinit->overlay = temp;//r_slave3; 
00525 
00526     // top-level decls
00527     r_top_comp->members = ( top_decls, r_index );
00528     r_index->type = r_index_type;
00529     r_index_type->width = MakeTreePtr<SpecificInteger>(32);
00530     r_index_identifier->sources = (fi->identifier);
00531     r_index->identifier = r_index_identifier;
00532     r_index->constancy = MakeTreePtr<NonConst>();
00533     r_index->initialiser = MakeTreePtr<SpecificInteger>(0);
00534 //    r_index->virt = MakeTreePtr<NonVirtual>();
00535 //    r_index->access = MakeTreePtr<Private>();
00536 
00537     // top-level statements
00538     r_inc->operands = ( r_index_identifier );
00539     r_top_comp->statements = ( r_inc, top_pre );
00540 
00541     // SlaveSearchReplace search to find automatic variables within the function
00542     stuff->terminus = overlay;
00543     overlay->through = s_instance;
00544     s_instance->identifier = s_identifier;
00545     s_instance->initialiser = MakeTreePtr<Uninitialised>(); // can't handle initialisers!
00546     s_instance->type = MakeTreePtr<Type>();
00547 
00548     // SlaveSearchReplace replace to insert as a static array (TODO be a member of enclosing class)
00549     r_instance->constancy = MakeTreePtr<NonConst>();
00550     r_instance->initialiser = MakeTreePtr<Uninitialised>();
00551     overlay->overlay = r_instance;
00552     r_identifier->sources = (s_identifier);
00553     r_instance->identifier = r_identifier;
00554     r_instance->type = r_array;
00555 //    r_instance->virt = MakeTreePtr<NonVirtual>();
00556 //    r_instance->access = MakeTreePtr<Private>();
00557     r_array->element = s_instance->type;
00558     r_array->size = MakeTreePtr<SpecificInteger>(10);
00559 
00560     // Sub-slave replace with a subscript into the array
00561     l_r_sub->operands = ( r_identifier, r_index_identifier );
00562 
00563     // SlaveSearchReplace to find early returns in the function
00564     s_gg->through = ret;
00565 
00566     // SlaveSearchReplace replace with a decrement of the stack index coming before the return
00567     //r_ret_comp->members = ( r_ret_decls );
00568     r_ret_dec->operands = ( r_index_identifier );
00569     r_ret_comp->statements = ( r_ret_dec, ret );
00570 
00571     Configure( fi );
00572 }
00573 
00574 */
00575 
00576 
00577 MergeFunctions::MergeFunctions()
00578 {
00579     MakeTreePtr<Scope> module;
00580     MakeTreePtr<Field> thread, s_func;
00581     MakeTreePtr<Thread> thread_type;
00582     MakeTreePtr<Callable> func_type;
00583     MakeTreePtr< Star<Declaration> > members, thread_decls;
00584     MakeTreePtr< Star<Statement> > thread_stmts;
00585     MakeTreePtr< Star<Base> > bases;    
00586     MakeTreePtr< Overlay<Compound> > thread_over;
00587     MakeTreePtr<Compound> s_thread_comp, r_thread_comp;
00588     MakeTreePtr<Call> s_call, ls_call;
00589     MakeTreePtr<InstanceIdentifier> func_id;
00590     MakeTreePtr<Label> r_label;
00591     MakeTreePtr< BuildLabelIdentifier > r_label_id("ENTER_%s");
00592     MakeTreePtr< MatchAll<Compound> > s_all;
00593     MakeTreePtr< Stuff<Compound> > s_stuff, func_stuff;
00594     MakeTreePtr<TypeIdentifier> module_id;
00595     MakeTreePtr<Goto> lr_goto, mr_goto;
00596     MakeTreePtr<Return> ms_return;    
00597     MakeTreePtr<TempReturnAddress> retaddr;
00598     MakeTreePtr<InstanceIdentifier> retaddr_id;
00599     MakeTreePtr< Erase<Declaration> > erase;
00600     
00601     mr_goto->destination = retaddr_id;
00602      
00603     MakeTreePtr< SlaveSearchReplace<Compound> > slavem( func_stuff, ms_return, mr_goto );        
00604     
00605     ls_call->callee = func_id;
00606     lr_goto->destination = r_label_id;
00607         
00608     MakeTreePtr< SlaveSearchReplace<Compound> > slavel( r_thread_comp, ls_call, lr_goto );    
00609     
00610     module->members = (members, thread, erase);
00611     erase->erase = (s_func);
00612     thread->type = thread_type;
00613     thread->initialiser = thread_over;
00614     thread_over->through = s_all;
00615     s_all->patterns = (s_thread_comp, s_stuff);
00616     s_stuff->terminus = s_call;
00617     s_thread_comp->members = (thread_decls);
00618     s_thread_comp->statements = (thread_stmts);
00619     s_call->callee = func_id;    
00620     s_func->type = func_type;
00621     s_func->initialiser = func_stuff;
00622     s_func->identifier = func_id;
00623     func_stuff->terminus = retaddr;
00624     retaddr->identifier = retaddr_id;
00625     thread_over->overlay = slavel;
00626     r_thread_comp->members = (thread_decls);
00627     r_thread_comp->statements = (thread_stmts, r_label, slavem);
00628     r_label->identifier = r_label_id;
00629     r_label_id->sources = (func_id);
00630          
00631     Configure( module );
00632 }
00633 
00634