Polaris: program_util.cc Source File

program_util.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 #include <stdio.h> 
00004 #include <strstream.h>
00005 
00006 #include "../CommonBlock.h"
00007 #include "../Equivalence.h"
00008 #include "../Program.h"
00009 #include "../ProgramTag.h"
00010 #include "../ProgramUnit.h"
00011 #include "../Collection/RefSet.h"
00012 #include "../Collection/RefList.h"
00013 #include "../Expression/Expression.h"
00014 #include "../Statement/EntryStmt.h"
00015 #include "../Symbol/BlockDataSymbol.h"
00016 #include "../Symbol/Symbol.h"
00017 #include "../Symbol/VariableSymbol.h"
00018 #include "symbol_util.h"
00019 #include "program_util.h"
00020 
00021 /// Mark variables found in DATA statement expressions
00022 /// (expr must always be a CommaExpr)
00023 
00024 void
00025 mark_data_variables(Expression & expr,
00026             RefSet<Symbol> & var_set,
00027             RefSet<Symbol> & overflow_set,
00028             RefSet<Symbol> & match_set,
00029             Boolean & found_vars)
00030 {
00031   for (Iterator<Expression> expr_iter = expr.arg_list();
00032        expr_iter.valid(); ++expr_iter) {
00033     
00034     /// ...  See documentation in Data.h for information
00035     /// ...  about valid expression types 
00036 
00037     Expression & current_expr = expr_iter.current();
00038 
00039     switch (current_expr.op()) {
00040     case ID_OP: {
00041       Symbol & current_symbol = current_expr.symbol();
00042       var_set.ins(current_symbol);
00043       if (match_set.member(current_symbol))
00044     found_vars = True;
00045       break;
00046     }
00047     case ARRAY_REF_OP: {
00048       Symbol & current_symbol = *current_expr.base_variable_ref();
00049       var_set.ins(current_symbol);
00050       if (match_set.member(current_symbol))
00051     found_vars = True;
00052       break;
00053     }
00054     case DO_OP:
00055       overflow_set.ins(current_expr.iterator().index_id().symbol());
00056       mark_data_variables(current_expr.iolist(), var_set,
00057               overflow_set, match_set, found_vars);
00058     default: break;
00059     }
00060   }
00061 }
00062 
00063 /// Move saved variables from a ProgramUnit into a common block
00064 
00065 void
00066 move_saved_vars(ProgramUnit & pgm,
00067         Program & p)
00068 {
00069     
00070     /// ...  Static counter of generated common blocks (and possibly block
00071     /// ...  data program units)
00072     
00073     static int saved_tag = 0;
00074     
00075     /// ...  Build a set of saved variables for later processing
00076     
00077     RefSet<Symbol> saved_vars;
00078     RefSet<Symbol> saved_init_vars;
00079 
00080     RefList<Equivalence> equivs_encountered;
00081     
00082     for (DictionaryIter<Symbol> symbol_iter = pgm.symtab().iterator();
00083      symbol_iter.valid(); ++symbol_iter) {
00084     Symbol & sym = symbol_iter.current();
00085     if ((sym.sym_class() == VARIABLE_CLASS) &&
00086         (sym.saved())) {
00087         Equivalence *equiv_class = sym.equivalence_ref();
00088         if (equiv_class) {
00089         if (!equivs_encountered.member(*equiv_class)) {
00090 
00091             /// ...  Make a new LOGICAL array of the proper size
00092             
00093             ArrayDims *dims = new ArrayDims;
00094 
00095             int size = equiv_class->size();
00096 
00097             ArrayBounds *bound = 
00098             new ArrayBounds(constant(1), 
00099                     constant(size % 4 == 0 ? size/4 : (size/4)+1));
00100             dims->ins_last(bound);
00101             VariableSymbol *new_sym =
00102             new VariableSymbol("EQUIV",
00103                        LOGICAL_TYPE,
00104                        NOT_FORMAL,
00105                        IS_SAVED,
00106                        NOT_GLOBAL,
00107                        dims);
00108 
00109             /// ...  Rename to uniqueness within the symbol table
00110             pgm.symtab().rename_and_ins(new_sym);
00111 
00112             /// ...  Insert the new variable into the 
00113             /// ...  equivalence class at byte offset 0
00114             /// ...  (automatically updates the symbol's 
00115             /// ...  _equivalence pointer).
00116 
00117             equiv_class->ins(*new_sym,0);
00118 
00119             /// ...  Put the new variable on the saved_vars list
00120 
00121             saved_vars.ins(*new_sym);
00122             if (sym.initial_value())
00123             saved_init_vars.ins(sym);
00124 
00125             /// ...  Finally, note that we did this by putting the equiv
00126             /// ...  class on the list of equivalences encountered
00127 
00128             equivs_encountered.ins_last(*equiv_class);
00129         }
00130         else {
00131             if (sym.initial_value())
00132             saved_init_vars.ins(sym);
00133         }
00134         } else {
00135         saved_vars.ins(sym);
00136         if (sym.initial_value())
00137             saved_init_vars.ins(sym);
00138         }
00139     }
00140     }
00141     
00142     if (saved_vars.any_valid()) {
00143     
00144     /// ...  Create a new, saved common block
00145     
00146     ostrstream * str_ref = new ostrstream;
00147     (*str_ref) << ++saved_tag << '\000';
00148     char * tag_data = str_ref->str();
00149     String string_tag(tag_data);
00150     delete [] tag_data;
00151     delete str_ref;
00152     CommonBlock * saved_cb;
00153     {
00154         String common_tag = "/CB" + string_tag + "/";
00155         saved_cb = new CommonBlock(common_tag);
00156     }
00157     saved_cb->saved(1);
00158     
00159     /// ...  Insert new common block into program
00160     
00161     pgm.common_blocks().ins(saved_cb);
00162     
00163     /// ...  Check to see if there are any initially defined saved
00164     /// ...  local variables
00165     
00166     ProgramUnit * saved_pu = 0;
00167     
00168     if (saved_init_vars.any_valid()) {
00169         
00170         /// ...  Create block data ProgramUnit
00171         
00172         ProgramTag block_tag;
00173         saved_pu = new ProgramUnit(block_tag, BLOCK_DATA_PU_TYPE);
00174         BlockDataSymbol * entry_symbol_ptr;
00175         {
00176         String entry_tag = "BD" + string_tag; 
00177         entry_symbol_ptr = new BlockDataSymbol(entry_tag);
00178         }
00179         Symbol & entry_symbol = 
00180         saved_pu->symtab().ins(entry_symbol_ptr);
00181         EntryStmt * entry_stmt = 
00182         new EntryStmt(saved_pu->stmts().new_tag(),
00183                   id(entry_symbol), comma());
00184         saved_pu->stmts().ins_after(entry_stmt,
00185                     saved_pu->stmts().first_ref());
00186         
00187         /// ...  Check through DATA statements
00188         
00189         Type int_type = make_type(INTEGER_TYPE);
00190         RefSet<Symbol> match_set(saved_init_vars);
00191         
00192         for (Mutator<Data> data_mutr = pgm.data();
00193          data_mutr.valid(); ++data_mutr) {
00194         
00195         RefSet<Symbol> local_set;
00196         RefSet<Symbol> local_overflow_set;
00197         Boolean found_vars = False;
00198         
00199         mark_data_variables(data_mutr.current().variable_list(),
00200                     local_set, local_overflow_set,
00201                     match_set, found_vars);
00202         
00203         if (found_vars) {
00204             
00205             /// ...  A variable which was initially defined was found
00206             /// ...  on this DATA statement
00207             
00208             /// ...  remove variables from match_set (if present)
00209 
00210             for (Mutator<Symbol> set_mutr = local_set;
00211              set_mutr.valid(); ++set_mutr) {
00212             Symbol & current_symbol = set_mutr.current();
00213             set_mutr.del();
00214             /* If an unsaved variable was initialized on the
00215                DATA statement, add it to saved_vars and
00216                saved_init_vars so we can copy the whole DATA
00217                statement over to BLOCK DATA */
00218             if (!current_symbol.saved()) {
00219               saved_vars.ins(current_symbol);
00220               saved_init_vars.ins(current_symbol);
00221             }
00222             match_set.del(current_symbol);
00223             }
00224             
00225             /// ...  For now, define integer variables with the same names
00226             /// ...  as those variable symbols found in overflow set (which
00227             /// ...  correspond to implied DO indexes under the DATA
00228             /// ...  statement) into the block data ProgramUnit (eventually,
00229             /// ...  these variables should go away)
00230             
00231             for (Mutator<Symbol> overflow_mutr = local_overflow_set;
00232              overflow_mutr.valid(); ++overflow_mutr) {
00233             Symbol & current_symbol = overflow_mutr.current();
00234             overflow_mutr.del();
00235             const char * current_name = current_symbol.name_ref();
00236             if (!saved_pu->symtab().find_ref(current_name)) {
00237                 VariableSymbol *var_sym =
00238                 new VariableSymbol(current_name, int_type,
00239                            NOT_FORMAL, NOT_SAVED);
00240                 saved_pu->symtab().ins(var_sym);
00241             }
00242             }
00243             
00244             /// ...  Grab data statement and put into block data ProgramUnit
00245             
00246             saved_pu->data().ins_last(data_mutr.grab());
00247             
00248             /// ...  End containing loop if no more variables to search for
00249             if (!match_set.any_valid())
00250             break;
00251         }
00252         }
00253     }
00254     
00255     /// ...  Loop through, processing saved variables
00256     
00257     for (Iterator<Symbol> saved_iter = saved_vars;
00258          saved_iter.valid(); ++saved_iter) {
00259         
00260         VariableSymbol & current_symbol = 
00261         (VariableSymbol &)saved_iter.current();
00262         
00263         /// ...  Clear saved and initial value indicators
00264         
00265         current_symbol.saved(NOT_SAVED);
00266         current_symbol.initial_value(NOT_INITIALIZED);
00267         
00268         /* Put eight-byte divisible variables first, then
00269            four-byte divisible, then two-byte divisible, then
00270            all others: within groups, sort in alphabetical
00271            order */
00272         
00273         int current_size = current_symbol.type().size();
00274         
00275         int maxdiv;
00276         
00277         if ((current_size % 8) == 0)
00278         maxdiv = 8;
00279         else if ((current_size % 4) == 0)
00280         maxdiv = 4;
00281         else if ((current_size % 2) == 0)
00282         maxdiv = 2;
00283         else
00284         maxdiv = 1;
00285         
00286         int cb_index = 0;
00287         
00288         if (maxdiv != 1) {
00289         for (Iterator<Symbol> pos_iter = saved_cb->iterator();
00290              pos_iter.valid(); ++pos_iter) {
00291             VariableSymbol & pos_symbol =
00292             (VariableSymbol &) pos_iter.current();
00293             int pos_size = pos_symbol.type().size();
00294             
00295             if ((((maxdiv == 2) && ((pos_size % 2) == 0)) ||
00296              ((maxdiv == 4) && ((pos_size % 4) == 0)) ||
00297              ((pos_size % 8) == 0)) &&
00298             (strcmp(current_symbol.name_ref(),
00299                 pos_symbol.name_ref()) > 0))
00300             ++cb_index;
00301             else
00302             break;
00303         }
00304         }
00305         else
00306         cb_index = saved_cb->entries();       
00307         
00308         /// ...  Insert variable into common block at this offset
00309         
00310         current_symbol.common(*saved_cb, cb_index);
00311         
00312         /* If there is a block data ProgramUnit, clone the variable
00313            (using member function clone_all to copy all pointers)
00314            and insert it into the block data ProgramUnit */
00315 
00316         if (saved_pu) {
00317         saved_pu->symtab().ins(current_symbol.clone_all());
00318         
00319         /// ...  If the symbol is an array, find all symbolic constants
00320         /// ...  used to declare it and insert them into the new symbol
00321         /// ...  table as well.
00322 
00323         if (current_symbol.is_array()) {
00324             
00325             RefSet<Symbol> symb_const;
00326             collect_symb_const(symb_const, current_symbol.dim());
00327             for (Iterator<Symbol> siter = symb_const;
00328              siter.valid();
00329              ++siter) {
00330             Symbol & constant = siter.current();
00331             if (!saved_pu->symtab().find_ref(constant.name_ref()))
00332                 saved_pu->symtab().ins(constant.clone_all());
00333             }
00334         }
00335         }
00336         
00337     }
00338     if (saved_pu) {
00339         
00340         for (Iterator<Equivalence> eqiter = equivs_encountered;
00341          eqiter.valid();
00342          ++eqiter) {
00343         Equivalence & eq = eqiter.current();
00344         saved_pu->equivalences().ins((Equivalence *)(eq.definition_clone()));
00345            
00346         for (Iterator<EquivalenceMember> eqmiter = eq.iterator();
00347              eqmiter.valid();
00348              ++eqmiter) {
00349             Symbol & eqsym = eqmiter.current().symbol();
00350             if (!saved_pu->symtab().find_ref(eqsym.name_ref()))
00351             saved_pu->symtab().ins(eqsym.clone_all());
00352         }
00353         }
00354 
00355         /// ...  Clone the common block and insert it into the block data
00356         /// ...  ProgramUnit
00357         
00358         CommonBlock * saved_cb_clone =
00359         new CommonBlock(*saved_cb);
00360         
00361         saved_pu->common_blocks().ins(saved_cb_clone);
00362         
00363         /// ...  Relink its symbol pointers
00364         
00365         saved_cb_clone->relink_dptrs(*saved_pu);
00366         
00367         /// ...  Relink all variable pointers
00368         
00369         saved_pu->symtab().relink_ptrs(*saved_pu);
00370         
00371         /// ...  Relink all data statement pointers
00372         
00373         saved_pu->data().relink_ptrs(*saved_pu);
00374         
00375         /// ...  Relink all equivalence pointers
00376 
00377         saved_pu->equivalences().relink_ptrs(*saved_pu);
00378 
00379         /// ...  Absorb block data ProgramUnit into containing program 
00380         
00381         p.absorb(saved_pu);
00382     }
00383     }
00384 }
00385     
00386 /// Rename variable new_symbol_ptr (to be inserted into new_pgm) and
00387 /// corresponding symbol current_symbol (which is in current_pgm) so that
00388 /// the two symbols have the same name in each ProgramUnit.
00389 
00390 /// This routine is used as part of partial ProgramUnit cloning in the
00391 /// presence of name conflicts (e.g., when inlining common blocks).
00392 
00393 Symbol &
00394 rename_variable_to_match(ProgramUnit & current_pgm,
00395              Symbol & current_symbol,
00396              ProgramUnit & new_pgm,
00397              Symbol * new_symbol_ptr)
00398 {
00399 /// Potentially rename into new program
00400   new_pgm.symtab().rename_and_ins(new_symbol_ptr);
00401 /// Look up symbol with new name in current program 
00402   Symbol         *check_ptr = 
00403     current_pgm.symtab().find_ref(new_symbol_ptr->name_ref());
00404 /// Handle when symbols do not match
00405   if (check_ptr != &current_symbol) {
00406     /// ...  Grab current symbol from symbol table
00407     current_pgm.symtab().grab(current_symbol.name_ref());
00408     /// ...  Grab second colliding symbol if need be
00409     if (check_ptr) 
00410       check_ptr = current_pgm.symtab().grab(check_ptr->name_ref());
00411     /// ...  Rename current symbol and reinsert it
00412     current_symbol.name(new_symbol_ptr->name_ref());
00413     current_pgm.symtab().ins(&current_symbol);
00414     /// ...  Handle second colliding symbol
00415     if (check_ptr) {
00416       /// ...  Rename and insert colliding symbol into current program.
00417       /// ...  
00418       /// ...  There is need for further renaming only if there is a third
00419       /// ...  collision (with the new program) after renaming and this
00420       /// ...  third collision involves a variable from an equivalence
00421       /// ...  block not yet present in the new program... if so, the
00422       /// ...  variable is yet to be processed (or the collision would not
00423       /// ...  have occurred) and so it can be handled later. 
00424       current_pgm.symtab().rename_and_ins(check_ptr);
00425     }
00426   }
00427 /// Return reference to new program symbol
00428   return *new_symbol_ptr;
00429 }
00430 
00431 /// Rename equivalence new_equiv_ptr (to be inserted into new_pgm) and
00432 /// corresponding equivalence current_equiv (which is in current_pgm) so that
00433 /// the two equivalences have the same name in each ProgramUnit.
00434 
00435 /// This routine is used as part of partial ProgramUnit cloning in the
00436 /// presence of name conflicts (e.g., when inlining equivalence blocks).
00437 
00438 Equivalence &
00439 rename_equivalence_to_match(ProgramUnit & current_pgm,
00440                 Equivalence & current_equiv,
00441                 ProgramUnit & new_pgm,
00442                 Equivalence * new_equiv_ptr)
00443 {
00444 /// Potentially rename into new program
00445   new_pgm.equivalences().rename_and_ins(new_equiv_ptr);
00446 /// Look up equivalence with new name in contained program 
00447   Equivalence  *check_ptr =  
00448     current_pgm.equivalences().find_ref(new_equiv_ptr->name_ref());
00449 /// Handle when symbols do not match
00450   if (check_ptr != &current_equiv) {
00451     /// ...  Grab current equivalence from equivalence dictionary
00452     current_pgm.equivalences().grab(current_equiv.name_ref());
00453     /// ...  Grab second colliding equivalence if need be
00454     if (check_ptr) 
00455       check_ptr = current_pgm.equivalences().grab(check_ptr->name_ref());
00456     /// ...  Rename current equivalence and reinsert it
00457     current_equiv.rename(new_equiv_ptr->name_ref());
00458     current_pgm.equivalences().ins(&current_equiv);
00459     /// ...  Handle second colliding equivalence
00460     if (check_ptr) {
00461       /// ...  Rename and insert colliding symbol into current program.
00462       /// ...  
00463       /// ...  There is need for further renaming only if there is a third
00464       /// ...  collision (with the new program) after renaming and this
00465       /// ...  third collision involves an equivalence block not yet
00466       /// ...  present in the new program... if so, the equivalence block
00467       /// ...   is yet to be processed (or the collision would not
00468       /// ...  have occurred) and so it will be handled later. 
00469       current_pgm.equivalences().rename_and_ins(check_ptr);
00470     }
00471   }
00472 /// Return reference to new program equivalence
00473   return *new_equiv_ptr;
00474 }
00475 
00476 
00477 RefSet<Symbol> *
00478 interface_vars( ProgramUnit & pgm )
00479 {
00480     /// ...  Make a RefSet to hold the interface variables for this program unit.
00481 
00482     RefSet<Symbol> * iface_vars = new RefSet<Symbol>;
00483 
00484     for (Iterator<Statement> entry_iter = pgm.stmts().iterate_entry_points();
00485      entry_iter.valid();
00486      ++entry_iter) {
00487 
00488     EntryStmt & entry_stmt = (EntryStmt &) entry_iter.current();
00489     
00490     if (entry_stmt.parameters_valid()) {
00491         for (Iterator<Expression> param_iter = entry_stmt.parameters_guarded().arg_list();
00492          param_iter.valid();
00493          ++param_iter) {
00494 
00495         Symbol * formal = param_iter.current().base_variable_ref();
00496 
00497         iface_vars->ins( *formal );
00498         }
00499     }
00500     }
00501 
00502     for (DictionaryIter<Symbol> sym_iter = pgm.symtab().iterator();
00503      sym_iter.valid();
00504      ++sym_iter) {
00505 
00506     Symbol & sym = sym_iter.current();
00507 
00508     if (sym.common_ref()) {
00509         iface_vars->ins( sym );
00510     }
00511     }
00512 
00513     return iface_vars;
00514 }
00515 
00516 /// Renames all occurences of var in pgm to a new symbol with the
00517 /// same base name. Used when some variable has the same name as
00518 /// an intrinsic function call (ex. DEALSE in OCEAN uses LOC as a
00519 /// variable name)
00520 void
00521 rename_all_occurences(ProgramUnit &pgm, Symbol &var)
00522 {
00523   Symbol *new_var = var.clone();
00524   new_var = & pgm.symtab().rename_and_ins(new_var);
00525   
00526   for(Iterator<Statement> siter = pgm.stmts(); siter.valid(); ++siter)
00527     for(Mutator<Expression> eiter = siter.current().iterate_expressions();
00528     eiter.valid(); ++eiter)
00529       substitute_var(eiter.current(), var, *new_var);
00530 
00531   pgm.symtab().del(var.name_ref());
00532 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:06:02 2005