Inferno  0.2
clean_up.cpp
Go to the documentation of this file.
00001 /*
00002  * clean_up.cpp
00003  *
00004  *  Created on: 26 Dec 2009
00005  *      Author: jgraley
00006  */
00007 
00008 #include "steps/clean_up.hpp"
00009 #include "tree/cpptree.hpp"
00010 #include "common/common.hpp"
00011 #include "sr/soft_patterns.hpp"
00012 #include "tree/typeof.hpp"
00013 #include "tree/misc.hpp"
00014 #include "inferno_patterns.hpp"
00015 
00016 using namespace CPPTree;
00017 using namespace Steps;
00018 
00019 // Removing superfluous CompundExpression blocks to clean up the code
00020 CleanupCompoundExpression::CleanupCompoundExpression() // LIMITAION: decls in body not allowed
00021 {
00022      // Lowering compound expressions
00023      //
00024      // exp( ({a; b; c; )) ) -> a; b; t=c; exp(t)
00025      //
00026      // Temp is used to preserve sequence point after c. This step assumes that
00027      // all sequence points that need preserving co-incide with the semicolons
00028      // in a Compound or CompundExpression. It also requires that there be no loops.
00029     MakeTreePtr< MatchAll<Statement> > s_all;
00030     MakeTreePtr< PointerIs<Statement> > sx_pointeris;
00031     MakeTreePtr< NotMatch<Statement> > sx_not;
00032     MakeTreePtr<Expression> sx_expr;
00033     
00034     MakeTreePtr< Stuff<Statement> > stuff;
00035     MakeTreePtr< NotMatch<Statement> > sr_not;
00036     MakeTreePtr<SequentialScope> sr_comp;
00037     MakeTreePtr< Star<Declaration> > sr_cdecls;
00038     MakeTreePtr< Star<Statement> > sr_cstmts;
00039     
00040     MakeTreePtr<CompoundExpression> s_ce;
00041     MakeTreePtr<Compound> r_comp;
00042     MakeTreePtr< Star<Statement> > s_pre, s_post, body;
00043     MakeTreePtr< Star<Declaration> > decls;
00044     MakeTreePtr<Temporary> r_temp;
00045     MakeTreePtr< TransformOf<Expression> > last( &TypeOf::instance );
00046     MakeTreePtr<BuildInstanceIdentifier> r_temp_id("result");
00047     MakeTreePtr<Assign> r_assign;
00048     MakeTreePtr< Overlay<Expression> > overlay;
00049     MakeTreePtr<Type> r_type;
00050 
00051     s_all->patterns = (stuff, sx_pointeris);
00052     sx_pointeris->pointer = sx_not;
00053     sx_not->pattern = sx_expr;
00054     stuff->recurse_restriction = sr_not;
00055     sr_not->pattern = sr_comp;
00056     sr_comp->members = sr_cdecls;
00057     sr_comp->statements = sr_cstmts;
00058     
00059     stuff->terminus = overlay;
00060     overlay->through = s_ce;
00061     s_ce->statements = ( body, last );
00062     s_ce->members = ( decls );
00063     
00064     r_comp->statements = ( body, r_assign, stuff );
00065     r_comp->members = ( decls, r_temp );
00066     r_temp->identifier = r_temp_id;
00067     r_temp->initialiser = MakeTreePtr<Uninitialised>();
00068     r_temp->type = r_type;
00069     r_assign->operands = (r_temp_id, last);
00070     last->pattern = r_type;
00071     overlay->overlay = r_temp_id;        
00072     
00073     Configure( s_all, r_comp );
00074 }
00075 
00076 
00077 // Removing superfluous Compund blocks to clean up the code
00078 CleanupCompoundMulti::CleanupCompoundMulti() // LIMITAION: decls in body not allowed
00079 {
00080      // {x;{a;b;c}y} -> {x;a;b;c;y}
00081      // Find a compound block as a statement in another compound block. 
00082      // Merge the decls and insert the statements in the correct sequence..
00083     MakeTreePtr<Compound> s_inner, s_outer, r_comp;
00084     MakeTreePtr< Star<Statement> > s_pre, s_post, s_body;
00085     MakeTreePtr< Star<Declaration> > s_inner_decls, s_outer_decls;
00086 
00087     s_inner->statements = ( s_body );
00088     s_inner->members = ( s_inner_decls );
00089     s_outer->statements = ( s_pre, s_inner, s_post );
00090     s_outer->members = ( s_outer_decls );
00091     r_comp->statements = ( s_pre, s_body, s_post );
00092     r_comp->members = ( s_inner_decls, s_outer_decls );
00093 
00094     Configure( s_outer, r_comp );
00095 }
00096 
00097 
00098 CleanupCompoundSingle::CleanupCompoundSingle() 
00099 {
00100     // Find a compound block with no decls and one statemewnt. Replace
00101     // with just the statement
00102     //
00103     //{a} -> a TODO need to restrict parent node to Statement: For, If etc OK; Instance is NOT OK
00104     //         TODO OR maybe just fix renderer for that case
00105     // Note: this hits eg If(x){a;} which the "Multi" version misses 
00106     MakeTreePtr< MatchAll<Statement> > all;    
00107     MakeTreePtr< NotMatch<Statement> > sx_not;
00108     MakeTreePtr<Instance> sx_instance;
00109     MakeTreePtr< AnyNode<Statement> > node;
00110     MakeTreePtr< Overlay<Statement> > over;   
00111     MakeTreePtr<Compound> s_comp;
00112     MakeTreePtr< Statement > body;
00113 
00114     all->patterns = (node, sx_not);
00115     node->terminus = over;
00116     sx_not->pattern = sx_instance;
00117     sx_instance->initialiser = s_comp;
00118     over->through = s_comp;
00119     over->overlay = body;
00120 
00121     s_comp->statements = body;
00122     // Note: leaving s_comp empty meaning no decls allowed
00123 
00124     Configure( all );
00125 }
00126 
00127 CleanupNop::CleanupNop() 
00128 {
00129     // Find compound block with Nop in it, replace has the Nop removed.
00130     // Note: Nop is a no-effect statement, sort-of like ; on its own.
00131     MakeTreePtr<Compound> s_comp, r_comp;
00132     MakeTreePtr<Nop> s_nop;
00133     MakeTreePtr< Star<Declaration> > decls;
00134     MakeTreePtr< Star<Statement> > pre, post;
00135 
00136     s_comp->members = decls;
00137     s_comp->statements = (pre, s_nop, post);
00138     
00139     r_comp->members = decls;
00140     r_comp->statements = (pre, post);
00141 
00142     Configure( s_comp, r_comp );
00143 }
00144 
00145 CleanupDuplicateLabels::CleanupDuplicateLabels()
00146 {
00147     // Search for a function that contains a compound block that has 
00148     // two labels in succession. Replace the pair of labels with a single
00149     // one.
00150     //
00151     // Using a slave, find references to either one of the original labels 
00152     // and replace by a reference to the new label.
00153     //
00154     // Notes:
00155     // - The slave must operate over the entire function, not just the 
00156     // compound that containes the labels, because labels have function 
00157     // scope and the gotos can be anywhere.
00158     // - Do not assume the usages of the labels will be gotos. We support
00159     // GCCs goto-a-variable extension in which case a label could be 
00160     // on the right of an assignment.
00161     
00162     MakeTreePtr<Instance> s_instance, r_instance;
00163     MakeTreePtr< Stuff<Compound> > stuff;
00164     MakeTreePtr< Overlay<Statement> > overlay;
00165     MakeTreePtr<Compound> s_comp, r_comp;
00166     MakeTreePtr<Label> s_label1, s_label2, r_label1; // keep l1 and elide l2
00167     MakeTreePtr< Star<Declaration> > decls;
00168     MakeTreePtr< Star<Statement> > pre, post;
00169     MakeTreePtr<LabelIdentifier> s_labelid1, s_labelid2;
00170     MakeTreePtr<BuildLabelIdentifier> r_labelid("%s_%s", BYPASS_WHEN_IDENTICAL);
00171     MakeTreePtr< MatchAny<LabelIdentifier> > l_s_orrule;
00172     MakeTreePtr<InstanceIdentifier> identifier;
00173     MakeTreePtr<Callable> type;
00174     
00175     l_s_orrule->patterns = (s_labelid1, s_labelid2);
00176     
00177     MakeTreePtr< SlaveSearchReplace<Compound> > r_slave( stuff, l_s_orrule, r_labelid );
00178     
00179     s_instance->initialiser = stuff;
00180     s_instance->identifier = identifier;
00181     s_instance->type = type;
00182     s_comp->members = decls;
00183     s_comp->statements = (pre, s_label1, s_label2, post);
00184     s_label1->identifier = s_labelid1;
00185     s_label2->identifier = s_labelid2;
00186     
00187     r_instance->initialiser = r_slave;
00188     r_instance->identifier = identifier;
00189     r_instance->type = type;
00190     stuff->terminus = overlay;           
00191     overlay->through = s_comp;
00192     overlay->overlay = r_comp;
00193     r_comp->members = decls;
00194     r_comp->statements = (pre, r_label1, post);
00195     r_label1->identifier = r_labelid;
00196     r_labelid->sources = (s_labelid1, s_labelid2);
00197     
00198     Configure( s_instance, r_instance );
00199 }
00200 
00201 CleanupIneffectualLabels::CleanupIneffectualLabels()
00202 {
00203     // Search for a function that contains a compound block that has 
00204     // a label followed by a goto. Remove the label, leaving the goto.
00205     //
00206     // Using a slave, find references to either one of the original labels 
00207     // and replace by a reference to a new merged one.
00208     //
00209     // Notes:
00210     // - The slave must operate over the entire function, not just the 
00211     // compound that containes the labels, because labels have function 
00212     // scope and the gotos can be anywhere.
00213     // - Do not assume the usages of the labels will be gotos. We support
00214     // GCCs goto-a-variable extension in which case a label could be 
00215     // on the right of an assignment.
00216     
00217     MakeTreePtr<Instance> s_instance, r_instance;
00218     MakeTreePtr< Stuff<Compound> > stuff;
00219     MakeTreePtr< Overlay<Statement> > overlay;
00220     MakeTreePtr<Compound> s_comp, r_comp;
00221     MakeTreePtr<Label> s_label; // keep l1 and elide l2
00222     MakeTreePtr< Star<Declaration> > decls;
00223     MakeTreePtr< Star<Statement> > pre, post;
00224     MakeTreePtr<LabelIdentifier> s_labelid1, s_labelid2;
00225     MakeTreePtr<BuildLabelIdentifier> r_labelid("%s_%s", BYPASS_WHEN_IDENTICAL);
00226     MakeTreePtr< MatchAny<LabelIdentifier> > l_s_orrule;
00227     MakeTreePtr<InstanceIdentifier> identifier;
00228     MakeTreePtr<Callable> type;
00229     MakeTreePtr<Goto> s_goto, r_goto;
00230     
00231     l_s_orrule->patterns = (s_labelid1, s_labelid2);
00232     
00233     MakeTreePtr< SlaveSearchReplace<Compound> > r_slave( stuff, l_s_orrule, r_labelid );
00234     
00235     s_instance->initialiser = stuff;
00236     s_instance->identifier = identifier;
00237     s_instance->type = type;
00238     s_comp->members = decls;
00239     s_comp->statements = (pre, s_label, s_goto, post);
00240     s_label->identifier = s_labelid1;
00241     s_goto->destination = s_labelid2;
00242     
00243     r_instance->initialiser = r_slave;
00244     r_instance->identifier = identifier;
00245     r_instance->type = type;
00246     stuff->terminus = overlay;           
00247     overlay->through = s_comp;
00248     overlay->overlay = r_comp;
00249     r_comp->members = decls;
00250     r_comp->statements = (pre, r_goto, post);
00251     r_goto->destination = r_labelid;
00252     r_labelid->sources = (s_labelid1, s_labelid2);
00253     
00254     Configure( s_instance, r_instance );
00255 }
00256 
00257 CleanupIneffectualGoto::CleanupIneffectualGoto()
00258 {
00259     // Find a compound containing a Goto and a Label where the 
00260     // goto goes to the label. Remove the Goto (but not the Label
00261     // since there may be other Gotos to it).
00262     MakeTreePtr<Compound> s_comp, r_comp;
00263     MakeTreePtr<Goto> s_goto;
00264     MakeTreePtr<Label> s_label, r_label;
00265     MakeTreePtr<LabelIdentifier> labelid;
00266     MakeTreePtr< Star<Declaration> > decls;
00267     MakeTreePtr< Star<Statement> > pre, post;
00268 
00269     s_comp->members = decls;
00270     s_comp->statements = (pre, s_goto, s_label, post);
00271     s_goto->destination = labelid;
00272     s_label->identifier = labelid;
00273     
00274     r_comp->members = decls;
00275     r_comp->statements = (pre, r_label, post);
00276     r_label->identifier = labelid;
00277 
00278     Configure( s_comp, r_comp );
00279 }
00280 
00281 CleanupUnusedLabels::CleanupUnusedLabels()
00282 {
00283     // Find a function that contains a compound that contains
00284     // a label. Use an and-not rule to exclude any usages of the 
00285     // label. Replace the compound with one that does not have the
00286     // label. 
00287     //
00288     // Usages are detected by searching for the label's identifier
00289     // using a recurse restriction that prevents recusing through
00290     // the Label node, thus excluding the declaration which we want
00291     // to ignore.
00292     MakeTreePtr<Instance> s_instance, r_instance;
00293     MakeTreePtr< Stuff<Compound> > stuff;
00294     MakeTreePtr< Stuff<Compound> > sx_stuff;
00295     MakeTreePtr< Overlay<Statement> > overlay;
00296     MakeTreePtr<Compound> s_comp, r_comp;
00297     MakeTreePtr<Label> s_label; // keep l1 and elide l2
00298     MakeTreePtr< Star<Declaration> > decls;
00299     MakeTreePtr< Star<Statement> > pre, post;
00300     MakeTreePtr<LabelIdentifier> labelid;
00301     MakeTreePtr<Goto> sx_goto;
00302     MakeTreePtr< MatchAll<Compound> > s_andrule;
00303     MakeTreePtr< NotMatch<Compound> > sx_notrule;
00304     MakeTreePtr< NotMatch<Node> > sxx_notrule;        
00305     MakeTreePtr< Label > sxx_label;        
00306     MakeTreePtr<InstanceIdentifier> identifier;
00307     MakeTreePtr<Callable> type;
00308 
00309     s_instance->initialiser = s_andrule;
00310     s_instance->identifier = identifier;
00311     s_instance->type = type;
00312     s_andrule->patterns = (stuff, sx_notrule);
00313     s_comp->members = decls;
00314     s_comp->statements = (pre, s_label, post);
00315     s_label->identifier = labelid;
00316                     
00317     sx_notrule->pattern = sx_stuff;
00318     sx_stuff->recurse_restriction = sxx_notrule;
00319     sxx_notrule->pattern = sxx_label;
00320     sx_stuff->terminus = labelid;
00321     
00322     r_instance->initialiser = stuff;
00323     r_instance->identifier = identifier;
00324     r_instance->type = type;
00325     stuff->terminus = overlay;
00326     overlay->through = s_comp;
00327     overlay->overlay = r_comp;
00328     r_comp->members = decls;
00329     r_comp->statements = (pre, post);
00330     
00331     Configure( s_instance, r_instance );
00332 }
00333 
00334 
00335 CleanUpDeadCode::CleanUpDeadCode()
00336 {
00337     MakeTreePtr<Compound> s_comp, r_comp;
00338     MakeTreePtr< Star<Declaration> > decls;
00339     MakeTreePtr< Star<Statement> > pre, post;
00340     MakeTreePtr< NotMatch<Statement> > s_dead_not;
00341     MakeTreePtr< MatchAny<Statement> > s_dead_any, s_exit_any;
00342     MakeTreePtr<Case> casee;
00343     MakeTreePtr<Break> breakk;
00344      
00345     s_comp->members = decls;
00346     s_comp->statements = ( pre, s_exit_any, s_dead_not, post );
00347     s_exit_any->patterns = (MakeTreePtr<Break>(), MakeTreePtr<Continue>(), MakeTreePtr<Return>(), MakeTreePtr<Goto>());
00348     s_dead_not->pattern = s_dead_any;
00349     s_dead_any->patterns = (MakeTreePtr<Case>(), MakeTreePtr<Default>(), MakeTreePtr<Label>());
00350     r_comp->members = decls;
00351     r_comp->statements = ( pre, s_exit_any, post );
00352     
00353     Configure( s_comp, r_comp );            
00354 }
00355 
00356 
00357 ReduceVoidCompoundExpression::ReduceVoidCompoundExpression()
00358 {
00359     MakeTreePtr<CompoundExpression> s_ce;
00360     MakeTreePtr< Star<Declaration> > decls;
00361     MakeTreePtr< Star<Statement> > stmts;
00362     MakeTreePtr< NotMatch<Statement> > last;
00363     MakeTreePtr< TransformOf<Expression> > sx_expr( &TypeOf::instance );
00364     MakeTreePtr< NotMatch<Type> > sx_type_not;
00365     MakeTreePtr<Void> sx_void;
00366     MakeTreePtr<Compound> r_comp;
00367     
00368     s_ce->members = (decls);
00369     s_ce->statements = (stmts, last);
00370     last->pattern = sx_expr;
00371     sx_expr->pattern = sx_type_not;
00372     sx_type_not->pattern = sx_void;
00373     r_comp->members = (decls);
00374     r_comp->statements = (stmts, last);
00375     
00376     Configure( s_ce, r_comp );      
00377 }
00378 
00379 
00380 CleanupUnusedVariables::CleanupUnusedVariables()
00381 {
00382     MakeTreePtr< MatchAll<Scope> > s_all;
00383     MakeTreePtr<Scope> scope;
00384     MakeTreePtr< Star<Declaration> > decls;    
00385     MakeTreePtr<Instance> inst;
00386     MakeTreePtr<NestedArray> nested_array;
00387     MakeTreePtr< NotMatch<Type> > sx_not;
00388     MakeTreePtr< MatchAny<Type> > sx_any;
00389     MakeTreePtr< TransformOf<TypeIdentifier> > getdecl( &GetDeclaration::instance ); // TODO should be modulo typedefs
00390     MakeTreePtr<InstanceIdentifier> id;
00391     MakeTreePtr< Stuff<Scope> > stuff1, s_stuff2;
00392     MakeTreePtr< MatchAll<Node> > s_antip;
00393     MakeTreePtr< AnyNode<Node> > s_anynode;
00394     MakeTreePtr< NotMatch<Node> > s_nm;
00395     MakeTreePtr< Erase<Instance> > erase;
00396     MakeTreePtr<InheritanceRecord> sx_ir;     
00397     MakeTreePtr< NotMatch<Scope> > s_nscope;
00398     
00399     s_all->patterns = (stuff1, s_nscope);
00400     stuff1->terminus = scope;
00401     scope->members = (erase, decls);
00402     erase->erase = inst;
00403     inst->type = nested_array;
00404     inst->identifier = id;
00405     nested_array->terminus = sx_not;
00406     sx_not->pattern = sx_any;
00407     sx_any->patterns = ( MakeTreePtr<Callable>(),
00408                          getdecl );
00409     getdecl->pattern = sx_ir;
00410     sx_ir->members = MakeTreePtr< Star<Declaration> >();
00411     sx_ir->bases = MakeTreePtr< Star<Base> >();
00412     s_nscope->pattern = s_stuff2;
00413     s_stuff2->terminus = s_antip;
00414     s_antip->patterns = (s_anynode, s_nm);
00415     s_anynode->terminus = id;
00416     s_nm->pattern = inst;
00417                         
00418     Configure( s_all, stuff1 );
00419 }
00420 
00421 
00422 CleanupNestedIf::CleanupNestedIf()
00423 {
00424     MakeTreePtr<If> s_outer_if, s_inner_if, r_if;
00425     MakeTreePtr<Statement> body;
00426     MakeTreePtr<Nop> s_inner_nop, s_outer_nop, r_nop;
00427     MakeTreePtr<Expression> inner_cond, outer_cond;
00428     MakeTreePtr<LogicalAnd> r_and;
00429     
00430     s_outer_if->condition = outer_cond;
00431     s_outer_if->body = s_inner_if;
00432     s_outer_if->else_body = s_outer_nop;
00433     s_inner_if->condition = inner_cond;
00434     s_inner_if->body = body;
00435     s_inner_if->else_body = s_inner_nop;
00436     
00437     r_if->condition = r_and;
00438     r_if->body = body; 
00439     r_if->else_body = r_nop;
00440     r_and->operands = (outer_cond, inner_cond); // outer first, to be side-effect correct
00441     
00442     Configure( s_outer_if, r_if );
00443 }