Inferno
0.2
|
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 }