Polaris: entry_util.cc Source File

entry_util.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 class Program;
00004 class String;
00005 ///
00006 #include "entry_util.h"
00007 #include "loopMark.h"
00008 #include "../ProgramUnit.h"
00009 #include "../Statement/GotoStmt.h"
00010 #include "../Statement/LabelStmt.h"
00011 #include "../Statement/ReturnStmt.h"
00012 #include "../Program.h"
00013 #include "../ProgramTag.h"
00014 
00015 /// Move all entry points to the top of the routine.
00016 /// Follow each one (except possibly the last) with a GO TO a
00017 /// label at its original location.
00018 /// This produces an empty section of code following each ENTRY
00019 /// that is only reachable via that ENTRY point.
00020 /// It also expands the scope of formal parameters
00021 /// to include all extant executable statements.
00022 /// ENTRY statements appear in their original relative order, thus
00023 /// the SUBROUTINE name does not change (Petersen, Jaxon, Grout)
00024 
00025 void 
00026 float_entry_points(ProgramUnit & pgm)
00027 {
00028     Statement      *p = pgm.stmts().first_ref();
00029 
00030     /// ...  Iterate over entries of program
00031 
00032     for (Iterator<Statement> entry_iter = pgm.stmts().iterate_entry_points();
00033                              entry_iter.valid();) {
00034         /// ...  Set c to point to current statement
00035         Statement      *c = &entry_iter.current();
00036 
00037         /// ...  Set the current position to the next entry statement (if any)
00038         ++entry_iter;
00039 
00040         if (c->stmt_class() != FLOW_ENTRY_STMT) {
00041             /// ...  Point to the statement after entry
00042             Statement      *t = c->next_ref();
00043 
00044             /// ...  If there is none, point at the entry statement itself
00045             if (!t) 
00046                 t = c;
00047 
00048             switch (t->stmt_class()) {
00049             case GOTO_STMT:
00050                 {
00051                     /// ...  If the subsequent statement is a GOTO_STMT, set t to
00052                     /// ...  its target
00053                     t = t->target_ref();
00054                 }
00055                 break;
00056 
00057             case LABEL_STMT:
00058                 break;
00059 
00060             default:
00061                 {
00062                     /// ...  Point at the previous statement
00063 
00064                     t = c->prev_ref();
00065 
00066                     if (!t)
00067                         t = c;
00068 
00069                     /// ...  If this wasn't the last entry, we will want to go
00070                     /// ...  to a label
00071 
00072                     if ((t == p) && (!entry_iter.valid())) {
00073                         t = c->next_ref();
00074                         if (!t)
00075                             t = c;
00076                     }
00077                     else if (t->stmt_class() != LABEL_STMT) {
00078                         /// ...  Create new label statement and insert it after
00079                         /// ...  entry
00080                         t = new LabelStmt(pgm.stmts().new_tag(), 
00081                                           pgm.stmts().new_label());
00082                         pgm.stmts().ins_after(t, c);
00083                     }
00084                 }
00085             }
00086 
00087             /// ...  If entry is not already just after p, move it there
00088             if (p->next_ref() != c)
00089                 pgm.stmts().move_after(*c, p);
00090 
00091             /// ...  Point p at the statement after c
00092             p = c->next_ref();
00093 
00094             if (!p)
00095                 p = c;
00096 
00097             /// ...  Insert a GOTO statement after c if ls is non-null
00098             if (((p != t) || (entry_iter.valid())) &&
00099                 ((p->stmt_class() != GOTO_STMT) || (p->target_ref() != t))) {
00100                 p = new GotoStmt(pgm.stmts().new_tag(), t);
00101                 pgm.stmts().ins_after(p, c);
00102             }
00103         }
00104     }
00105 }
00106 
00107 /// Move most RETURN statements to the bottom of the routine.  At the point
00108 /// of the RETURN statement, insert a goto statement.  Before the final
00109 /// RETURN in the routine, add a label as the target of the branches.
00110 /// Useless for alternate returns, or STOP points.
00111 
00112 void 
00113 sink_return_points(ProgramUnit & pgm)
00114 {
00115     /// ...  Find last statement in program
00116 
00117     Statement      *s = pgm.stmts().last_ref();
00118 
00119     /// ...  Skip the FlowExitStmt at the end of the program.
00120 
00121     if (! s)
00122     return;
00123 
00124     p_assert(s->stmt_class() == FLOW_EXIT_STMT,
00125          "Program unit has no FlowExitStmt.");
00126 
00127     s = s->prev_ref();
00128 
00129     /// ...  Exit if the program unit doesn't have any return statements.
00130 
00131     Iterator<Statement> return_iter = pgm.stmts().stmts_of_type(RETURN_STMT);
00132 
00133     if (! s || ! return_iter.valid())
00134     return;
00135 
00136     /// ...  If the program unit does not end with a RETURN statement, add one.
00137 
00138     if (s->stmt_class() != RETURN_STMT) {
00139         pgm.stmts().ins_after(new ReturnStmt(pgm.stmts().new_tag(), omega()),
00140                   s);
00141         s = s->next_ref();
00142     }
00143 
00144     /// ...  Initialize label statement pointer
00145 
00146     LabelStmt      *ls = 0;
00147 
00148     /// ...  Iterate over RETURN statements of program
00149 
00150     for ( ; return_iter.valid(); ++return_iter) {
00151         /// ...  Set c to point to current statement
00152         Statement      *c = &return_iter.current();
00153 
00154         /// ...  Perform no processing for the last RETURN
00155         if (c == s)
00156             continue;
00157 
00158         /// ...  Perform no processing for ineligible alternate RETURN
00159         /// ...  statements
00160 
00161         if (c->expr_valid())
00162             continue;
00163 
00164         /// ...  If first eligible RETURN, insert or find a label before 
00165         /// ...  last RETURN
00166 
00167         if (!ls) {
00168             /// ...  Find statement before last RETURN
00169             Statement      *p = s->prev_ref();
00170 
00171             /// ...  If this is a label, we are done
00172             if (p->stmt_class() == LABEL_STMT)
00173                 ls = (LabelStmt *) p;
00174             else {
00175                 /// ...  Create new label statement and insert it before RETURN
00176                 ls = new LabelStmt(pgm.stmts().new_tag(), 
00177                                    pgm.stmts().new_label());
00178                 pgm.stmts().ins_before(ls, s);
00179             }
00180         }
00181 
00182         /// ...  Insert a GOTO statement before c
00183         pgm.stmts().ins_before(new GotoStmt(pgm.stmts().new_tag(), ls), c);
00184 
00185         /// ...  Delete statement c
00186         pgm.stmts().del(*c);
00187     }
00188 }
00189 
00190 
00191 /// split_multiple_entries
00192 ///   If the given program unit ha multiple entries, than split it into
00193 ///   several program units, each with a single entry.  These new program
00194 ///   units are inserted into new_pgms.
00195 
00196 void
00197 split_multiple_entries(ProgramUnit &pgm, Program &new_pgms)
00198 {
00199     float_entry_points(pgm);
00200     String orig_entry_name = pgm.routine_name_ref();
00201     Iterator<Statement> entry_iter = pgm.stmts().stmts_of_type(ENTRY_STMT);
00202 
00203     if (entry_iter.valid())
00204     ++entry_iter;       /// ...  Skip the first entry.
00205 
00206     if (entry_iter.valid()) {
00207     for ( ; entry_iter.valid(); ++entry_iter) {
00208         const Statement &entry_stmt = entry_iter.current();
00209         ProgramUnit *pgm_clone = new ProgramUnit(pgm);
00210         
00211         /// ...  Delete all ENTRY statements except for the current entry.
00212 
00213         String entry_tag(entry_stmt.tag());
00214             Iterator<Statement> c_entry_iter = pgm_clone->stmts().stmts_of_type(ENTRY_STMT);
00215             
00216             for ( ; c_entry_iter.valid(); ++c_entry_iter) {
00217                 if (entry_tag != c_entry_iter.current().tag()) {
00218             pgm_clone->symtab().del(
00219             c_entry_iter.current().routine_guarded().symbol().name_ref());
00220                     pgm_clone->stmts().del(c_entry_iter.current());
00221         }
00222         }
00223 
00224         /// ...  Delete all statements up to the current entry.
00225         
00226         Iterator<Statement> header_iter = pgm_clone->stmts().iterator();
00227         
00228         for ( ; header_iter.valid(); ++header_iter) {
00229         Statement &header_stmt = header_iter.current();
00230 
00231         if (entry_tag == header_stmt.tag())
00232             break;
00233         else if (header_stmt.stmt_class() != FLOW_ENTRY_STMT)
00234             pgm_clone->stmts().del(header_stmt);
00235         }
00236         
00237         /// ...  Add the new program unit to the set of programs.
00238         
00239         ProgramTag clone_tag;
00240         pgm_clone->rename(clone_tag);
00241         String new_entry_name = entry_stmt.routine_guarded().symbol().name_ref();
00242         reset_loop_labels(*pgm_clone, orig_entry_name, new_entry_name);
00243         new_pgms.absorb(pgm_clone);
00244     }
00245 
00246     /// ...  Delete all entries except for the first from the original
00247     /// ...  program unit.
00248 
00249     entry_iter.reset();
00250     ++entry_iter;
00251 
00252     for ( ; entry_iter.valid(); ++entry_iter) {
00253         pgm.symtab().del(
00254         entry_iter.current().routine_guarded().symbol().name_ref());
00255         pgm.stmts().del(entry_iter.current());
00256     }
00257     }
00258 }    
00259 
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:46 2005