Polaris: InlineObject.cc Source File

InlineObject.cc

Go to the documentation of this file.
00001 ///
00002 ///
00003 /// Original code written by John Robert Grout, UIUC
00004 ///
00005 /// Recursive inlining features added by Keith Jackson, Texas A&M University
00006 ///  (kjackson@tamu.edu)
00007 ///
00008 #ifdef POLARIS_GNU_PRAGMAS
00009 #pragma implementation
00010 #endif
00011 ///
00012 #include "InlineObject.h"
00013 
00014 #include <stdio.h>
00015 #include <strstream.h>
00016 
00017 #include "AbstractAccess.h"
00018 #include "Collection/KeySet.h"
00019 #include "CommonBlock.h"
00020 #include "Directive/AssertComment.h"
00021 #include "Directive/AssertPrivate.h"
00022 #include "Directive/AssertRelation.h"
00023 /// added AssertRecursiveInline.h (kjackson)
00024 #include "Directive/AssertRecursiveInline.h"
00025 #include "Directive/Assertion.h"
00026 #include "Equivalence.h"
00027 #include "Expression/expr_funcs.h"
00028 #include "Expression/ArgNumberExpr.h"
00029 #include "Expression/IntConstExpr.h"
00030 #include "Expression/LambdaCallExpr.h"
00031 #include "Expression/LogicalConstExpr.h"
00032 #include "FormatDB.h"
00033 #include "Info.h"
00034 #include "IntElem.h"
00035 #include "LabelDB.h"
00036 #include "ProgramUnit.h"
00037 #include "Statement/AssignmentStmt.h"
00038 #include "Statement/GotoStmt.h"
00039 #include "Statement/LabelStmt.h"
00040 #include "StmtList.h"
00041 #include "Symbol/FunctionSymbol.h"
00042 #include "Symbol/VariableSymbol.h"
00043 #include "TranslateObject.h"
00044 #include "Wildcard/AnyOfType.h"
00045 #include "Wildcard/WildcardOr.h"
00046 #include "utilities/StmtInfo.h"
00047 #include "utilities/access_util.h"
00048 #include "utilities/entry_util.h"
00049 #include "utilities/intrinsic_util.h"
00050 #include "utilities/lambda_util.h"
00051 #include "utilities/precalc_util.h"
00052 #include "utilities/program_util.h"
00053 #include "utilities/removegotos_util.h"
00054 #include "utilities/stmt_util.h"
00055 #include "utilities/string_util.h"
00056 #include "utilities/switches_util.h"
00057 #include "utilities/symbol_util.h"
00058 
00059 #include "Constant/constant.h"
00060 #include "Deadcode/deadcode.h"
00061 
00062 template class TypedBaseMap<ProgramUnit,InlineObject>;
00063 template class ProtoMap<ProgramUnit,InlineObject>;
00064 template class Map<ProgramUnit,InlineObject>;
00065 template ostream & operator << (ostream &,
00066                 const Map<ProgramUnit,InlineObject> &);
00067 template class KeyIterator<ProgramUnit,InlineObject>;
00068 
00069 template class Assign<InlineWorkSpace>;
00070 template class Element<InlineWorkSpace>;
00071 template ostream & operator << (ostream &,
00072                 const Element<InlineWorkSpace> &);
00073 template class RefElement<InlineWorkSpace>;
00074 template ostream & operator << (ostream &,
00075                 const RefElement<InlineWorkSpace> &);
00076 
00077 void 
00078 InlineWorkSpace::print(ostream & o) const
00079 {
00080   if (_count_active) {
00081     o << "(<" <<
00082       _exec_lines_input << ", " << _exec_lines_output << ">, <" <<
00083     _total_lines_input << ", " << _total_lines_output << ">)";
00084   }
00085   else
00086     o << "(<false>)";
00087 }
00088   
00089 struct VariableSizes {
00090   int             size;       /// ...  size of whole variable
00091   int             elem_size;  /// ...  size of element
00092 
00093   inline VariableSizes(VariableSymbol & var);
00094   inline void remap(VariableSymbol & var);
00095 };
00096 
00097 inline 
00098 VariableSizes::VariableSizes(VariableSymbol & var)
00099 {
00100   size = var.size();
00101   elem_size = var.type().size();
00102 }
00103 
00104 inline void
00105 VariableSizes::remap(VariableSymbol & var)
00106 {
00107   size = var.size();
00108   elem_size = var.type().size();
00109 }
00110 
00111 enum CONFORM_TYPE {
00112     IDENTICAL,
00113     TRANSFORMABLE_CONSTANT,
00114     TRANSFORMABLE_ARRAY,
00115     TRANSFORMABLE_SUBSTRING,
00116     TRANSFORMABLE_SUBSTRING_ARRAY,
00117     NON_CONFORMABLE
00118 };
00119 
00120 void 
00121 InlineObject::print(ostream & o) const
00122 {
00123   TranslateObject::print(o);
00124 
00125   if (_ws_ref.valid()) {
00126     o << "\nInline workspace:\n\n";
00127     o << *_ws_ref;
00128   }
00129 }
00130 
00131 /// Remap and move the formats from contained pgm to main program, renaming
00132 /// them as necessary
00133 
00134 void 
00135 InlineObject::_remap_and_move_formats()
00136 {
00137 
00138 /// Clone formats from contained pgm and insert them into main pgm */
00139 
00140   for (KeyIterator<int,Format> db_iter = _pgm_ref->formats();
00141        db_iter.valid(); ++db_iter) {
00142     Format & current_format = db_iter.current_data();
00143     int format_label = current_format.value();
00144 
00145     /// ...  Iterate to fixed point to find unconflicting number for format in
00146     /// ...  contained and main program
00147 
00148     while (1) {
00149 
00150       int label_save = format_label;
00151       format_label = _pgm_main.stmts().new_label(label_save);
00152       if (format_label == label_save)
00153     break;
00154       label_save = format_label;
00155       format_label = _pgm_ref->stmts().new_label(label_save);
00156       if (format_label == label_save)
00157     break;
00158     }
00159     
00160     /// ...  Relabel format if necessary
00161 
00162     if (format_label != current_format.value())
00163       _pgm_ref->formats().relabel(current_format.value(),format_label);
00164 
00165     /// ...  Clone and insert into main program
00166 
00167     Format * cloned_format = (Format *) current_format.listable_clone();
00168     _pgm_main.formats().ins(cloned_format);
00169 
00170     /// ...  Map from format to cloned format
00171 
00172     _format_map.ins(current_format, *cloned_format);
00173   }
00174 }
00175 
00176 /// Precalculate adjustable array bounds
00177 
00178 void 
00179 InlineObject::_precalc_adjustable_array_bounds()
00180 {
00181     StmtInfo        arg_map;
00182 
00183     arg_map.program_ref = _pgm_ref;
00184 
00185     /// ...  Iterate over entries of program
00186 
00187     for (Iterator<Statement> entry_iter 
00188             = _pgm_ref->stmts().iterate_entry_points();
00189                              entry_iter.valid(); ++entry_iter) {
00190         /// ...  Set c to point to current statement
00191 
00192         Statement      *c = &entry_iter.current();
00193 
00194         /// ...  Iterate over entry's parameters if necessary
00195 
00196         if ((c->stmt_class() == FLOW_ENTRY_STMT) || (!c->parameters_valid()))
00197             continue;
00198 
00199         /// ...  Point to the statement after entry
00200 
00201         arg_map.stmt_ref = c->next_ref();
00202 
00203     {
00204 
00205       // Iterate over formal parameters
00206 
00207       // Type int_type = make_type(INTEGER_TYPE);
00208 
00209       for (Iterator<Expression> parm_iter 
00210            = c->parameters_guarded().arg_list();
00211            parm_iter.valid(); ++parm_iter) {
00212         p_assert(parm_iter.current().op() == ID_OP,
00213              "Bad entry parmlist in precalc_adjustable_array_bounds");
00214 
00215         Symbol & parm_symbol = parm_iter.current().symbol();
00216 
00217         if (parm_symbol.sym_class() == VARIABLE_CLASS) {
00218 
00219           for (Iterator<ArrayBounds> bound_iter = parm_symbol.dim();
00220            bound_iter.valid(); 
00221            ++bound_iter) {
00222         ArrayBounds & current_bound = bound_iter.current();
00223 
00224         if (current_bound.lower_exists()) {
00225           Expression & lb = current_bound.lower_guarded();
00226 
00227           if (lb.op() != INTEGER_CONSTANT_OP) {
00228             Assign<Expression> lb_as (
00229               current_bound.arg_list().assign(lb));
00230             lb_as = get_precalc(current_bound.arg_list().pull(lb),
00231                     *arg_map.program_ref,
00232                     *arg_map.stmt_ref,
00233                     PRECALC_ALWAYS, "PC");
00234           }
00235         }
00236 
00237         if (current_bound.upper_exists()) {
00238           Expression & ub = current_bound.upper_guarded();
00239 
00240           if (ub.op() != INTEGER_CONSTANT_OP) {
00241             Assign<Expression> ub_as (
00242               current_bound.arg_list().assign(ub));
00243             ub_as = get_precalc(current_bound.arg_list().pull(ub),
00244                     *arg_map.program_ref,
00245                     *arg_map.stmt_ref,
00246                     PRECALC_ALWAYS, "PC");
00247           }
00248         }
00249           }
00250         }
00251       }
00252     }
00253       }
00254   }
00255 
00256 /// Expand array names which occur in I/O statements into an implicit
00257 /// DO-loop nest over its bounds
00258 
00259 void 
00260 InlineObject::_expand_IO_array_names()
00261 
00262 {
00263 /// Iterate over all candidate I/O statements
00264 
00265   for (Iterator<Statement> IO_iter 
00266        = _pgm_ref->stmts().stmts_of_type(READ_STMT, WRITE_STMT, PRINT_STMT);
00267        IO_iter.valid(); ++IO_iter) {
00268     Statement & s = IO_iter.current();
00269 
00270     /// ...  Iterate over the list of arguments (if any)
00271     
00272     if (s.io_list_valid()) {
00273       for (Mutator<Expression> expr_mutr = s.io_list_guarded().arg_list();
00274        expr_mutr.valid(); ++expr_mutr) {
00275     Expression   & expr = expr_mutr.current();
00276     IntConstExpr   cstone(1);
00277 
00278     if (expr.op() != ID_OP)
00279       continue;
00280 
00281     Symbol & sym = expr.symbol();
00282 
00283     if (sym.sym_class() != VARIABLE_CLASS)
00284       continue;
00285 
00286     if (sym.is_array()) {
00287 
00288       ArrayDims & dim = sym.dim();
00289 
00290       // Expand the expression into an implicit DO-loop nest
00291 
00292       Type            int_type = make_type(INTEGER_TYPE);
00293       Expression     *array_expr 
00294         = array_reference(expr.clone(), comma());
00295       Expression     *current_expr = array_expr;
00296 
00297       for (Iterator<ArrayBounds> bound_iter = dim;
00298            bound_iter.valid();
00299            ++bound_iter) {
00300         ArrayBounds & current_bound = bound_iter.current();
00301         Expression  * bound_lb = current_bound.lower_ref();
00302 
00303         if (!bound_lb)
00304           bound_lb = &cstone;
00305 
00306         Expression     *bound_ub = current_bound.upper_ref();
00307 
00308         if (!bound_ub)
00309         bound_ub = &cstone;
00310 
00311         Expression *var_comma_expr 
00312           = comma(bound_lb->clone(), bound_ub->clone());
00313         
00314         /// ...  Create new local symbol
00315 
00316         Symbol *var_sym 
00317           = new VariableSymbol("PV", int_type,
00318                    NOT_FORMAL, NOT_SAVED);
00319 
00320         /// ...  Insert into symbol table
00321 
00322         _pgm_ref->symtab().rename_and_ins(var_sym);
00323 
00324         /// ...  Insert ID for symbol onto end of array
00325         /// ...  reference
00326 
00327         array_expr->subscript().arg_list().ins_last(id(*var_sym));
00328 
00329         /// ...  Create iteration expression
00330 
00331         Expression *var_eq_expr 
00332           = equal(id(*var_sym), var_comma_expr);
00333 
00334         /// ...  Create do expression
00335 
00336         current_expr
00337           = do_expression(comma(current_expr), var_eq_expr);
00338 
00339       }
00340 
00341       // Insert implicit DO-loop nest in place
00342 
00343       expr_mutr.modify(current_expr);
00344 
00345     }
00346       }
00347     }
00348   }
00349 }
00350 
00351 /// Remap and move a specific variable symbol from contained pgm to
00352 /// main program such that no conflicts arise with respect to either
00353 /// program.
00354 
00355 void 
00356 InlineObject::_remap_variable_symbol(Symbol & current_symbol,
00357                                    RefList<Symbol>&rename_list)
00358 {
00359     /// ...  If the variable symbol collides with main program or is the
00360     /// ...  name of an intrinsic function, process it later.
00361 
00362     const char     *sym_name = current_symbol.name_ref();
00363 
00364     if ((int) _pgm_main.symtab().find_ref(sym_name) ||
00365         (int) lookup_intrinsic(sym_name)) {
00366         rename_list.ins_last(current_symbol);
00367     }
00368     else {
00369         /// ...  If the current symbol can be left as is, move it into main program
00370         /// ...  now and save its translation. 
00371 
00372         Symbol         *new_symbol_ptr 
00373             = current_symbol.clone();
00374 
00375         _pgm_main.symtab().ins(new_symbol_ptr);
00376 
00377     /// ...  If subprogram variable is not saved, remember that it is
00378     /// ...  private to this routine
00379 
00380     PRIVAT_TYPE priv_type = NOT_PRIVATE;
00381 
00382     if(current_symbol.saved()==NOT_SAVED) {
00383       priv_type = PRIVATE;
00384       _private_vars++;
00385     }
00386 
00387     /// ...  If subprogram variable is an integer scalar whose name
00388     /// ...  begins with "PC", remember it as a candidate for propagation.
00389 
00390     PRECALC_TYPE prec_type = NOT_PRECALC_VAR;
00391 
00392     const Type & current_type = current_symbol.type();
00393 
00394     if ((current_type.data_type() == INTEGER_TYPE) &&
00395         (current_type.is_scalar()) &&
00396         (strncmp(current_symbol.name_ref(),"PC",2) == 0)) {
00397       prec_type = CAND_PRECALC_VAR;
00398       _precalc_vars++;
00399     }
00400 
00401         _symbol_map.ins(current_symbol,
00402             new SymRefElem(*new_symbol_ptr, priv_type,
00403                    prec_type));
00404 
00405 
00406     }
00407 }
00408 
00409 /// Remap a specific symbol with no value from contained pgm to main
00410 /// program, renaming any conflicting symbol in the main program.
00411 
00412 void 
00413 InlineObject::_remap_unvalued_symbol(Symbol & current_symbol)
00414 {
00415   Symbol * new_symbol_ptr = NULL;
00416 
00417 /// Attempt to grab a potentially conflicting main program symbol
00418 
00419   Symbol         *main_symbol_ptr 
00420     = _pgm_main.symtab().grab(current_symbol.name_ref());
00421 
00422   if (!main_symbol_ptr) {
00423 
00424     /// ...  There is no conflicting main program symbol, so clone current_symbol
00425     /// ...  and insert it into the main program symbol table
00426 
00427     new_symbol_ptr = current_symbol.clone();
00428     _pgm_main.symtab().ins(new_symbol_ptr);
00429   }
00430   else {
00431 
00432     /// ...  There is a potentially conflicting main program symbol
00433 
00434     switch (main_symbol_ptr->sym_class()) {
00435 
00436     case VARIABLE_CLASS:
00437     case SYMBOLIC_CONSTANT_CLASS:
00438 
00439       {
00440     /// ...  The main program symbol is a valued symbol
00441 
00442     /// ...  Clone current_symbol and insert it into the main program
00443     /// ...  symbol table
00444 
00445     new_symbol_ptr = current_symbol.clone();
00446     _pgm_main.symtab().ins(new_symbol_ptr);
00447 
00448     /// ...  Reinsert conflicting symbol into the main program symbol table
00449     /// ...  with rename
00450 
00451     _pgm_main.symtab().rename_and_ins(main_symbol_ptr);
00452     break;
00453     }
00454 
00455     case FUNCTION_CLASS:
00456     case SUBROUTINE_CLASS:
00457     case PROGRAM_CLASS:
00458     case BLOCK_DATA_CLASS:
00459     case NAMELIST_CLASS:
00460 
00461       {
00462     /// ...  The main program symbol is also an unvalued symbol
00463 
00464     /// ...  For the FORTRAN program to be correct, the definitions of
00465     /// ...  these unvalued symbols must match... so we can translate
00466     /// ...  references to current_symbol to point at the main program symbol
00467 
00468     new_symbol_ptr = main_symbol_ptr;
00469 
00470     /// ...  Reinsert the grabbed main program symbol
00471 
00472     _pgm_main.symtab().ins(main_symbol_ptr);
00473 
00474     break;
00475     }
00476   default: break;
00477       }
00478     }
00479 
00480     /// ...  Save the translation from contained pgm to main program
00481 
00482     _symbol_map.ins(current_symbol,
00483             new SymRefElem(*new_symbol_ptr));
00484 
00485 }
00486 
00487 /// Remap and move a list of symbols with values from contained pgm to main
00488 /// program which need renaming such that no conflicts arise with respect
00489 /// to either program or against the names of intrinsic functions.
00490 
00491 void 
00492 InlineObject::_remap_variable_symbols(RefList<Symbol>&rename_list)
00493 {
00494     for (Iterator<Symbol> rename_iter = rename_list;
00495                           rename_iter.valid(); ++rename_iter) {
00496 
00497         /// ...  Clone the symbol from our symbol table and insert 
00498         /// ...  with rename into main program.
00499 
00500         Symbol & current_symbol = rename_iter.current();
00501         Symbol * new_symbol_ptr = current_symbol.clone();
00502 
00503         _pgm_main.symtab().rename_and_ins(new_symbol_ptr);
00504 
00505     /// ...  If subprogram variable is not saved, remember that it is
00506     /// ...  private to this routine
00507 
00508     PRIVAT_TYPE priv_type = NOT_PRIVATE;
00509 
00510     if(current_symbol.saved()==NOT_SAVED) {
00511       priv_type = PRIVATE;
00512       _private_vars++;
00513     }
00514 
00515     /// ...  If subprogram variable is an integer scalar whose name
00516     /// ...  begins with "PC", remember it as a candidate for propagation.
00517 
00518     PRECALC_TYPE prec_type = NOT_PRECALC_VAR;
00519 
00520     const Type & current_type = current_symbol.type();
00521 
00522     if ((current_type.data_type() == INTEGER_TYPE) &&
00523         (current_type.is_scalar()) &&
00524         (strncmp(current_symbol.name_ref(),"PC",2) == 0)) {
00525       prec_type = CAND_PRECALC_VAR;
00526       _precalc_vars++;
00527     }
00528 
00529         _symbol_map.ins(current_symbol,
00530             new SymRefElem(*new_symbol_ptr, priv_type,
00531                    prec_type));
00532 
00533     }
00534 }
00535 
00536 void 
00537 InlineObject::_remap_local_variables()
00538 {
00539 
00540     RefList<Symbol> rename_list;
00541     RefList<Symbol> symbolic_list;
00542 
00543     for (DictionaryIter<Symbol> sym_iter = _pgm_ref->symtab().iterator();
00544                                 sym_iter.valid(); ++sym_iter) {
00545         Symbol & current_symbol = sym_iter.current();
00546 
00547         switch (current_symbol.sym_class()) {
00548         case VARIABLE_CLASS:
00549             {
00550                 if ((!current_symbol.formal()) &&
00551                     (!current_symbol.equivalence_ref()) &&
00552                     (!current_symbol.common_ref()))
00553                     _remap_variable_symbol(current_symbol, rename_list);
00554                 break;
00555             }
00556 
00557         case FUNCTION_CLASS:
00558         case SUBROUTINE_CLASS:
00559     case PROGRAM_CLASS:
00560     case BLOCK_DATA_CLASS:
00561     case NAMELIST_CLASS:
00562         {
00563             _remap_unvalued_symbol(current_symbol);
00564             break;
00565       }
00566 
00567         case SYMBOLIC_CONSTANT_CLASS:
00568             {
00569           Symbol & main_symbol =
00570         rename_variable_to_match(*_pgm_ref, current_symbol,
00571                      _pgm_main, current_symbol.clone());
00572           _symbol_map.ins(current_symbol,
00573                   new SymRefElem(main_symbol));
00574           symbolic_list.ins_last(main_symbol);
00575           break;
00576         }
00577 
00578     default: break;
00579       }
00580       }
00581 
00582     /// ...  If variable symbols to rename, do so
00583 
00584     if(rename_list.entries())
00585       _remap_variable_symbols(rename_list);
00586 
00587     /// ...  Relink expressions in main program symbolic constants to point
00588     /// ...  at main program symbols
00589     
00590     for(Iterator<Symbol> symbolic_iter = symbolic_list;
00591     symbolic_iter.valid(); ++ symbolic_iter) {
00592       symbolic_iter.current().relink_dptrs(_pgm_main);
00593     }
00594   }
00595 
00596 /// Relabel the labels in the contained pgm to avoid conflict with the
00597 /// main pgm
00598 
00599 void 
00600 InlineObject::_rename_branch_targets()
00601 {
00602 
00603   StmtList & stmts = _pgm_ref->stmts();
00604   StmtList & main_stmts = _pgm_main.stmts();
00605 
00606 /// Scan the label database in ascending label order
00607 
00608   int label_number = stmts.labels().first_ref();
00609 
00610   while (label_number) {
00611 
00612     /// ...  Iterate to fixed point to find unconflicting number for label
00613     /// ...  in contained and main program
00614 
00615     int old_label_number = label_number;
00616 
00617     while (1) {
00618 
00619       int label_save = label_number;
00620       label_number = main_stmts.new_label(label_save);
00621       if (label_number == label_save)
00622     break;
00623       label_save = label_number;
00624       label_number = stmts.new_label(label_save);
00625       if (label_number == label_save)
00626     break;
00627     }
00628 
00629     /// ...  Relabel label statement if necessary
00630     
00631     if (label_number != old_label_number)
00632       stmts.relabel(old_label_number,label_number);
00633 
00634     /// ...  Find next label in label database (Note: we may see a label
00635     /// ...  twice, but the second time, it won't conflict)
00636 
00637     label_number = stmts.labels().successor_ref(old_label_number);
00638 
00639   }
00640 
00641 }
00642 
00643 /// Test and see if a parameter and a main program expression are
00644 /// conformable enough to be easily replaced.
00645 ///
00646 /// IDENTICAL: 
00647 ///      means that they are identical.
00648 /// TRANSFORMABLE_CONSTANT: 
00649 ///      means that the calling argument is a non-symbolic constant.
00650 /// TRANSFORMABLE_ARRAY: 
00651 ///      means that the calling reference is an array reference which 
00652 ///      is different but conformable.
00653 /// TRANSFORMABLE_SUBSTRING: 
00654 ///      means that the calling reference is a substring reference (whose
00655 ///      associated string has conformability IDENTICAL)
00656 /// TRANSFORMABLE_SUBSTRING_ARRAY: 
00657 ///      means that the calling reference is a substring reference (whose
00658 ///      associated string has conformability TRANSFORMABLE_ARRAY)
00659 /// NON_CONFORMABLE: 
00660 ///      means that they are not conformable.
00661 ///
00662 
00663 static CONFORM_TYPE 
00664 conformable_test(VariableSymbol * name_ptr, Expression & main_expr,
00665          bool equivalent_var_generated)
00666 {
00667     Symbol         *main_name_ptr = 0;
00668     Expression     *main_subs_ptr = 0;
00669     Expression     *main_bound_ptr = 0;
00670 
00671     /// ...  Perform initialization
00672 
00673     switch (main_expr.op()) {
00674     case INTEGER_CONSTANT_OP:
00675     case REAL_CONSTANT_OP:
00676     case LOGICAL_CONSTANT_OP:
00677 
00678       if (main_expr.type() == name_ptr->type())
00679     return TRANSFORMABLE_CONSTANT;
00680       else
00681     return NON_CONFORMABLE;
00682 
00683     case ID_OP:
00684         {
00685             main_name_ptr = main_expr.base_variable_ref();
00686 
00687             if (main_name_ptr->sym_class() == SYMBOLIC_CONSTANT_CLASS) {
00688                 if (main_name_ptr->type() == name_ptr->type())
00689                     return IDENTICAL;
00690                 else
00691                     return NON_CONFORMABLE;
00692             }
00693             break;
00694         }
00695 
00696     case ARRAY_REF_OP:
00697         {
00698             main_name_ptr = main_expr.base_variable_ref();
00699             main_subs_ptr = &main_expr.subscript();
00700             break;
00701         }
00702 
00703     case SUBSTRING_OP:
00704       {
00705     main_bound_ptr = &main_expr.bound();
00706     Expression & main_string_expr = main_expr.string();
00707     main_name_ptr = main_string_expr.base_variable_ref();
00708     if (main_string_expr.op()==ARRAY_REF_OP)
00709       main_subs_ptr = &main_string_expr.subscript();
00710     break;
00711       }
00712 
00713     default:
00714         p_abort("Illegal expression detected in conformable_test");
00715     }
00716 
00717     /// ...  Equivalenced common variables are not transformable unless
00718     /// ...  an equivalent variable (with matching name) has already been
00719     /// ...  generated
00720 
00721     bool transformable = ((!name_ptr->common_ref()) ||
00722               (!name_ptr->equivalence_ref()) ||
00723               equivalent_var_generated);
00724 
00725     const Type & name_type = name_ptr->type();
00726     const Type & main_name_type = main_name_ptr->type();
00727 
00728     /// ...  If name_ptr points to a character dummy, it is conformable with any
00729     /// ...  main program character variable
00730 
00731     if ((name_type.data_type() == CHARACTER_TYPE) && (name_type.size() == 0)) {
00732       if (main_name_type.data_type() == CHARACTER_TYPE) {
00733     if (!main_bound_ptr)
00734       return IDENTICAL;
00735     else
00736       return TRANSFORMABLE_SUBSTRING;
00737       }
00738       else
00739     return NON_CONFORMABLE;
00740     }
00741 
00742     /// ...  Otherwise, if the types are different, they are non-conformable
00743 
00744     if ((name_type.data_type() != main_name_type.data_type()) ||
00745         (name_type.size() != main_name_type.size()))
00746         return NON_CONFORMABLE;
00747 
00748     /// ...  TODO: An array reference with substring operator in calling program
00749     /// ...  is only conformable to _one_ variable (or, perhaps, an array of single
00750     /// ...  characters) in the called program
00751 
00752     /// ...  Get the dimension information for each symbol
00753 
00754     ArrayDims & name_dim = name_ptr->dim();
00755     int         name_dims = name_dim.entries();
00756 
00757     ArrayDims & main_name_dim = main_name_ptr->dim();
00758     int         main_name_dims = main_name_dim.entries();
00759 
00760     /// ...  If both variables are scalars, they are conformable
00761 
00762     if ((name_dims == 0) && (main_name_dims == 0)) {
00763       if (!main_bound_ptr)
00764         return IDENTICAL;
00765       else
00766     return TRANSFORMABLE_SUBSTRING;
00767     }
00768 
00769     /// ...  Set default conformability
00770 
00771     CONFORM_TYPE    conformable;
00772       
00773     if (!main_bound_ptr)
00774       conformable = IDENTICAL;
00775     else
00776       conformable = TRANSFORMABLE_SUBSTRING;
00777 
00778     /// ...  Perform array-to-array checking
00779 
00780     if ((name_dims != 0) && (main_name_dims != 0)) {
00781         /// ...  Perform m to m dimensional array-to-array checking
00782 
00783         if (name_dims == main_name_dims) {
00784             /// ...  Iterate over all the dimensions
00785 
00786             IntConstExpr    cstone(1);
00787 
00788             Iterator<ArrayBounds> name_iter = name_dim;
00789             Iterator<ArrayBounds> main_name_iter = main_name_dim;
00790 
00791             List<Expression>  dummy_list;
00792             List<Expression> *main_subs_listptr = &dummy_list;
00793 
00794             if (main_subs_ptr)
00795                 main_subs_listptr = &main_subs_ptr->arg_list();
00796 
00797             Iterator<Expression> main_subs_iter(*main_subs_listptr);
00798 
00799             for (int i = 0; i<name_dims; ++i) {
00800                 Expression     *name_lb = name_iter.current().lower_ref();
00801 
00802                 if (!name_lb)
00803                     name_lb = &cstone;
00804 
00805                 Expression *name_ub = name_iter.current().upper_ref();
00806 
00807                 if (!name_ub)
00808                     name_ub = &cstone;
00809 
00810                 Expression *main_name_lb = main_name_iter.current().lower_ref();
00811 
00812                 if (!main_name_lb)
00813                     main_name_lb = &cstone;
00814 
00815                 Expression *main_name_ub = main_name_iter.current().upper_ref();
00816 
00817                 if (!main_name_ub)
00818                     main_name_ub = &cstone;
00819 
00820                 Expression     *main_name_offptr;
00821 
00822                 /// ...  Handle case when main_name was subscripted
00823 
00824                 if (main_subs_ptr) {
00825                     main_name_offptr =
00826                         simplify(sub(main_subs_iter.current().clone(),
00827                                      main_name_lb->clone()));
00828 
00829                     /// ...  If there's a difference in a dimension other than
00830                     /// ...  the last one, variables are non-conformable 
00831 
00832                     if ((i != name_dims - 1) &&
00833                       ((main_name_offptr->op() != INTEGER_CONSTANT_OP) ||
00834                        (main_name_offptr->value() != 0))) {
00835                         delete main_name_offptr;
00836                         return NON_CONFORMABLE;
00837                     }
00838 
00839                     delete main_name_offptr;
00840                     main_name_offptr = main_subs_iter.current().clone();
00841                 }
00842                 else {
00843                     /// ...  If main name not offset, default offset is lower bound
00844                     main_name_offptr = main_name_lb->clone();
00845                 }
00846 
00847                 Expression     *offset 
00848                     = simplify(sub(sub(main_name_ub->clone(),
00849                                        main_name_offptr->clone()),
00850                                    sub(name_ub->clone(), name_lb->clone())));
00851 
00852                 if ((offset->op() != INTEGER_CONSTANT_OP) ||
00853                     (offset->value() != 0)) {
00854                     delete main_name_offptr;
00855                     delete offset;
00856 
00857                     if (transformable &&
00858             (i == main_name_dims - 1)) {
00859               if (!main_bound_ptr)
00860                         return TRANSFORMABLE_ARRAY;
00861               else
00862             return TRANSFORMABLE_SUBSTRING_ARRAY;
00863             }
00864                     else
00865                         return NON_CONFORMABLE;
00866                 }
00867 
00868                 delete offset;
00869 
00870                 /// ...  Absorb main_name_offptr as subexpression of offset
00871 
00872                 offset = simplify(sub(main_name_offptr, name_lb->clone()));
00873 
00874                 if ((offset->op() != INTEGER_CONSTANT_OP) ||
00875                     (offset->value() != 0)) {
00876           if (!main_bound_ptr)
00877                     conformable = TRANSFORMABLE_ARRAY;
00878           else
00879             conformable = TRANSFORMABLE_SUBSTRING_ARRAY;
00880         }
00881 
00882                 delete offset;
00883 
00884                 /// ...  Increment dimension iterators
00885 
00886                 ++name_iter;
00887                 ++main_name_iter;
00888 
00889                 if (main_subs_ptr)
00890                     ++main_subs_iter;
00891             }
00892         if (transformable)
00893           return conformable;
00894         else
00895           return NON_CONFORMABLE;
00896     }
00897         else {
00898             /// ...  Handle one to many case
00899       if (transformable &&
00900           (main_name_dims == 1)) {
00901         if (!main_bound_ptr)
00902           return TRANSFORMABLE_ARRAY;
00903         else
00904           return TRANSFORMABLE_SUBSTRING_ARRAY;
00905       }
00906     }
00907       }
00908     else {
00909         /// ...  Handle array to scalar case
00910         if (transformable &&
00911         (name_dims == 0)) {
00912         if (!main_bound_ptr)
00913           return TRANSFORMABLE_ARRAY;
00914         else
00915           return TRANSFORMABLE_SUBSTRING_ARRAY;
00916       }
00917       }
00918 
00919     return NON_CONFORMABLE;
00920 }
00921 
00922 /// Given an array reference calling parameter pointed to by src_name_ptr
00923 /// with subscript pointed to by src_subs_ptr, return a CommaExpr which
00924 /// points to a pair of expressions: a subscript to an equivalent
00925 /// one-dimensional array pointed to by tgt_name_ptr (which can be in
00926 /// either program) and a test expression (possibly symbolic) which will
00927 /// be zero iff the equivalent variable is aligned correctly for this
00928 /// reference.
00929 
00930 Expression     *
00931 InlineObject::_linearize_array_ref(VariableSymbol * src_name_ptr,
00932                    Expression     * src_subs_ptr,
00933                    VariableSymbol * tgt_name_ptr)
00934 {
00935 
00936     /// ...  Get the dimension information for each symbol
00937 
00938     ArrayDims & src_dim = src_name_ptr->dim();
00939     int         src_dims = src_dim.entries();
00940 
00941     ArrayDims & tgt_dim = tgt_name_ptr->dim();
00942     /// ...    int         tgt_dims = tgt_dim.entries();
00943 
00944     List<Expression> & src_subs_list = src_subs_ptr->arg_list();
00945 
00946     /// ...  Calculate initial offset
00947 
00948     Expression     *src_exl;
00949     Expression     *src_exu;
00950     Expression     *tgt_exl;
00951     Expression     *offset;
00952 
00953     if (src_dims>1) {
00954         src_exl = src_dim[src_dims - 1].lower_ref();
00955 
00956         if (src_exl)
00957             src_exl = src_exl->clone();
00958         else
00959             src_exl = constant(1);
00960 
00961         /// ...  Absorb src_exl as subexpression of offset
00962 
00963         offset = sub(src_subs_list[src_dims - 1].clone(), src_exl);
00964 
00965         for (int i = src_dims - 2; i>0; --i) {
00966             src_exl = src_dim[i].lower_ref();
00967 
00968             if (src_exl)
00969                 src_exl = src_exl->clone();
00970             else
00971                 src_exl = constant(1);
00972 
00973             src_exu = src_dim[i].upper_ref();
00974 
00975             if (src_exu)
00976                 src_exu = src_exu->clone();
00977             else
00978                 src_exu = constant(1);
00979 
00980             /// ...  Absorb src_exl and src_exu as subexpressions of offset
00981 
00982             offset = add(mul(add(sub(src_exu, src_exl), constant(1)),
00983                              offset),
00984                          sub(src_subs_list[i].clone(), src_exl->clone()));
00985         }
00986     }
00987     else {
00988         offset = constant(0);
00989     }
00990 
00991     src_exl = src_dim[0].lower_ref();
00992 
00993     if (src_exl)
00994         src_exl = src_exl->clone();
00995     else
00996         src_exl = constant(1);
00997 
00998     src_exu = src_dim[0].upper_ref();
00999 
01000     if (src_exu)
01001         src_exu = src_exu->clone();
01002     else
01003         src_exu = constant(1);
01004 
01005     /// ...  Absorb src_exl and src_exu as subexpressions of offset
01006 
01007     offset = add(mul(add(sub(src_exu, src_exl), constant(1)),
01008                      offset),
01009                  sub(src_subs_list[0].clone(), src_exl->clone()));
01010 
01011     /// ...  Adjust for size differences between source and target
01012 
01013     int src_name_size = src_name_ptr->type().size();
01014     int tgt_name_size = tgt_name_ptr->type().size();
01015 
01016     Expression * test_expr;
01017 
01018     if (tgt_name_size > src_name_size) {
01019 
01020       p_assert(!(tgt_name_size % src_name_size),
01021            "Non-conformable sizes encountered in _linearize_array_ref");
01022 
01023       /// ...  Calculate divisor
01024 
01025       Expression * divisor = constant(tgt_name_size / src_name_size);
01026 
01027       /// ...  Generate test expression
01028 
01029       Symbol *mod_sym = _pgm_main.symtab().find_ref("MOD");
01030 
01031       if (! mod_sym) {
01032         mod_sym = new FunctionSymbol("MOD", make_type(INTEGER_TYPE),
01033                                      NOT_EXTERNAL, IS_INTRINSIC, NOT_FORMAL);
01034         _pgm_main.symtab().ins(mod_sym);
01035       }
01036         
01037       test_expr = intrinsic_call(id(*mod_sym),
01038                  comma(offset->clone(), divisor->clone()));
01039       test_expr->type(offset->type());
01040 
01041       test_expr = eq(test_expr,constant(0));
01042 
01043       /// ...  Divide offset to adjust for larger target size
01044 
01045       offset = div(offset, divisor);
01046 
01047     }
01048 
01049     else {
01050 
01051       if (src_name_size > tgt_name_size) {
01052     
01053     p_assert(!(src_name_size % tgt_name_size),
01054          "Non-conformable sizes encountered in _linearize_array_ref");
01055 
01056     /// ...  Multiply offset to adjust for smaller target size
01057 
01058     offset = mul(offset, constant(src_name_size / tgt_name_size));
01059 
01060       }
01061     test_expr = new LogicalConstExpr(".TRUE.");
01062     }
01063 
01064 
01065     tgt_exl = tgt_dim[0].lower_ref();
01066 
01067     if (tgt_exl)
01068         tgt_exl = tgt_exl->clone();
01069     else
01070         tgt_exl = constant(1);
01071 
01072     /// ...  Absorb tgt_exl as subexpression of offset
01073 
01074     offset = add(offset, tgt_exl);
01075 
01076     /// ...  Return expressions
01077 
01078     return comma(offset,test_expr);
01079 }
01080 
01081 /// Given a variable pointed to by src_name_ptr with constant array 
01082 /// bounds, convert the element offset src_offset and return an 
01083 /// equivalent subscript.
01084 
01085 static Expression      *
01086 unlinearize_array_ref(VariableSymbol * src_name_ptr, int src_offset)
01087 {
01088     int             lb_size_array[7];
01089     int             src_size_array[7];
01090     int             i = 0;
01091     int             src_size = 1;
01092     Iterator<ArrayBounds> array_iter(src_name_ptr->dim());
01093 
01094     for ( ; array_iter.valid(); ++array_iter, ++i) {
01095         int             ub_size;
01096 
01097         Expression     *lb = array_iter.current().lower_ref();
01098 
01099         if (lb)
01100             lb_size_array[i] = lb->value();
01101         else
01102             lb_size_array[i] = 1;
01103 
01104         Expression     *ub = array_iter.current().upper_ref();
01105 
01106         if (ub)
01107             ub_size = ub->value();
01108         else
01109             ub_size = 1;
01110 
01111         src_size = src_size * (ub_size - lb_size_array[i] + 1);
01112         src_size_array[i] = src_size;
01113     }
01114 
01115     /// ...  Iterate backward over the dimensions to calculate offsets
01116 
01117     Expression *returned_ref = comma();
01118 
01119     i = src_name_ptr->dim().entries() - 1;
01120 
01121     for ( ; i > 0; --array_iter, --i ) {
01122         int off_value = lb_size_array[i] + (src_offset / src_size_array[i]);
01123 
01124         returned_ref->arg_list().ins_first(constant(off_value));
01125         src_offset = src_offset % src_size_array[i];
01126     }
01127 
01128     returned_ref->arg_list().ins_first(constant(lb_size_array[0] + src_offset));
01129 
01130     return returned_ref;
01131 }
01132 
01133 /// Given a calling expression main_expr in pgm_main which doesn't
01134 /// correspond to the dummy variable pointed to by name_ptr, generate an
01135 /// (or use) an equivalent conformable variable in pgm_main (and, if
01136 /// calling parameter was an array reference, generate an equivalent array
01137 /// reference expression).  Return a CommaExpr which points to a pair
01138 /// of expressions: a conformable expression, and a test expression (possibly
01139 /// symbolic) which will be zero iff the equivalent variable is aligned
01140 /// correctly for this reference.
01141 
01142 Expression     *
01143 InlineObject::_gen_equivalent_var(VariableSymbol * name_ptr,
01144                                   Expression & main_expr)
01145 {
01146   p_assert((main_expr.base_variable_ref() &&
01147         (main_expr.base_variable_ref()->sym_class() == VARIABLE_CLASS)),
01148        "Non-conformable non-variable in _gen_equivalent_var");
01149 
01150   VariableSymbol *main_name_ptr 
01151     = (VariableSymbol *) main_expr.base_variable_ref();
01152 
01153   Expression     *main_subs_ptr = 0;
01154 
01155   if (main_expr.op() == ARRAY_REF_OP)
01156     main_subs_ptr = &main_expr.subscript();
01157 
01158 /// Calculate element and array sizes of name and main_name
01159 
01160   VariableSizes   variable_sizes(*name_ptr);
01161 
01162   VariableSizes   main_variable_sizes(*main_name_ptr);
01163 
01164   int             main_name_base;
01165 
01166   VariableSymbol *equiv_name_ptr = 0;
01167 
01168 /// Check if main_name is already in an equivalence class
01169 
01170   Equivalence    *main_equiv_ptr = main_name_ptr->equivalence_ref();
01171 
01172   if (main_equiv_ptr) {
01173 
01174     /// ...  Check each member for suitability
01175 
01176     main_name_base = main_equiv_ptr->find_ref(*main_name_ptr)->byte_base();
01177 
01178     for (Iterator<EquivalenceMember> equiv_iter =
01179      main_equiv_ptr->iterator();equiv_iter.valid(); ++equiv_iter) {
01180       equiv_name_ptr =
01181     (VariableSymbol *) & equiv_iter.current().symbol();
01182 
01183       int equiv_name_base = equiv_iter.current().byte_base();
01184 
01185       if ((equiv_name_base == main_name_base) &&
01186       (equiv_name_ptr->type().data_type()==
01187        name_ptr->type().data_type())) {
01188 
01189     VariableSizes   equiv_variable_sizes(*equiv_name_ptr);
01190 
01191     if ((main_variable_sizes.size == equiv_variable_sizes.size) 
01192         && (variable_sizes.elem_size == equiv_variable_sizes.elem_size)
01193         && ((!name_ptr->is_array()) ||
01194         (equiv_name_ptr->dim().entries() == 1))) {
01195 
01196       // Member variable is suitable
01197 
01198       // If not equivalenced common variable, return to caller
01199       // now
01200 
01201       if ((!name_ptr->common_ref()) || (!name_ptr->equivalence_ref())) {
01202 
01203         /// ...  If array reference, adjust subscript and return to
01204         /// ...  caller
01205 
01206         if (main_subs_ptr) {
01207         
01208           Expression     *linearized_ref =
01209         simplify(_linearize_array_ref(main_name_ptr, main_subs_ptr,
01210                           equiv_name_ptr ));
01211           Expression     * test_expr =
01212         linearized_ref->arg_list().grab(1);
01213 
01214           return comma(array_reference(id(*equiv_name_ptr),
01215                        linearized_ref),
01216                test_expr);
01217         }
01218         else
01219           return comma(id(*equiv_name_ptr),
01220                new LogicalConstExpr(".TRUE."));
01221       }
01222 
01223       // If equivalenced common variable, use this variable as a
01224       // template for another variable
01225 
01226       else
01227         break;
01228 
01229     }
01230     else
01231       equiv_name_ptr = 0;
01232       }
01233       else
01234     equiv_name_ptr = 0;
01235 
01236     }
01237   }
01238 
01239   else {
01240     /// ...  Generate a new equivalence class which follows the existing
01241     /// ...  conventions
01242     char            label_buff[10];
01243     int             equiv_count = _pgm_main.equivalences().entries();
01244 
01245     sprintf(label_buff, "EQ%u", equiv_count+1);
01246 
01247     main_equiv_ptr = new Equivalence(label_buff);
01248 
01249     /// ...  Insert it into main pgm, renaming if necessary
01250     _pgm_main.equivalences().rename_and_ins(main_equiv_ptr);
01251 
01252     /// ...  Insert main_name into it with byte base 0
01253     main_name_base = 0;
01254     main_equiv_ptr->ins(*main_name_ptr, main_name_base);
01255 
01256     /// ...  If equivalenced common variable, main program variable
01257     /// ...  might be suitable as a template, so check it
01258 
01259     if (name_ptr->common_ref() && name_ptr->equivalence_ref() &&
01260     (main_name_ptr->type().data_type()==
01261      name_ptr->type().data_type()) &&
01262     (variable_sizes.elem_size == main_variable_sizes.elem_size) &&
01263     ((!name_ptr->is_array()) ||
01264      (main_name_ptr->dim().entries() == 1)))
01265       equiv_name_ptr = main_name_ptr;
01266 
01267   }
01268 
01269 /// If one not found already, generate new equivalence variable
01270 
01271   if (!equiv_name_ptr) {
01272 
01273     /// ...  Calculate the new variable's bounds
01274 
01275     Expression     *upper_bound;
01276     ArrayBounds    *new_bounds;
01277 
01278     if ((variable_sizes.size != 0) ||
01279     (main_variable_sizes.size != 0)) {
01280       if (variable_sizes.size<main_variable_sizes.size)
01281     upper_bound 
01282       = constant(main_variable_sizes.size / variable_sizes.elem_size);
01283       else
01284     upper_bound =
01285       constant(variable_sizes.size / variable_sizes.elem_size);
01286       new_bounds = new ArrayBounds(constant(1), upper_bound);
01287     }
01288     else 
01289       new_bounds = new ArrayBounds();
01290 
01291     equiv_name_ptr
01292       = new VariableSymbol(main_name_ptr->name_ref(), name_ptr->type(),
01293                main_name_ptr->formal(), main_name_ptr->saved(),
01294                new_bounds);
01295 
01296     /// ...  Insert into main program and equivalence
01297       
01298     _pgm_main.symtab().rename_and_ins(equiv_name_ptr);
01299     main_equiv_ptr->ins(*equiv_name_ptr, main_name_base);
01300 
01301   }
01302 
01303 /// If not equivalenced common variable, return to caller
01304 /// now
01305 
01306   if ((!name_ptr->common_ref()) || (!name_ptr->equivalence_ref())) {
01307 
01308     /// ...  If array reference, adjust subscript and return to
01309     /// ...  caller
01310 
01311     if (main_subs_ptr) {
01312         
01313       Expression     *linearized_ref =
01314     simplify(_linearize_array_ref(main_name_ptr, main_subs_ptr,
01315                       equiv_name_ptr ));
01316       Expression     * test_expr =
01317     linearized_ref->arg_list().grab(1);
01318 
01319       return comma(array_reference(id(*equiv_name_ptr),
01320                    linearized_ref),
01321            test_expr);
01322     }
01323     else
01324       return comma(id(*equiv_name_ptr),
01325            new LogicalConstExpr(".TRUE."));
01326   }
01327 
01328 /// If equivalenced common variable, clone name_ptr
01329 
01330   Symbol & main_equiv_name =
01331     rename_variable_to_match(*_pgm_ref, *name_ptr,
01332                  _pgm_main, name_ptr->clone());
01333 
01334 /// Change main_equiv_name's formal and saved values to those of main_name_ptr
01335 
01336   main_equiv_name.formal(main_name_ptr->formal());
01337   main_equiv_name.saved(main_name_ptr->saved());
01338 
01339 /// Insert into equivalence at correct byte base
01340 
01341   if(!main_subs_ptr)
01342     main_equiv_ptr->ins(main_equiv_name, main_name_base);
01343   else {
01344     /// ...  Calculate correct byte base
01345     Expression     *linearized_ref
01346       = simplify(_linearize_array_ref(main_name_ptr, main_subs_ptr,
01347                       equiv_name_ptr));
01348     int array_offset = linearized_ref->arg_list()[0].value();
01349     delete linearized_ref;
01350     ArrayBounds & old_bound = equiv_name_ptr->dim()[0];
01351     if (old_bound.lower_exists())
01352       array_offset = array_offset - old_bound.lower_guarded().value();
01353     else
01354       --array_offset;
01355 
01356     main_equiv_ptr->ins(main_equiv_name,
01357             main_name_base +
01358             array_offset * variable_sizes.elem_size);
01359 
01360   }
01361 
01362 /// Return equivalent variable to caller
01363 
01364   return comma(id(main_equiv_name),
01365            new LogicalConstExpr(".TRUE."));
01366 }
01367 
01368 /// Determine if an alternate expression will be generated
01369 
01370 bool
01371 alternate_expr_valid(VariableSymbol * name_ptr,
01372              Expression & main_expr)
01373 {
01374   bool return_value = false;
01375 
01376   if (main_expr.op()==ID_OP) {
01377     Symbol & main_name = main_expr.symbol();
01378     if (main_name.is_scalar()) {
01379       ArrayDims & name_dims = name_ptr->dim();
01380       if ((name_dims.entries()==1)) {
01381     ArrayBounds & name_bnds = name_dims[0];
01382     Expression * lower_bnd_ref = 0;
01383     if (name_bnds.lower_exists())
01384       lower_bnd_ref = &name_bnds.lower_guarded();
01385     if ((!lower_bnd_ref ||
01386          ((lower_bnd_ref->op()==INTEGER_CONSTANT_OP) &&
01387           (lower_bnd_ref->value() == 1))) &&
01388         name_bnds.upper_exists()) {
01389       Expression & upper_bnd = name_bnds.upper_guarded();
01390       if ((upper_bnd.op()==INTEGER_CONSTANT_OP) &&
01391           (upper_bnd.value() == 2))
01392         return_value = true;
01393     }
01394       }
01395     }
01396   }
01397   return return_value;
01398 }
01399 
01400 /// If a complex scalar has been passed to a two-element real array
01401 /// (with lower and upper bounds 1 and 2), generate an alternate
01402 /// expression (an ID expression for the complex scalar) which will
01403 /// be used if possible during statement and expression translation.
01404 ///
01405 /// This routine should eventually be extended to generate alternate
01406 /// expressions for complex arrays.
01407 ///
01408 
01409 static Expression *
01410 gen_alternate_expr(VariableSymbol * name_ptr,
01411            Expression & main_expr)
01412 {
01413   if (alternate_expr_valid(name_ptr, main_expr))
01414     return id(main_expr.symbol());
01415   else
01416     return NULL;
01417 }
01418       
01419 /// Fix up alternate expression
01420 
01421 static void
01422 fix_alternate_expr(Statement & s,
01423            ProgramUnit & pgm)
01424 {
01425   static String real_str("REAL");
01426   static String aimag_str("AIMAG");
01427   static String cmplx_str("CMPLX");
01428   static Type real_type(REAL_TYPE, 0);
01429   static Type cmplx_type(COMPLEX_TYPE, 0);
01430 
01431   Expression * intrinsic_parm_expr = NULL;
01432   const char * symbol_name =
01433     s.lhs().intrinsic().symbol().tag_ref();
01434 
01435 /// Grab lhs alternate expression and make a copy of
01436 /// subexpression for lhs (for now, must be IDExpr)
01437 
01438   Mutator<Expression> out_mutr = s.iterate_out_exprs_guarded();
01439   Expression * rhs_alternate_expr = out_mutr.current().grab_right();
01440   Expression * lhs_alternate_expr = rhs_alternate_expr->arg_list()[0].clone();
01441 
01442 /// Replace lhs via mutator (to avoid unnecessary build_refs)
01443 
01444   out_mutr.modify(lhs_alternate_expr);
01445 
01446 /// Pull rhs and build intrinsic around it
01447 
01448   Mutator<Expression> in_mutr = s.iterate_in_exprs_guarded();
01449   Assign<Expression> in_as(in_mutr.assign());
01450   Expression * rhs_expr = in_mutr.pull();
01451 
01452   if (aimag_str==symbol_name) {
01453     /// ...  Create call to "REAL" function
01454     Symbol * opposite_ptr = 
01455       pgm.symtab().find_ref(real_str);
01456     Expression * opposite_id_expr;
01457     if (opposite_ptr)
01458       opposite_id_expr = id(*opposite_ptr);
01459     else
01460       opposite_id_expr = new_intrinsic(real_str, real_type, pgm);
01461     intrinsic_parm_expr = comma(intrinsic_call(opposite_id_expr,
01462                            rhs_alternate_expr),
01463                 rhs_expr);
01464   }
01465   else if (real_str==symbol_name) {
01466     /// ...  Create call to "AIMAG" function
01467     Symbol * opposite_ptr = 
01468       pgm.symtab().find_ref(aimag_str);
01469     Expression * opposite_id_expr;
01470     if (opposite_ptr)
01471       opposite_id_expr = id(*opposite_ptr);
01472     else
01473       opposite_id_expr = new_intrinsic(aimag_str, real_type, pgm);
01474     intrinsic_parm_expr = comma(rhs_expr,
01475                 intrinsic_call(opposite_id_expr,
01476                            rhs_alternate_expr));
01477   }
01478   else
01479     p_abort("Invalid intrinsic function encountered in fix_alternate_expr");
01480 
01481   Expression * intrinsic_id_expr;
01482 
01483 /// Create call to "COMPLX" function
01484   Symbol * intrinsic_ptr = 
01485     pgm.symtab().find_ref(cmplx_str);
01486   if (intrinsic_ptr)
01487     intrinsic_id_expr = id(*intrinsic_ptr);
01488   else
01489     intrinsic_id_expr = new_intrinsic(cmplx_str, cmplx_type, pgm);
01490 
01491 /// Finally, replace rhs with intrinsic function
01492 
01493   in_as = intrinsic_call(intrinsic_id_expr, intrinsic_parm_expr);
01494 
01495 /// Assume that caller will rebuild statement references
01496 }
01497 
01498 /// Make parameter variable and main program expression conformable
01499 
01500 Expression *
01501 InlineObject::make_conformable(VariableSymbol * name_ptr,
01502                    Expression & main_expr)
01503 {
01504     Expression     *main_expr_ptr = &main_expr;
01505     Expression     *test_expr = 0;
01506     bool            non_conformable_flag = false;
01507     Expression     *debug_output = 0;
01508 
01509     if (_debug_flag) {
01510       debug_output = comma();
01511       debug_output->arg_list().ins_first(id(*name_ptr));
01512     }
01513 
01514     /// ...  Check conformability of variables
01515     CONFORM_TYPE    conformable = conformable_test(name_ptr, main_expr,
01516                            non_conformable_flag);
01517 
01518     if (conformable == NON_CONFORMABLE) {
01519 
01520       Expression * equivalent_pair = 
01521         main_expr_ptr = _gen_equivalent_var(name_ptr, main_expr);
01522 
01523       /// ...  If complex passed to real, attempt to generate an alternate
01524       /// ...  expression which avoids use of the equivalence
01525 
01526       if ((main_expr.type().data_type() == COMPLEX_TYPE) &&
01527       (name_ptr->type().data_type() == REAL_TYPE)) {
01528     Expression * alt_expr = gen_alternate_expr(name_ptr,main_expr);
01529     if (alt_expr)
01530       _alternate_map.ins(*name_ptr,alt_expr);
01531       }
01532     
01533       non_conformable_flag = true;
01534       main_expr_ptr = equivalent_pair->arg_list().grab(0);
01535       test_expr = equivalent_pair->arg_list().grab(0);
01536       delete equivalent_pair;
01537       conformable = conformable_test(name_ptr, *main_expr_ptr,
01538                      non_conformable_flag);
01539       p_assert(conformable != NON_CONFORMABLE,
01540            "Call to _gen_equivalent_var failed in make_conformable");
01541     }
01542 
01543     /// ...  Map non-constant references from name to main_name
01544 
01545     if (conformable != TRANSFORMABLE_CONSTANT) {
01546       Symbol & base_symbol = *main_expr_ptr->base_variable_ref();
01547       _symbol_map.ins(*name_ptr, new SymRefElem(base_symbol));
01548       if (_debug_flag)
01549     debug_output->arg_list().ins_last(id(base_symbol));
01550     }
01551 
01552     /// ...  TODO: Handle conformable but different sized character variables
01553     /// ...  properly
01554 
01555     /// ...  Remap transformable references
01556 
01557     /// ...   VariableSymbol *main_name_ptr = NULL;
01558     Expression *main_subs_ptr = NULL;
01559     Expression *main_array_ptr = main_expr_ptr;
01560 
01561     switch (conformable) {
01562     case TRANSFORMABLE_CONSTANT:
01563         {
01564             /// ...  Map references from name to a constant
01565             _constant_map.ins(*name_ptr, *main_expr_ptr);
01566         if (_debug_flag)
01567           debug_output->arg_list().ins_last(main_expr_ptr->clone());
01568             break;
01569         }
01570 
01571     case TRANSFORMABLE_SUBSTRING:
01572     {
01573       // Save substring bounds
01574       _substring_map.ins(*name_ptr, main_expr_ptr->bound().clone());
01575       break;
01576     }
01577 
01578     case TRANSFORMABLE_SUBSTRING_ARRAY:
01579     {
01580 
01581       // Save substring bounds
01582       _substring_map.ins(*name_ptr, main_expr_ptr->bound().clone());
01583 
01584       // Point at the main program array reference
01585 
01586       main_array_ptr = & main_expr_ptr->string();
01587 
01588       // Flow through into TRANFORMABLE_ARRAY code
01589 
01590     }
01591 
01592     case TRANSFORMABLE_ARRAY:
01593         {
01594             /// ...  Map references from name to main_name
01595             VariableSymbol *main_name_ptr 
01596                 = (VariableSymbol *) main_array_ptr->base_variable_ref();
01597 
01598             if (main_array_ptr->op() == ARRAY_REF_OP)
01599                 main_subs_ptr = &main_array_ptr->subscript();
01600 
01601             /// ...  Get the dimension information for each symbol
01602             ArrayDims & name_dim = name_ptr->dim();
01603             int         name_dims = name_dim.entries();
01604 
01605             ArrayDims & main_name_dim = main_name_ptr->dim();
01606             int         main_name_dims = main_name_dim.entries();
01607 
01608             Expression      *lambda_ref = comma();
01609 
01610             if ((main_name_dims>0) && (name_dims == main_name_dims)) {
01611                 Iterator<ArrayBounds> name_iter = name_dim;
01612                 Iterator<ArrayBounds> main_name_iter = main_name_dim;
01613 
01614                 List<Expression>  dummy_list;
01615                 List<Expression> *main_subs_listptr = &dummy_list;
01616 
01617                 if (main_subs_ptr)
01618                     main_subs_listptr = &main_subs_ptr->arg_list();
01619 
01620                 Iterator<Expression> main_subs_iter(*main_subs_listptr);
01621 
01622                 for (int i = 1; i <= name_dims; ++i) {
01623                     Expression     *name_lb = name_iter.current().lower_ref();
01624 
01625                     if (name_lb)
01626                         name_lb = name_lb->clone();
01627                     else
01628                         name_lb = constant(1);
01629 
01630                     Expression *main_name_lb 
01631                         = main_name_iter.current().lower_ref();
01632 
01633                     if (main_name_lb)
01634                         main_name_lb = main_name_lb->clone();
01635                     else
01636                         main_name_lb = constant(1);
01637 
01638                     /// ...  Absorb name_lb, main_name_lb as subexpressions of
01639                     /// ...  main_name_offptr
01640 
01641                     Expression *main_name_offptr = sub(main_name_lb, name_lb);
01642 
01643                     /// ...  If subscript, adjust main_name_offptr and iterate
01644                     /// ...  subscript iterator
01645 
01646                     if (main_subs_ptr) {
01647                         main_name_offptr 
01648                             = add(main_name_offptr,
01649                                   sub(main_subs_iter.current().clone(),
01650                                       main_name_lb->clone()));
01651                         ++main_subs_iter;
01652                     }
01653 
01654             Type main_type = make_type(INTEGER_TYPE);
01655 
01656                     main_name_offptr 
01657                         = add(main_name_offptr,
01658                               new ArgNumberExpr(main_type, i));
01659 
01660                     /// ...  Insert main_name_offptr into lambda ref
01661 
01662                     lambda_ref->arg_list().ins_last(main_name_offptr);
01663 
01664                     /// ...  Increment variable iterators
01665 
01666                     ++name_iter;
01667                     ++main_name_iter;
01668                 }
01669 
01670                 /// ...  Insert lambda call reference into map
01671                 _array_map.ins(*name_ptr, lambda_ref);
01672         if (_debug_flag)
01673           debug_output->arg_list().ins_last(lambda_ref->clone());
01674             }
01675             else if ((main_name_dims == 1) && (name_dims>0)) {
01676                 /// ...  Build a subscript reference for one to many 
01677                 /// ...  dimension case.
01678 
01679                 Expression *subscript_ref = comma();
01680 
01681         Type int_type = make_type(INTEGER_TYPE);
01682 
01683                 for (int i = 1; i <= name_dims; ++i) {
01684                     Expression     *arg_number_ptr 
01685                         = new ArgNumberExpr(int_type, i);
01686 
01687                     /// ...  Insert into subscript_ref
01688                     subscript_ref->arg_list().ins_last(arg_number_ptr);
01689                 }
01690 
01691                 /// ...  Linearize subscript reference
01692 
01693         Expression *linearize_pair = 
01694           _linearize_array_ref(name_ptr, subscript_ref, 
01695                        main_name_ptr);
01696 
01697                 Expression *offset = linearize_pair->arg_list().grab(0);
01698 
01699         delete linearize_pair;
01700 
01701                 /// ...  If subscript on main_name, adjust lambda_ref
01702 
01703                 if (main_subs_ptr) {
01704                     Expression *main_name_lb 
01705                         = main_name_ptr->dim()[0].lower_ref();
01706 
01707                     if (main_name_lb)
01708                         main_name_lb = main_name_lb->clone();
01709                     else
01710                         main_name_lb = constant(1);
01711 
01712                     /// ...  Absorb main_name_lb as subexpresion of offset
01713                     offset = add(offset,
01714                                  sub(main_subs_ptr->arg_list()[0].clone(),
01715                                      main_name_lb));
01716                 }
01717 
01718                 /// ...  Insert offset into lambda ref
01719                 lambda_ref->arg_list().ins_last(offset);
01720 
01721                 /// ...  Insert lambda call reference into map
01722                 _array_map.ins(*name_ptr, lambda_ref);
01723         if (_debug_flag)
01724           debug_output->arg_list().ins_last(lambda_ref->clone());
01725             }
01726             else if (name_dims == 0) {
01727                 if (main_subs_ptr)
01728                     lambda_ref = main_subs_ptr->clone();
01729                 else
01730                     lambda_ref = initial_array_ref(main_name_ptr);
01731 
01732                 /// ...  Insert lambda call reference into map
01733                 _array_map.ins(*name_ptr, lambda_ref);
01734         if (_debug_flag)
01735           debug_output->arg_list().ins_last(lambda_ref->clone());
01736             }
01737         }
01738     default: break;
01739     }
01740 
01741     /// ...  Handle non-conformable case
01742 
01743     if (non_conformable_flag) {
01744 
01745       if (test_expr->op()!=LOGICAL_CONSTANT_OP) {
01746 
01747       /// ...  Insert test expression into list for later assertion
01748 
01749     _test_exprs.ins_last(test_expr);
01750 
01751       }
01752 
01753       else {
01754 
01755     /// ...  Test expression is either irrelevantly true or
01756     /// ...  catastrophically false
01757 
01758     p_assert(strcmp(test_expr->data_ref(),".TRUE.") == 0,
01759          "Illegal subscript alignment detected in make_conformable");
01760     delete test_expr;
01761 
01762       }
01763 
01764       /// ...  Clean up main expression
01765 
01766       delete main_expr_ptr;
01767     }
01768 
01769     return debug_output;
01770 }
01771 
01772 /// Map common blocks between contained pgm and main program
01773 
01774 void 
01775 InlineObject::_remap_common_blocks()
01776 {
01777     /// ...  Iterate over common blocks
01778     for (DictionaryIter<CommonBlock> common_iter = _pgm_ref->common_blocks();
01779                                      common_iter.valid(); ++common_iter) {
01780         /// ...  Check for a corresponding common block in the main program
01781         CommonBlock    &common_local = common_iter.current();
01782         const char     *common_main_tag 
01783             = common_local.name_ref();
01784         CommonBlock    *common_main_ptr 
01785             = _pgm_main.common_blocks().find_ref(common_main_tag);
01786 
01787         if (!common_main_ptr) {
01788 
01789       RefList<Symbol> common_relink_list;
01790 
01791       // Remap individual variables into main program, renaming if
01792       // necessary.
01793 
01794       for (Iterator<Symbol> common_block_iter 
01795            = common_local.iterator();
01796            common_block_iter.valid(); 
01797            ++common_block_iter) {
01798         VariableSymbol & current_symbol =
01799           (VariableSymbol &) common_block_iter.current();
01800 
01801         /// ...  Rename variable to match
01802         Symbol & main_symbol =
01803           rename_variable_to_match(*_pgm_ref, current_symbol,
01804                        _pgm_main, current_symbol.clone_all());
01805 
01806         /// ...  Map current symbol to main program symbol
01807         _symbol_map.ins(current_symbol,
01808                 new SymRefElem(main_symbol));
01809 
01810         /// ...  Put symbol on relink list if unequivalenced
01811 
01812         if (!current_symbol.equivalence_ref())
01813           common_relink_list.ins_last(main_symbol);
01814       }
01815         
01816       // Clone now uncolliding common block and insert it into main
01817       // program (but do not propagate meaningless SAVE to PROGRAM_PU)
01818 
01819       common_main_ptr = new CommonBlock(common_local);
01820       if (common_local.saved() &&
01821           (_pgm_main.pu_class()==PROGRAM_PU_TYPE))
01822         common_main_ptr->saved(0);
01823       _pgm_main.common_blocks().ins(common_main_ptr);
01824 
01825       // Relink pointers in common block
01826 
01827       common_main_ptr->relink_dptrs(_pgm_main);
01828 
01829       // Relink pointers in unequivalenced common block variables
01830 
01831       for (Iterator<Symbol> relink_iter = common_relink_list;
01832            relink_iter.valid(); ++relink_iter)
01833         relink_iter.current().relink_dptrs(_pgm_main);
01834 
01835         }
01836         else {
01837         map_existing_common_block(common_local, common_main_ptr);
01838     }
01839     }
01840 }
01841 
01842 /// Map the variables from a COMMON in a called routine to a COMMON by
01843 /// the same name in a calling routine.
01844 /// COMMON in called routine:    common_local
01845 /// COMMON in calling routine:   common_main_ptr
01846 /// Calling routine:             pgm_main
01847 
01848 void
01849 InlineObject::map_existing_common_block(CommonBlock & common_local, 
01850                     CommonBlock * common_main_ptr)
01851 {
01852     /// ...  There's a similar common block in main pgm, so build
01853     /// ...  common_map and common_main_map and perform overlapping
01854     /// ...  common block processing 
01855 
01856     /// ...  Propagate SAVE if inlining into another subprogram
01857 
01858     if (common_local.saved() &&
01859     (_pgm_main.pu_class()!=PROGRAM_PU_TYPE))
01860     common_main_ptr->saved(1);
01861 
01862     /// ...  Iterate over variables in common blocks
01863     int             common_offset = 0;
01864     int             common_main_offset = 0;
01865 
01866     Iterator<Symbol> common_main_block_iter 
01867     = common_main_ptr->iterator();
01868     VariableSymbol *name_ptr;
01869     VariableSymbol *main_name_ptr 
01870     = (VariableSymbol *) & common_main_block_iter.current();
01871     VariableSizes   common_main_variable_sizes(*main_name_ptr);
01872     
01873     for (Iterator<Symbol> common_block_iter 
01874      = common_local.iterator();
01875      common_block_iter.valid();
01876      ++common_block_iter) {
01877     /// ...  Calculate offset information for contained variable
01878     name_ptr = (VariableSymbol *) & common_block_iter.current();
01879     
01880     VariableSizes   common_variable_sizes(*name_ptr);
01881 
01882     /// ...  If current main pgm variable doesn't overlap the
01883     /// ...  contained variable, look at the next main pgm variable. 
01884 
01885     while (common_main_block_iter.valid() &&
01886            ((common_main_offset>common_offset) ||
01887         (common_main_offset + common_main_variable_sizes.size <=
01888          common_offset))) {
01889         common_main_offset += common_main_variable_sizes.size;
01890         
01891         ++common_main_block_iter;
01892 
01893         if (common_main_block_iter.valid()) {
01894         main_name_ptr 
01895             = (VariableSymbol *) 
01896             &common_main_block_iter.current();
01897         common_main_variable_sizes.remap(*main_name_ptr);
01898         }
01899     }
01900 
01901     /// ...  Fall out of the loop if the main pgm common block runs
01902     /// ...  out; this case will be implemented later.
01903     if (!common_main_block_iter.valid())
01904         break;
01905 
01906     int             var_offset = common_offset - common_main_offset;
01907     Expression     *main_expr_ptr;
01908     Expression     *main_id_ptr = id(*main_name_ptr);
01909 
01910     if (var_offset) {
01911         if ((var_offset % common_main_variable_sizes.elem_size) 
01912         == 0) {
01913         
01914         /// ...  Generate subscript expression
01915         Expression *main_subs_ptr 
01916             = unlinearize_array_ref(main_name_ptr,
01917                         var_offset / common_main_variable_sizes.elem_size);
01918 
01919         /// ...  Absorb ID and subscript expressions into array
01920         /// ...  reference.
01921 
01922         main_expr_ptr 
01923             = array_reference(main_id_ptr, main_subs_ptr);
01924         }
01925         else {
01926 
01927         /// ...  Generate equivalent variable (eventually, attempt
01928         /// ...  to generate an alternate expression here for
01929         /// ...  complex mapped to real)
01930 
01931         Expression *equivalent_pair =
01932             _gen_equivalent_var(name_ptr,*main_id_ptr);
01933         Expression *main_equiv_ptr =
01934             equivalent_pair->arg_list().grab(0);
01935         delete equivalent_pair;
01936 
01937         /// ...  Point at base variable
01938         VariableSymbol *equiv_name_ptr =
01939             (VariableSymbol *) main_equiv_ptr->base_variable_ref();
01940         
01941         /// ...  Delete ID expression because it wasn't absorbed
01942         delete main_id_ptr;
01943 
01944         /// ...  Generate subscript expression
01945         Expression *main_subs_ptr 
01946             = unlinearize_array_ref(equiv_name_ptr,
01947                         var_offset / common_variable_sizes.elem_size);
01948 
01949         /// ...  Absorb ID and subscript expressions into array
01950         /// ...  reference.
01951 
01952         main_expr_ptr 
01953             = array_reference(main_equiv_ptr, main_subs_ptr);
01954 
01955         }
01956     }
01957     else {
01958         main_expr_ptr = main_id_ptr;
01959     }
01960 
01961     /// ...  Make the common block variables conform to one another
01962     Expression * debug_output =
01963         make_conformable(name_ptr, *main_expr_ptr);
01964 
01965     if (debug_output)
01966         delete debug_output;
01967 
01968     /// ...  Delete main program expression
01969     delete main_expr_ptr;
01970 
01971     /// ...  Increment common_offset by size of variable
01972     common_offset += common_variable_sizes.size;
01973     }
01974 }
01975 
01976 /// Map equivalences between contained pgm and main program
01977 
01978 void 
01979 InlineObject::_remap_equivalences()
01980 {
01981     /// ...  Iterate over equivalences
01982 
01983   for (DictionaryIter<Equivalence> equiv_iter = _pgm_ref->equivalences();
01984        equiv_iter.valid(); ++equiv_iter) {
01985     Equivalence & current_equiv = equiv_iter.current();
01986 
01987     Equivalence * pre_main_equiv_ptr = 0;
01988     int pre_main_equiv_bb = 0;
01989     int common_bb = 0;
01990     PRIVAT_TYPE priv_type = PRIVATE;
01991 
01992     /// ...  Search equivalence for common and saved variables.
01993 
01994     for (Iterator<EquivalenceMember> scan_iter = current_equiv.iterator();
01995      scan_iter.valid(); ++scan_iter) {
01996       EquivalenceMember & scan_em = scan_iter.current();
01997       Symbol & scan_symbol = scan_em.symbol();
01998       if(scan_symbol.saved()!=NOT_SAVED) {
01999     priv_type = NOT_PRIVATE;
02000     break;
02001       }
02002       else if(scan_symbol.common_ref()) {
02003     priv_type = NOT_PRIVATE;
02004     SymRefElem * main_symbol_ref =
02005       _symbol_map.find_ref(scan_symbol);
02006     Symbol * main_symbol_ptr = _pgm_main.symtab().find_ref(scan_symbol.name_ref());
02007     p_assert(main_symbol_ptr &&
02008          main_symbol_ref &&
02009          (&(*main_symbol_ref->symref()) == main_symbol_ptr),
02010          "Invalid common symbol in _remap_equivalences");
02011 
02012     /// ...  If conflicting common block with no equivalence for the
02013     /// ...  corresponding top level variable, create an equivalence
02014     /// ...  in top level program and insert corresponding variable
02015     /// ...  into it at byte base 0
02016 
02017     if (!main_symbol_ptr->equivalence_ref()) {
02018       char            label_buff[10];
02019       int             equiv_count = _pgm_main.equivalences().entries();
02020       sprintf(label_buff, "EQ%u", equiv_count+1);
02021       Equivalence * main_equiv_ptr = new Equivalence(label_buff);
02022       _pgm_main.equivalences().rename_and_ins(main_equiv_ptr);
02023       main_equiv_ptr->ins(*main_symbol_ptr, 0);
02024     }
02025 
02026     /// ...  Process common variable differently only if it is in a
02027     /// ...  different equivalence (from a conflicting common block)
02028 
02029     if (main_symbol_ptr->equivalence_ref() != &current_equiv) {
02030       pre_main_equiv_ptr = main_symbol_ptr->equivalence_ref();
02031       common_bb = scan_em.byte_base();
02032       EquivalenceMember * em_ptr =
02033         pre_main_equiv_ptr->find_ref(*main_symbol_ptr);
02034       p_assert(em_ptr,
02035            "Invalid equivalence in _remap_equivalences");
02036       pre_main_equiv_bb = em_ptr->byte_base();
02037     }
02038     break;
02039       }
02040     }
02041 
02042     if (priv_type == PRIVATE)
02043       _private_vars += current_equiv.entries();
02044 
02045     if (pre_main_equiv_ptr) {
02046 
02047       /// ...  Insert variables into equivalence generated by conflicting common
02048       /// ...  block
02049 
02050       for (Iterator<EquivalenceMember> eb_iter = current_equiv.iterator();
02051        eb_iter.valid(); ++eb_iter) {
02052     EquivalenceMember & current_em = eb_iter.current();
02053     Symbol & current_symbol = current_em.symbol();
02054     if (!current_symbol.common_ref()) {
02055       int em_bb = current_em.byte_base();
02056       current_equiv.del(current_symbol);
02057       Symbol & main_symbol =
02058         rename_variable_to_match(*_pgm_ref, current_symbol,
02059                      _pgm_main, current_symbol.clone());
02060       _symbol_map.ins(current_symbol,
02061               new SymRefElem(main_symbol, priv_type));
02062 
02063       // Put into pre-existing equivalence class
02064       pre_main_equiv_ptr->ins(main_symbol,
02065                   em_bb - common_bb + pre_main_equiv_bb);
02066     }
02067       }
02068     }
02069 
02070     else {
02071 
02072       /// ...  Remap non-common variables into main program, renaming if
02073       /// ...  necessary.
02074 
02075       for (Iterator<EquivalenceMember> eb_iter = current_equiv.iterator();
02076        eb_iter.valid(); ++eb_iter) {
02077     EquivalenceMember & current_em = eb_iter.current();
02078     VariableSymbol & current_symbol = (VariableSymbol &) current_em.symbol();
02079 
02080     if (!current_symbol.common_ref()) {
02081 
02082       Symbol & main_symbol =
02083         rename_variable_to_match(*_pgm_ref, current_symbol,
02084                      _pgm_main, current_symbol.clone_all());
02085 
02086       // Map current symbol to main program symbol
02087       _symbol_map.ins(current_symbol,
02088               new SymRefElem(main_symbol, priv_type));
02089     }
02090       }
02091         
02092       /// ...  Clone now uncolliding equivalence block and insert it into main
02093       /// ...  program
02094 
02095       Equivalence & equiv_main =
02096     rename_equivalence_to_match(*_pgm_ref, current_equiv,
02097                     _pgm_main, new Equivalence(current_equiv));
02098 
02099       /// ...  Relink pointers in equivalence block
02100 
02101       equiv_main.relink_dptrs(_pgm_main);
02102 
02103       /// ...  Relink pointers in equivalence block variables
02104 
02105       for (Iterator<EquivalenceMember> relink_iter = equiv_main.iterator();
02106        relink_iter.valid(); ++relink_iter)
02107     relink_iter.current().symbol().relink_dptrs(_pgm_main);
02108 
02109     }
02110 
02111   }
02112 }
02113 
02114 
02115 /// Remap and move data statements from contained pgm to main program,
02116 /// renaming them
02117 
02118 void 
02119 InlineObject::_remap_and_move_data()
02120 {
02121 /// Insert all data statements into main program
02122 
02123   for (Iterator<Data> data_iter = _pgm_ref->data();
02124        data_iter.valid(); ++data_iter) {
02125 
02126     Data *current_data = data_iter.current().clone();
02127 
02128     /// ...  Rename variables in variable list
02129 
02130     Expression & var_list =
02131       CASTAWAY(Expression &) current_data->variable_list();
02132 
02133     for (Mutator<Expression> expr_mutr = var_list.arg_list();
02134      expr_mutr.valid(); ++expr_mutr) {
02135       bool local_expr_flag = false;
02136       Assign<Expression> expr_as(expr_mutr.assign());
02137       expr_as = _translate_symbol_refs_expr(expr_mutr.pull(),
02138                         IN_REF_EXPR,
02139                         local_expr_flag);
02140     }
02141       
02142     /// ...  Insert data statement into main program
02143     
02144     _pgm_main.data().ins_last(current_data);
02145 
02146   }
02147 }
02148 
02149 /// At the call site, remap the uses of each argument in the main program
02150 /// and return the entry point of the routine
02151 
02152 Statement & 
02153 InlineObject::_remap_arg_uses(Statement & s)
02154 {
02155 
02156     Symbol         *entry_name_ptr = 0;
02157 
02158     List<Expression> *actual_ptr = 0;
02159     int actual_entries = 0;
02160     List<Expression> *formal_ptr = 0;
02161     int formal_entries = 0;
02162 
02163     ostrstream *str_ref;
02164     char *data;
02165 
02166     if (s.stmt_class() == CALL_STMT) {
02167         /// ...  CALL statement: find the pointer to the actual list in main
02168         /// ...  pgm and the pointer to the contained entry name symbol
02169 
02170         if (s.parameters_valid())
02171             actual_ptr = &s.parameters_guarded().arg_list();
02172 
02173         entry_name_ptr =
02174       _pgm_ref->symtab().find_ref(s.routine_guarded().symbol().name_ref());
02175     }
02176     else {
02177         /// ...  Function call: find the pointer to the actual list in main
02178         /// ...  pgm, the pointer to the contained entry name sym, and the 
02179         /// ...  pointer to the symbol for the temporary variable to which the 
02180         /// ...  function value is assigned in pgm (cloning it from main pgm)
02181 
02182         if (s.rhs().parameters_valid())
02183       actual_ptr = &s.rhs().parameters_guarded().arg_list();
02184         entry_name_ptr =
02185       _pgm_ref->symtab().find_ref(s.rhs().function().symbol().name_ref());
02186 
02187         /// ...  Map the entry name symbol to the temporary name in main program
02188         _symbol_map.ins(*entry_name_ptr,
02189             new SymRefElem(s.lhs().symbol()));
02190     }
02191 
02192     /// ...  If debugging is on, make debugging output and create beginning and
02193     /// ...  ending comments
02194 
02195     if (_debug_flag) {
02196       str_ref = new ostrstream;
02197       StringElem * comment_line;
02198       const char * rout_tag = entry_name_ptr->tag_ref();
02199       (*str_ref) << " Beginning of call to routine " << rout_tag << '\000';
02200       data = str_ref->str();
02201       comment_line = new StringElem(data);
02202       delete [] data;
02203       delete str_ref;
02204       _begin_comment_list.ins_first(comment_line);
02205       str_ref = new ostrstream;
02206       (*str_ref) << " End of call to routine " << rout_tag << '\000';
02207       data = str_ref->str();
02208       comment_line = new StringElem(data);
02209       delete [] data;
02210       delete str_ref;
02211       _end_comment_list.ins_first(comment_line);
02212     }
02213 
02214     /// ...  Find the entry point and its parameter list
02215     Statement      *entry_point_ptr = NULL;
02216 
02217     for (Iterator<Statement> entry_iter 
02218             = _pgm_ref->stmts().iterate_entry_points();
02219                              entry_iter.valid(); ++entry_iter) {
02220         /// ...  Set c to point to current statement
02221         Statement      *c = &entry_iter.current();
02222 
02223         if ((c->stmt_class() != FLOW_ENTRY_STMT) &&
02224             (entry_name_ptr == &c->routine_guarded().symbol())) {
02225             entry_point_ptr = c;
02226             break;
02227         }
02228     }
02229 
02230     p_assert(entry_point_ptr, "Entry point not found by _remap_arg_uses");
02231 
02232     /// ...  Define the default number of actual and formal entries in each list
02233 
02234     if (actual_ptr)
02235       actual_entries = actual_ptr->entries();
02236 
02237     if (entry_point_ptr->parameters_valid()) {
02238       formal_ptr = &entry_point_ptr->parameters_guarded().arg_list();
02239       formal_entries = formal_ptr->entries();
02240     }
02241 
02242     /// ...  If mismatching numbers of arguments, error
02243 
02244     p_assert(actual_entries==formal_entries,
02245              "Different number of parameters in _remap_arg_uses");
02246 
02247     if (actual_entries) {
02248       /// ...  Build iterators for argument list and parameter list
02249       Iterator<Expression> actual_iter = *actual_ptr;
02250       Iterator<Expression> formal_iter = *formal_ptr;
02251 
02252       while (actual_iter.valid() && formal_iter.valid()) {
02253     /// ...  Point at formal variable and expression in main program
02254     VariableSymbol *name_ptr 
02255       = (VariableSymbol *) formal_iter.current().base_variable_ref();
02256     Expression & main_expr 
02257       = actual_iter.current();
02258 
02259     /// ...  Make them conform to one another
02260     Expression * debug_output =
02261       make_conformable(name_ptr, main_expr);
02262 
02263     /// ...  If debugging on, write comment line about mapping
02264 
02265     if (_debug_flag) {
02266       Iterator<Expression> debug_iter = debug_output->arg_list();
02267       str_ref = new ostrstream;
02268       (*str_ref) << " Dummy parm "
02269              << debug_iter.current(); ++debug_iter;
02270       (*str_ref) << " replaced by actual parm "
02271              << debug_iter.current(); ++debug_iter;
02272       if (debug_iter.valid()) {
02273         (*str_ref) << " (with lambda subexpression " << debug_iter.current()
02274           << ')';
02275       }
02276       (*str_ref) <<  '\000';
02277       data = str_ref->str();
02278       StringElem *comment_line = new StringElem(data);
02279       delete [] data;
02280       delete str_ref;
02281       _begin_comment_list.ins_last(comment_line);
02282       delete debug_output;
02283     }
02284 
02285     /// ...  Increment the iterators
02286 
02287     ++actual_iter;
02288     ++formal_iter;
02289       }
02290     }
02291 
02292     return *entry_point_ptr;
02293 }
02294 
02295 /// Insert a mapping from the formal arg names to the actual
02296 /// arg names for a particular call statement.
02297 /// USED ONLY FOR ACCESS REGION ARGUMENT TRANSLATION.
02298 
02299 void
02300 InlineObject::remap_arg_names(Statement & s)
02301 {
02302 
02303     Symbol         *entry_name_ptr = 0;
02304 
02305     List<Expression> *actual_ptr = 0;
02306     int actual_entries = 0;
02307     List<Expression> *formal_ptr = 0;
02308     int formal_entries = 0;
02309 
02310     /// ...   ostrstream *str_ref;
02311     /// ...   char *data;
02312 
02313     int narrays = 0;
02314     int nreshaped = 0;
02315 
02316     if (s.stmt_class() == CALL_STMT) {
02317         /// ...  CALL statement: find the pointer to the actual list in main
02318         /// ...  pgm and the pointer to the contained entry name symbol
02319 
02320         if (s.parameters_valid())
02321             actual_ptr = &s.parameters_guarded().arg_list();
02322 
02323         entry_name_ptr =
02324       _pgm_ref->symtab().find_ref(s.routine_guarded().symbol().name_ref());
02325     }
02326     else {
02327         /// ...  Function call: find the pointer to the actual list in main
02328         /// ...  pgm, the pointer to the contained entry name sym, and the 
02329         /// ...  pointer to the symbol for the temporary variable to which the 
02330         /// ...  function value is assigned in pgm (cloning it from main pgm)
02331 
02332         if (s.rhs().parameters_valid())
02333       actual_ptr = &s.rhs().parameters_guarded().arg_list();
02334         entry_name_ptr =
02335       _pgm_ref->symtab().find_ref(s.rhs().function().symbol().name_ref());
02336 
02337         /// ...  Map the entry name symbol to the temporary name in main program
02338 ///        _symbol_map.ins(*entry_name_ptr,
02339 //          new SymRefElem(s.lhs().symbol()));
02340     }
02341 
02342     /// ...  Find the entry point and its parameter list
02343     Statement      *entry_point_ptr = NULL;
02344 
02345     for (Iterator<Statement> entry_iter 
02346             = _pgm_ref->stmts().iterate_entry_points();
02347                              entry_iter.valid(); ++entry_iter) {
02348         /// ...  Set c to point to current statement
02349         Statement      *c = &entry_iter.current();
02350 
02351         if ((c->stmt_class() != FLOW_ENTRY_STMT) &&
02352             (entry_name_ptr == &c->routine_guarded().symbol())) {
02353             entry_point_ptr = c;
02354             break;
02355         }
02356     }
02357 
02358     p_assert(entry_point_ptr, "Entry point not found by _remap_arg_uses");
02359 
02360     /// ...  Define the default number of actual and formal entries in each list
02361 
02362     if (actual_ptr)
02363       actual_entries = actual_ptr->entries();
02364 
02365     if (entry_point_ptr->parameters_valid()) {
02366       formal_ptr = &entry_point_ptr->parameters_guarded().arg_list();
02367       formal_entries = formal_ptr->entries();
02368     }
02369 
02370     /// ...  If mismatching numbers of arguments, error
02371 
02372     p_assert(actual_entries==formal_entries,
02373              "Different number of parameters in _remap_arg_uses");
02374 
02375     if (actual_entries) {
02376 
02377       /// ...  Build iterators for argument list and parameter list
02378       Iterator<Expression> actual_iter = *actual_ptr;
02379       Iterator<Expression> formal_iter = *formal_ptr;
02380 
02381       /// ...  Prepare the formal-actual mapping.
02382 
02383       while (actual_iter.valid() && formal_iter.valid()) {
02384       // Point at formal variable and expression in main program
02385       VariableSymbol *formal_symbol 
02386           = (VariableSymbol *) formal_iter.current().base_variable_ref();
02387       Expression & current_expr 
02388           = actual_iter.current();
02389 //    VariableSymbol *actual_symbol 
02390 //        = (VariableSymbol *) current_expr.base_variable_ref();
02391 
02392       Expression * actual_expr=0;
02393       AbstractAccess * aa;
02394 
02395       if ((current_expr.op() == FUNCTION_CALL_OP) && 
02396           (strcmp(current_expr.arg_list()[0].symbol().name_ref(), "<BETA>") == 0)) {
02397           
02398           /// ...  This must be in GSA form!  CALL x(<beta>(ALPHA(,input),output), ... )
02399 
02400           if (current_expr.arg_list()[1].arg_list()[0].op() == ALPHA_OP) {
02401 
02402           actual_expr = current_expr.arg_list()[1].arg_list()[0].arg_list()[1].arg_list()[0].clone();
02403           aa = compute_abstract_access(*actual_expr,
02404                            &s, 
02405                            AR_READWRITE);
02406           } else {
02407           p_abort("Unexpected form of BETA function");
02408           }
02409       } else {
02410           actual_expr = current_expr.clone();
02411           aa = compute_abstract_access( *actual_expr, &s, AR_READWRITE );
02412       }
02413       
02414       _insert_arg_mapping(*formal_symbol, actual_expr, aa);
02415       // Add mapping to InlineObject
02416 
02417       // If the actual_expr is not either an ArrayRefExpr or an IDExpr,
02418       // forget it.
02419 
02420       if ((actual_expr->op() == ARRAY_REF_OP) ||
02421           (actual_expr->op() == ID_OP)) {
02422           
02423           _symbol_map.ins(*formal_symbol,
02424                   new SymRefElem(*(actual_expr->base_variable_ref())));
02425       }
02426 
02427       // Increment the iterators
02428 
02429       ++actual_iter;
02430       ++formal_iter;
02431       }
02432 
02433       /// ...  Check for reshaping, if required
02434 
02435       if (_ar_reshape) {
02436       actual_iter.reset();
02437       formal_iter.reset();
02438       while (actual_iter.valid() && formal_iter.valid()) {
02439           /// ...  Point at formal variable and expression in main program
02440           VariableSymbol *formal_symbol 
02441           = (VariableSymbol *) formal_iter.current().base_variable_ref();
02442           Expression & current_expr 
02443           = actual_iter.current();
02444           VariableSymbol *actual_symbol 
02445           = (VariableSymbol *) current_expr.base_variable_ref();
02446 
02447           /// ...  If both actual and formal are arrays, then check for reshaping
02448 
02449           if (_ar_reshape && actual_symbol &&
02450           formal_symbol->is_array() && actual_symbol->is_array()) {
02451 
02452           narrays++;  /// ...  Found both are arrays.
02453 
02454           for (int i=0; i<formal_symbol->dim().entries()-1; i++) {
02455 
02456               if (i>actual_symbol->dim().entries()-1) {
02457               nreshaped++;
02458               if (_ar_reshape == 2) {
02459                   ostrstream str1;
02460                   ostrstream str2;
02461                   str1 << convert_case(formal_symbol->name_ref());
02462                   str2 << convert_case(actual_symbol->name_ref());
02463                   formal_symbol->dim().print(str1);
02464                   actual_symbol->dim().print(str2);
02465                   str1 << '\000';
02466                   str2 << '\000';
02467                   char *data1 = str1.str();
02468                   char *data2 = str2.str();
02469                   cout << "RESHAPING: " << data2 << " to " << data1 << endl;
02470               }  
02471               break;
02472               }
02473 
02474               ArrayBounds & actual_bounds = actual_symbol->dim()[i];
02475               ArrayBounds & formal_bounds = formal_symbol->dim()[i];
02476 
02477               Expression * act_lo;
02478               Expression * form_lo;
02479               Expression * act_num_elems;
02480               Expression * form_num_elems;
02481 
02482               if (!(actual_bounds.lower_exists())) {
02483               act_lo = constant(1);
02484               } else {
02485               act_lo = actual_bounds.lower_guarded().clone();
02486               }
02487 
02488               if (!actual_bounds.upper_exists()) {
02489               nreshaped++;
02490               ostrstream str1;
02491               ostrstream str2;
02492               str1 << convert_case(formal_symbol->name_ref());
02493               str2 << convert_case(actual_symbol->name_ref());
02494               formal_symbol->dim().print(str1);
02495               actual_symbol->dim().print(str2);
02496               str1 << '\000';
02497               str2 << '\000';
02498               char *data1 = str1.str();
02499               char *data2 = str2.str();
02500               cout << "RESHAPING: " << data2 << " to " << data1 << endl;
02501               delete act_lo;
02502               break;
02503               }
02504 
02505               act_num_elems = simplify(add(sub(actual_bounds.upper_guarded().clone(),
02506                                act_lo),
02507                            constant(1)));
02508 
02509               if (!(formal_bounds.lower_exists())) {
02510               form_lo = constant(1);
02511               } else {
02512               form_lo = formal_bounds.lower_guarded().clone();
02513               }
02514 
02515               Expression * upper_expr;
02516 
02517               /// ...  If the declared upper bound of the formal is a variable,
02518               /// ...  which is also a parameter, substitute the actual expression
02519               /// ...  for the variable.
02520               Expression & upper = formal_bounds.upper_guarded();
02521 
02522               if ((upper.op() == ID_OP) && (upper.symbol().formal())) {
02523               upper_expr = actual_arg(upper.symbol())->clone();
02524               } else {
02525               upper_expr = formal_bounds.upper_guarded().clone();
02526               }
02527 
02528               form_num_elems = simplify(add(sub(upper_expr, form_lo),
02529                             constant(1)));
02530 
02531               Expression * diff = simplify(sub(form_num_elems,act_num_elems));
02532 
02533               if (!is_integer_zero(*diff)) {
02534               nreshaped++;
02535               ostrstream str1;
02536               ostrstream str2;
02537               str1 << convert_case(formal_symbol->name_ref());
02538               str2 << convert_case(actual_symbol->name_ref());
02539               formal_symbol->dim().print(str1);
02540               actual_symbol->dim().print(str2);
02541               str1 << '\000';
02542               str2 << '\000';
02543               char *data1 = str1.str();
02544               char *data2 = str2.str();
02545               cout << "RESHAPING: " << data2 << " to " << data1 << endl;
02546               delete diff;
02547               break;
02548               } else {
02549               delete diff;
02550               }
02551           }
02552           }
02553 
02554           /// ...  Increment the iterators
02555 
02556           ++actual_iter;
02557           ++formal_iter;
02558       }
02559       }
02560   }
02561     if (_ar_reshape) {
02562     cout << "CALL: " << actual_entries << " params " << narrays << " arrays " << nreshaped << " reshaped" << endl;
02563     }
02564 }
02565 
02566 
02567 /// At the call site in the main program, precalculate an expression
02568 /// if it does not map 1-1 in the subroutine.
02569 
02570 static Expression *
02571 remap_args_precalc_expr(StmtInfo & arg_map,
02572             Expression * expr)
02573 {
02574 
02575   switch (expr->op()) {
02576 
02577   case INTEGER_CONSTANT_OP:
02578   case REAL_CONSTANT_OP:
02579   case LOGICAL_CONSTANT_OP:
02580   case ID_OP:
02581     break;
02582 
02583   case ARRAY_REF_OP:
02584     {
02585       /// ...  Traverse array subscripts
02586       for (Mutator<Expression> subs_mutr = expr->subscript().arg_list();
02587        subs_mutr.valid(); ++subs_mutr) {
02588     Expression & current_subs = subs_mutr.current();
02589 
02590     if (current_subs.op() != INTEGER_CONSTANT_OP) {
02591       Assign<Expression> subs_as(subs_mutr.assign());
02592       subs_as = get_precalc(subs_mutr.pull(),
02593                 *arg_map.program_ref,
02594                 *arg_map.stmt_ref,
02595                 PRECALC_ALWAYS, "PC");
02596     }
02597       }
02598       break;
02599     }
02600 
02601 
02602   case SUBSTRING_OP:
02603     {
02604 
02605       /// ...  Store bound list
02606 
02607       List<Expression> & bound_list = expr->bound().arg_list();
02608       int bound_entries = bound_list.entries();
02609 
02610       /// ...  Remember length of base character expression
02611 
02612       int base_len = expr->string().base_variable_ref()->type().size();
02613 
02614       switch (bound_list[0].op()) {
02615 
02616       case INTEGER_CONSTANT_OP:
02617     break;
02618       case OMEGA_OP:
02619     {
02620       bound_list.del(0);
02621       bound_list.ins_first(constant(1));
02622       break;
02623     }
02624       default: {
02625     Assign<Expression> bound_as(bound_list.assign(0));
02626     bound_as = get_precalc(bound_list.pull(0),
02627                    *arg_map.program_ref,
02628                    *arg_map.stmt_ref,
02629                    PRECALC_ALWAYS, "PC");
02630       }
02631       }
02632 
02633       if (bound_entries==2)
02634     switch (bound_list[1].op()) {
02635 
02636     case INTEGER_CONSTANT_OP:
02637       break;
02638     case OMEGA_OP:
02639       {
02640         bound_list.del(1);
02641         bound_list.ins_last(constant(base_len));
02642         break;
02643       }
02644     default: {
02645       Assign<Expression> bound_as(bound_list.assign(1));
02646       bound_as = get_precalc(bound_list.pull(1),
02647                  *arg_map.program_ref,
02648                  *arg_map.stmt_ref,
02649                  PRECALC_ALWAYS, "PC");
02650     }
02651     }
02652 
02653       else
02654 
02655     /// ...  Increase length of bound_list by adding an explicit upper bound
02656     /// ...  for the string
02657 
02658     bound_list.ins_last(constant(base_len));
02659 
02660       /// ...  Precalculate string part of substring if need be
02661 
02662       expr->left(remap_args_precalc_expr(arg_map,expr->grab_left()));
02663       break;
02664     }
02665 
02666   default:
02667     expr = get_precalc(expr,
02668                *arg_map.program_ref,
02669                *arg_map.stmt_ref,
02670                PRECALC_ALWAYS, "PC");
02671   }
02672 
02673   return expr;
02674 
02675 }
02676 
02677 /// At the call site in the main program, precalculate any expressions
02678 /// which do not map 1-1 in the subroutine.
02679 
02680 static Statement *
02681 remap_args_precalc(ProgramUnit & pgm_main,
02682            Statement & s)
02683 {
02684     Statement      *prev_stmt_ref = s.prev_ref();
02685     Expression     *arglist_ptr = 0;
02686 
02687     /// ...  Find the argument list
02688 
02689     switch (s.stmt_class()) {
02690     case CALL_STMT:
02691         {
02692             if (s.parameters_valid())
02693                 arglist_ptr = &s.parameters_guarded();
02694             else
02695                 return &s;
02696             break;
02697         }
02698 
02699     case ASSIGNMENT_STMT:
02700         {
02701             if ((s.rhs().op() == FUNCTION_CALL_OP) &&
02702                 (s.rhs().parameters_valid()))
02703                 arglist_ptr = &(s.rhs().parameters_guarded());
02704             else
02705                 return &s;
02706             break;
02707         }
02708 
02709     default:
02710         return &s;
02711     }
02712 
02713     /// ...  Set up argument map for precalculation
02714     StmtInfo        arg_map;
02715 
02716     arg_map.program_ref = &pgm_main;
02717     arg_map.stmt_ref = &s;
02718 
02719     /// ...  Iterate over the arguments
02720     for (Mutator<Expression> arg_mutr = arglist_ptr->arg_list();
02721                               arg_mutr.valid(); ++arg_mutr) {
02722       Assign<Expression> expr_as(arg_mutr.assign());
02723       expr_as = remap_args_precalc_expr(arg_map, arg_mutr.pull());
02724     }
02725 
02726     /// ...  Recalculate flow information after possible precalculations
02727 
02728     s.build_refs();
02729 
02730     if (prev_stmt_ref)
02731         return prev_stmt_ref->next_ref();
02732     else
02733         return pgm_main.stmts().first_ref();
02734 }
02735 
02736 /// Precalculate function call
02737 
02738 static Expression     *
02739 precalc_func_call(Expression * e, ExtraInfo & extra_info)
02740 {
02741     StmtInfo & arg_map = *((Info<StmtInfo * >&) extra_info).data();
02742 
02743     return get_precalc(e->clone(), *arg_map.program_ref, *arg_map.stmt_ref,
02744                PRECALC_ALWAYS, "PC");
02745 }
02746 
02747 /// Precalculate all function calls which are not subexpressions of
02748 /// a do expr via a call to replace (to insure postorder precalculation)
02749 
02750 /// Replace a do expr with itself to prevent further checking of its
02751 /// subexpressions
02752 
02753 static Expression     *
02754 precalc_non_do_expr(Expression * e, ExtraInfo & extra_info)
02755 {
02756   static AnyOfType func_call_pattern(FUNCTION_CALL_OP);
02757 
02758   if (e->op() == FUNCTION_CALL_OP)
02759     return replace(e, func_call_pattern, precalc_func_call,
02760            extra_info, NON_RECURSIVE_REPLACE,
02761            POSTORDER_REPLACE);
02762   else
02763     return e;
02764 
02765 }
02766 
02767 /// Clean up statement
02768 
02769 static Statement &
02770 clean_statement(ProgramUnit & pgm,
02771         Statement & s)
02772 {
02773 /// Static patterns
02774   static AnyOfType func_call_pattern(FUNCTION_CALL_OP);
02775   static StmtInfo arg_map;
02776 
02777   Statement      *prev_stmt_ref = s.prev_ref();
02778   STMT_TYPE       stype = s.stmt_class();
02779 
02780   arg_map.program_ref = &pgm;
02781   arg_map.stmt_ref = &s;
02782 
02783   switch (stype) {
02784 
02785   case ASSIGNMENT_STMT: {
02786 
02787     /// ...  If assignment statement is already in a suitable form (ID_OP on
02788     /// ...  LHS), look for FUNCTION_CALL_OP only in RHS arguments (if any)
02789 
02790     if (s.lhs().op() == ID_OP) {
02791       for (Mutator<Expression> expr_mutr = s.rhs().arg_list();
02792        expr_mutr.valid(); ++expr_mutr) {
02793     Info<StmtInfo *> inf(&arg_map);
02794     Assign<Expression> expr_as(expr_mutr.assign());
02795     expr_as = replace(expr_mutr.pull(),
02796               func_call_pattern,
02797               precalc_func_call, inf,
02798               NON_RECURSIVE_REPLACE,
02799               POSTORDER_REPLACE);
02800       }
02801     }
02802     /// ...  If assignment statement with non ID-OP on LHS,
02803     /// ...  look for FUNCTION_CALL_OP everywhere
02804     else {
02805       for (Mutator<Expression> expr_mutr = s.iterate_expressions();
02806        expr_mutr.valid(); ++expr_mutr) {
02807     Info<StmtInfo *> inf(&arg_map);
02808     Assign<Expression> expr_as(expr_mutr.assign());
02809     expr_as = replace(expr_mutr.pull(),
02810               func_call_pattern,
02811               precalc_func_call, inf,
02812               NON_RECURSIVE_REPLACE,
02813               POSTORDER_REPLACE);
02814       }
02815     }
02816     break;
02817   }
02818 
02819   case READ_STMT:
02820   case WRITE_STMT:
02821   case PRINT_STMT: {
02822 
02823     /// ...  Look for DO_OP and FUNCTION_CALL_OP, and do not search for
02824     /// ...  FUNCTION_CALL_OP within a DO_OP
02825 
02826     static WildcardOr * full_pattern =
02827       new WildcardOr(new AnyOfType(FUNCTION_CALL_OP),
02828              new AnyOfType(DO_OP));
02829                                       
02830     for (Mutator<Expression> expr_mutr = s.iterate_expressions();
02831      expr_mutr.valid(); ++expr_mutr) {
02832       Info<StmtInfo *> inf(&arg_map);
02833 
02834       Assign<Expression> expr_as(expr_mutr.assign());
02835       expr_as = replace(expr_mutr.pull(),
02836             *full_pattern,
02837             precalc_non_do_expr, inf,
02838             NON_RECURSIVE_REPLACE,
02839             PREORDER_REPLACE);
02840     }
02841     break;
02842   }
02843 
02844   default: {
02845 
02846     /// ...  Look for FUNCTION_CALL_OP everywhere
02847 
02848     for (Mutator<Expression> expr_mutr = s.iterate_expressions();
02849      expr_mutr.valid(); ++expr_mutr) {
02850       Info<StmtInfo *> inf(&arg_map);
02851       Assign<Expression> expr_as(expr_mutr.assign());
02852       expr_as = replace(expr_mutr.pull(),
02853             func_call_pattern,
02854             precalc_func_call, inf,
02855             NON_RECURSIVE_REPLACE,
02856             POSTORDER_REPLACE);
02857     }
02858   }
02859   }
02860 
02861 /// Point at first statement after function call precalculation
02862   Statement      *first_stmt_ref;
02863 
02864   if (prev_stmt_ref)
02865     first_stmt_ref = prev_stmt_ref->next_ref();
02866   else
02867     first_stmt_ref = &s;
02868 
02869   RefSet<Statement> processed_stmts;
02870 
02871 /// Iterate until earliest precalculation statement is known
02872 
02873   do {
02874     processed_stmts.ins(*first_stmt_ref);
02875     first_stmt_ref = remap_args_precalc(pgm, *first_stmt_ref);
02876   }
02877   while (!processed_stmts.member(*first_stmt_ref));
02878 
02879 /// Perform more processing if any precalculation statements generated
02880 
02881   if (first_stmt_ref != &s) {
02882 
02883     /// ...  Iterate until there are no more statements to process
02884 
02885     Statement * stmt_ref = first_stmt_ref->next_ref();
02886 
02887     while (stmt_ref != &s) {
02888 
02889       while (!processed_stmts.member(*stmt_ref)) {
02890     processed_stmts.ins(*stmt_ref);
02891     stmt_ref = remap_args_precalc(pgm, *stmt_ref);
02892       }
02893       stmt_ref = stmt_ref->next_ref();
02894     }
02895 
02896     /// ...  If need be, rebuild references on original statement
02897 
02898     if (!processed_stmts.member(s))
02899       s.build_refs();
02900 
02901   }
02902 
02903 /// Point to first precalculation statement generated
02904 
02905   return *first_stmt_ref;
02906 }
02907 
02908 /// Clean up program variables
02909 
02910 static void
02911 clean_variables(ProgramUnit & pgm)
02912 {
02913   List<StringElem> rename_list;
02914 
02915   for (DictionaryIter<Symbol> sym_iter = pgm.symtab().iterator();
02916        sym_iter.valid(); ++ sym_iter) {
02917 
02918       Symbol & current_symbol = sym_iter.current();
02919 
02920       switch (current_symbol.sym_class()) {
02921 
02922       case VARIABLE_CLASS:
02923       case SYMBOLIC_CONSTANT_CLASS: {
02924 
02925       const char     *current_tag = current_symbol.name_ref();
02926       if(lookup_intrinsic(current_tag))
02927           rename_list.ins_last(new StringElem(current_tag));
02928       }
02929       default: break;
02930       }
02931   }
02932 
02933   for (Iterator<StringElem> rename_iter = rename_list;
02934        rename_iter.valid(); ++rename_iter) {
02935 
02936     Symbol * symbol_ptr = pgm.symtab().grab(rename_iter.current());
02937     pgm.symtab().rename_and_ins(symbol_ptr);
02938   }
02939 }
02940 
02941 /// Work routine for counting executable statements
02942 
02943 int
02944 count_stmt(Statement & stmt,
02945        int stmt_counter)
02946 {
02947   switch (stmt.stmt_class()) {
02948   case UNDEFINED_STMT:
02949   case IMPLIED_GOTO_STMT:
02950   case FLOW_ENTRY_STMT:
02951   case FLOW_EXIT_STMT:
02952   case BLOCK_ENTRY_STMT:
02953   case BLOCK_EXIT_STMT:
02954   case ENTRY_STMT:
02955   case LABEL_STMT:
02956   case ALLOCATE_STMT:
02957   case DEALLOCATE_STMT:
02958   case NULLIFY_STMT:
02959   case DIRECTIVE_STMT:
02960   case STMT_PTR:
02961       return stmt_counter;
02962   default: break;
02963   }
02964   return ++stmt_counter;
02965 }
02966 
02967 /// Count executable statements
02968 
02969 static int
02970 count_stmts(Iterator<Statement> stmt_iter)
02971 {
02972   int executable_stmts = 0;
02973   for (; stmt_iter.valid(); ++stmt_iter)
02974     executable_stmts = count_stmt(stmt_iter.current(), executable_stmts);
02975   return executable_stmts;
02976 }
02977 
02978 /// Clean program for inlining, counting statements and creating a
02979 /// workspace for program if requested
02980 
02981 void
02982 clean_program(ProgramUnit & pgm, Element<InlineWorkSpace> & ws_ref)
02983 {
02984     clean_variables(pgm);
02985     int executable_stmts = 0;
02986     for (Iterator<Statement> stmt_iter = pgm.stmts().iterator();
02987      stmt_iter.valid(); ++stmt_iter) {
02988     Statement & current_stmt = stmt_iter.current();
02989     if (ws_ref->count_active())
02990         executable_stmts = count_stmt(current_stmt, executable_stmts);
02991     Statement & first_precalc_stmt = 
02992         clean_statement(pgm, current_stmt);
02993 
02994     if (&first_precalc_stmt != &current_stmt) {
02995       
02996         /// ...  Check for assertions to propagate onto other
02997         /// ...  statements
02998 
02999         RefList<Assertion> assertlist;
03000 
03001         for (Iterator<Assertion> assert_iter = current_stmt.assertions();
03002          assert_iter.valid(); ++ assert_iter) {
03003         Assertion & current_assert = assert_iter.current();
03004         AssertionType current_type = current_assert.type();
03005         /// ...  added AS_RECURSIVEINLINE (kjackson)
03006         if ((current_type == AS_INLINE) ||
03007             (current_type == AS_RECURSIVEINLINE) ||
03008             (current_type == AS_NOINLINE) ||
03009             (current_type == AS_SIDE_EFFECT_FREE)) {
03010             assertlist.ins_last(current_assert);
03011             break;
03012         }
03013         }
03014 
03015         int entries = assertlist.entries();
03016 
03017         if (entries > 0 || ws_ref->count_active()) {
03018 
03019         /// ...  Go through precalculation statements
03020         
03021         for (Iterator<Statement> prop_iter =
03022              pgm.stmts().iterator(first_precalc_stmt,
03023                       *current_stmt.prev_ref());
03024              prop_iter.valid(); ++prop_iter) {
03025             Statement & prop_stmt = prop_iter.current();
03026             /// ...  Count statements if requested
03027             if (ws_ref->count_active())
03028             executable_stmts = count_stmt(prop_stmt, executable_stmts);
03029             /// ...  Propagate assertion onto any precalculated
03030             /// ...  function calls
03031             if (entries > 0) {
03032             for (Iterator<Assertion> assertion_iter = assertlist; 
03033                  assertion_iter.valid();
03034                  ++assertion_iter) {
03035                 if ((prop_stmt.stmt_class()==ASSIGNMENT_STMT) &&
03036                 (prop_stmt.rhs().op()==FUNCTION_CALL_OP))
03037                 prop_stmt.assertions().ins_last(assertion_iter.current().clone());
03038             }
03039             }
03040         }
03041     
03042         /// ...  Remove original assertion if it no longer pertains
03043 
03044         if (entries > 0) {
03045 
03046             for (Iterator<Assertion> assert_iter = assertlist;
03047              assert_iter.valid();
03048              ++assert_iter) {
03049             
03050             /// ...  AssertionType this_type = assert_iter.current().type();
03051                 /// ...  added AS_RECURSIVEINLINE (kjackson, Hao)
03052             if ((assert_iter.current().type() == AS_INLINE) ||
03053                     (assert_iter.current().type() == AS_RECURSIVEINLINE) ||
03054                 (assert_iter.current().type() == AS_NOINLINE)) {
03055                 STMT_TYPE stype = current_stmt.stmt_class();
03056 
03057                 if (stype == CALL_STMT)
03058                 continue;
03059                 if ((stype != ASSIGNMENT_STMT) ||
03060                 current_stmt.rhs().op() != FUNCTION_CALL_OP)
03061                 current_stmt.assertions().del(assert_iter.current());
03062             } else {
03063                 current_stmt.assertions().del(assert_iter.current());
03064             }
03065             }
03066         }
03067         }
03068     }
03069     }
03070 
03071 /// Create inline workspace to store line count if requested
03072   if (ws_ref->count_active()) {
03073     int total_stmts = pgm.stmts().entries();
03074     pgm.work_stack().push(new InlineWorkSpace(*ws_ref,
03075                           executable_stmts,
03076                           total_stmts));
03077     const char * routine_name_ref = pgm.routine_name_ref();
03078     const char * null_name_ref = "NULL";
03079     cout << "Routine " << (routine_name_ref ? routine_name_ref : null_name_ref)
03080       << ": <" << executable_stmts << ", " << total_stmts << ">\n";
03081     int exec_routine_count =
03082       InlineWorkSpace::exec_routine_count() + 1;
03083     InlineWorkSpace::exec_routine_count(exec_routine_count);
03084     int total_routine_count =
03085       InlineWorkSpace::total_routine_count() + 1;
03086     InlineWorkSpace::total_routine_count(total_routine_count);
03087     int exec_line_count =
03088       InlineWorkSpace::exec_line_count() + executable_stmts;
03089     InlineWorkSpace::exec_line_count(exec_line_count);
03090     int total_line_count =
03091       InlineWorkSpace::total_line_count() + total_stmts;
03092     InlineWorkSpace::total_line_count(total_line_count);
03093   }
03094 }
03095 
03096 /// Clean up program after inlining
03097 
03098 void
03099 cleanup_program(ProgramUnit & pgm)
03100 {
03101 
03102   static String dc_debug_switch("dead_debug");
03103 
03104 /// Build list of candidate precalculation variables
03105 
03106   RefSet<Symbol> candidate_set;
03107 
03108   for (DictionaryIter<Symbol> symbol_iter = pgm.symtab().iterator();
03109        symbol_iter.valid(); ++symbol_iter) {
03110 
03111     Symbol & current_symbol = symbol_iter.current();
03112     const Type & current_type = current_symbol.type();
03113 
03114     if ((current_type.data_type() == INTEGER_TYPE) &&
03115     (current_type.is_scalar()) &&
03116     (strncmp(current_symbol.name_ref(),"PC",2) == 0))
03117       candidate_set.ins(current_symbol);
03118   }
03119 
03120   if (candidate_set.entries()) {
03121 
03122     /// ...  Propagate the candidate variables if possible
03123 
03124     propagate_constants(pgm, candidate_set, REMOVE_UNREACH_CODE);
03125 
03126     /// ...  Accept small substitutions
03127 
03128     expand_small_substituted(pgm);
03129 
03130     /// ...  Clear any leftover substitutions
03131 
03132     clear_substituted(pgm);
03133 
03134   }
03135 
03136 /// Deadcode the program
03137 
03138   eliminate_dead_code(pgm, DONT_DEADCODE_ARRAYS,
03139               switch_value(dc_debug_switch));
03140 
03141 }
03142 
03143 /// Simplify the array reference and substring expressions within an
03144 /// expression
03145 
03146 static Expression *
03147 simplify_subs_exprs(Expression * expr)
03148 
03149 {
03150 
03151   switch (expr->op()) {
03152 
03153   case ARRAY_REF_OP:
03154   case SUBSTRING_OP:
03155 
03156     /// ...  Simplify array reference or substring expressions
03157 
03158     return simplify(expr);
03159 
03160   default:
03161 
03162     /// ...  Traverse subexpressions and replace any which are relevant
03163     for (Mutator<Expression> expr_mutr = expr->arg_list();
03164      expr_mutr.valid(); ++expr_mutr) {
03165       Assign<Expression> expr_as(expr_mutr.assign());
03166       expr_as = simplify_subs_exprs(expr_mutr.pull());
03167     }
03168   }
03169   return expr;
03170 }
03171 
03172 /// Translate symbol references within the range of an Expression
03173 /// mutator using the symbol, array, constant and substring maps,
03174 /// returning a count of the number of modifications
03175 
03176 int
03177 InlineObject::_translate_symbol_refs_mutr(Mutator<Expression> expr_mutr,
03178                       LambdaInfo & lambda,
03179                       REF_TYPE ref)
03180 {
03181   int modify_counter = 0;
03182 
03183   for (; expr_mutr.valid(); ++expr_mutr) {
03184 
03185     int local_modify_counter = 0;
03186 
03187     /// ...  Remove expression from arg list
03188 
03189     Assign<Expression> ex_as(expr_mutr.assign());
03190     Expression * ex = expr_mutr.pull();
03191 
03192     /// ...  Substitute expression until fixed point
03193 
03194     local_modify_counter = remap_expr( &ex, lambda, ref );
03195 
03196     /// ...  If it was replaced before, accumulate counter and
03197     /// ...  simplify the array refs within the expression
03198 
03199     if (local_modify_counter) {
03200       modify_counter += local_modify_counter;
03201       ex = simplify_subs_exprs(ex);
03202     }
03203 
03204     /// ...  Put expression back into arg list
03205 
03206     ex_as = ex;
03207   }
03208 
03209   return modify_counter;
03210 }
03211 
03212 /// Take an expression and map the variables in it from the called routine into
03213 /// the caller routine.
03214 
03215 int
03216 InlineObject::remap_expr( Expression ** ex, LambdaInfo & lambda, REF_TYPE ref ) const
03217 {
03218     int local_modify_counter = 0;
03219  
03220     while (1) {
03221       /// ...  Nothing replaced so far
03222       bool local_expr_flag = false;
03223 
03224       *ex = _translate_symbol_refs_expr(*ex, ref, local_expr_flag, 
03225                        &(this->_formal_to_actual));
03226 
03227       /// ...  If this expression was replaced, remove lambda
03228       /// ...  calls and check the expression again.
03229 
03230       if (local_expr_flag) {
03231     ++local_modify_counter;
03232     *ex = remove_lambda_calls(*ex, lambda);
03233       }
03234       else
03235     break;
03236     }
03237     return local_modify_counter;
03238 }
03239 
03240 /// Translate formal parameter references (doing simple symbol
03241 /// replacement)
03242 ///
03243 /// This member function should only be called when doing equivalence
03244 /// normalization for formal parameters
03245 
03246 void
03247 InlineObject::_translate_symbol_refs_entry(LambdaInfo & lambda)
03248 {
03249   Statement & s = *lambda.stmt_ref;
03250 ///  Statement * prev_stmt_ref = s.prev_ref();
03251 
03252 /// Iterate over any expressions in an assertion
03253 /// (note: do not keep track of assertion modifications,
03254 /// because they do not require any cleanup processing)
03255 
03256   for (Iterator<Assertion> assert_iter = s.assertions();
03257        assert_iter.valid(); ++assert_iter) {
03258 
03259     Assertion & current_assert = assert_iter.current();
03260     /// ...    AssertionType current_type = current_assert.type();
03261 
03262     if (current_assert.arg_list_valid()) {
03263       _translate_symbol_refs_mutr(Mutator<Expression>(current_assert.arg_list_guarded()),
03264                   lambda, IN_REF_EXPR);
03265     }
03266   }
03267 
03268 /// Iterate over the formal parameters (if any)
03269   
03270   if (s.parameters_valid()) {
03271     bool modify_flag = false;
03272     for (Iterator<Expression> expr_iter = s.parameters_guarded().arg_list();
03273      expr_iter.valid(); ++expr_iter) {
03274       Expression & expr = expr_iter.current();
03275       p_assert(expr.op() == ID_OP,
03276            "Invalid parameter encountered in _translate_symbol_refs_entry_");
03277       SymRefElem *symbol_ref
03278     = _symbol_map.find_ref(expr.symbol());
03279       if (symbol_ref) {
03280     /// ...  Modify original expression in place
03281     modify_flag = true;
03282     expr.symbol(*symbol_ref->symref());
03283       }
03284     }
03285     if (modify_flag)
03286       s.build_refs();
03287   }
03288   return;
03289 }
03290 
03291 /// Translate symbol references within a statement's expression list using
03292 /// the symbol, array, constant and substring maps.
03293 
03294 void 
03295 InlineObject::_translate_symbol_refs_stmt(LambdaInfo & lambda,
03296                                           TRANS_CLEANUP_TYPE cleanup)
03297 {
03298     Statement & s = *lambda.stmt_ref;
03299     Statement * prev_stmt_ref = s.prev_ref();
03300 
03301     /// ...  Iterate over all statement expressions
03302     bool modify_flag = false;
03303 
03304     /// ...  Iterate over any expressions in an assertion
03305     /// ...  (note: do not keep track of assertion modifications,
03306     /// ...  because they do not require any cleanup processing)
03307 
03308     for (Iterator<Assertion> assert_iter = s.assertions();
03309      assert_iter.valid(); ++assert_iter) {
03310 
03311       Assertion & current_assert = assert_iter.current();
03312       /// ...   AssertionType current_type = current_assert.type();
03313 
03314       if (current_assert.arg_list_valid()) {
03315     _translate_symbol_refs_mutr(Mutator<Expression>(current_assert.arg_list_guarded()),
03316                     lambda, IN_REF_EXPR);
03317       }
03318     }
03319 
03320     // Iterate over any s_control expressions in an I/O statement
03321     /// ...  (keep track of modifications)
03322 
03323     if (s.s_control_valid()) {
03324         for (Iterator<s_control_type> s_iter = s.s_control_guarded();
03325                                       s_iter.valid(); ++s_iter) {
03326       if (_translate_symbol_refs_mutr(Mutator<Expression>(s_iter.current().expr),
03327                       lambda, IN_REF_EXPR))
03328         modify_flag = true;
03329     }
03330       }
03331 
03332     /// ...  Iterate over in, out, and in out ref expressions
03333     /// ...  (keep track of modifications)
03334 
03335     if (s.iterate_in_exprs_valid() &&
03336     _translate_symbol_refs_mutr(s.iterate_in_exprs_guarded(),lambda,
03337                     IN_REF_EXPR))
03338       modify_flag = true;
03339 
03340     if (s.iterate_out_exprs_valid()) {
03341 
03342       Mutator<Expression> out_mutr = s.iterate_out_exprs_guarded();
03343       if (_translate_symbol_refs_mutr(out_mutr,lambda,OUT_REF_EXPR)) {
03344     modify_flag = true;
03345     if ((s.stmt_class()==ASSIGNMENT_STMT) &&
03346         (s.lhs().op()==INTRINSIC_CALL_OP))
03347       fix_alternate_expr(s, _pgm_main);
03348       }
03349     }
03350 
03351     if (s.iterate_in_out_exprs_valid() &&
03352     _translate_symbol_refs_mutr(s.iterate_in_out_exprs_guarded(),lambda,
03353                     IN_OUT_REF_EXPR))
03354       modify_flag = true;
03355 
03356     /// ...  If body of statement was not modified, return to caller
03357 
03358     if (!modify_flag)
03359       return;
03360 
03361     /// ...  If body of statement was modified by a call which needed
03362     /// ...  no cleanup, rebuild references and return to caller.
03363 
03364     if (cleanup != CLEANUP_NEEDED) {
03365         s.build_refs();
03366         return;
03367     }
03368 
03369     /// ...  If body of statement modified by a call which needed cleanup,
03370     /// ...  do full cleanup processing
03371 
03372     Statement      *first_stmt_ref;
03373 
03374     /// ...  If precalculation statements were generated by lambda_call
03375     /// ...  processing, begin cleanup there first.
03376 
03377     p_assert(prev_stmt_ref, "Replacement done for first statement in StmtList");
03378 
03379     if (prev_stmt_ref != s.prev_ref()) {
03380         Statement      *clean_stmt = prev_stmt_ref->next_ref();
03381 
03382         /// ...  Point at first statement generated by cleanup of lambda call
03383         /// ...  precalculation (which might, for example, have had nested
03384         /// ...  function calls in its RHS).
03385 
03386         first_stmt_ref = &clean_statement(*_pgm_ref, *clean_stmt);
03387 
03388         /// ...  Clean up any other precalculation statements and the original
03389         /// ...  statement.
03390 
03391         for (Iterator<Statement> precalc_stmt_iter 
03392                 = _pgm_ref->stmts().iterator(*clean_stmt->next_ref(), s);
03393                                  precalc_stmt_iter.valid(); 
03394                                ++precalc_stmt_iter) {
03395             clean_statement(*_pgm_ref, precalc_stmt_iter.current());
03396         }
03397     }
03398     else {
03399         /// ...  If no preculation statements were generated by lambda_call
03400         /// ...  processing, just clean up the original statement.
03401         first_stmt_ref = &clean_statement(*_pgm_ref, s);
03402     }
03403 
03404     /// ...  Rebuild statement references
03405     s.build_refs();
03406 
03407     /// ...  Handle precalculation statements (if any)
03408     if (first_stmt_ref == &s)
03409         return;
03410 
03411     /// ...  Now, do rename and translate processing for cleaned up
03412     /// ...  precalculation statements
03413 
03414     RefList<Symbol> rename_list;
03415 
03416     for (Iterator<Statement> precalc_stmt_iter 
03417             = _pgm_ref->stmts().iterator(*first_stmt_ref, *s.prev_ref());
03418                              precalc_stmt_iter.valid();
03419                            ++precalc_stmt_iter) {
03420         Statement & precalc_stmt 
03421             = precalc_stmt_iter.current();
03422 
03423         p_assert(precalc_stmt.stmt_class() == ASSIGNMENT_STMT,
03424                  "Non-assignment statement encountered "
03425                  "in translate_symbol_refs_stmt");
03426 
03427         _remap_variable_symbol(precalc_stmt.lhs().symbol(), rename_list);
03428     }
03429 
03430     /// ...  Handle any symbols which need renaming.
03431     _remap_variable_symbols(rename_list);
03432 
03433     /// ...  Now, translate these assignment statements for the main program
03434     LambdaInfo our_lambda(_pgm_ref, 0, INLINE_CALL);
03435 
03436     for (Iterator<Statement> trans_stmt_iter 
03437             = _pgm_ref->stmts().iterator(*first_stmt_ref, *s.prev_ref());
03438                              trans_stmt_iter.valid(); ++trans_stmt_iter) {
03439         our_lambda.stmt_ref = &trans_stmt_iter.current();
03440         _translate_symbol_refs_stmt(our_lambda, cleanup);
03441     }
03442 
03443     /// ...  Finally, recursively retranslate original statement for the main
03444     /// ...  program
03445 
03446     /// ...  Note that cleanup processing is not needed when retranslating
03447     /// ...  the original statement
03448 
03449     our_lambda.stmt_ref = &s;
03450 
03451     _translate_symbol_refs_stmt(our_lambda, NO_CLEANUP_NEEDED);
03452 }
03453 
03454 /// Translate contained symbol references using the symbol, array
03455 /// and constant maps
03456 
03457 void 
03458 InlineObject::translate_symbol_refs(TRANS_CLEANUP_TYPE cleanup)
03459 {
03460   static LambdaInfo lambda(0, 0, INLINE_CALL);
03461 
03462   lambda.program_ref = _pgm_ref;
03463 
03464 /// If there is no translation to do, return to caller
03465 
03466   if ((!_symbol_map.entries()) && (!_constant_map.entries()) &&
03467       (!_format_map.entries()))
03468     return;
03469 
03470 /// Translate each statement
03471 
03472   for (Iterator<Statement> stmt_iter = _pgm_ref->stmts().iterator();
03473        stmt_iter.valid(); ++stmt_iter) {
03474     Statement & s = stmt_iter.current();
03475     if ((s.stmt_class()!=ENTRY_STMT)) {
03476       lambda.stmt_ref = &s;
03477       _translate_symbol_refs_stmt(lambda, cleanup);
03478     }
03479     else if (cleanup == NO_CLEANUP_NEEDED) {
03480       lambda.stmt_ref = &s;
03481       _translate_symbol_refs_entry(lambda);
03482     }
03483   }
03484 }
03485 
03486 /* Merge the contained pgm, and any precalculation statements introduced
03487    before statement s, into the main program at statement s after doing
03488    constant propagation and substitution of simple expressions.
03489    recursive indicates that the statements substituted will include
03490    RECURSIVE_INLINE assertions, to be evaluated after the substitution. */
03491 
03492 /// recursive added (kjackson)
03493 Statement & 
03494 InlineObject::_remap_merge_stmts(Statement & entry_statement, Statement & s,
03495                  bool recursive)
03496 {
03497   
03498 /// Find the FLOW_ENTRY and FLOW_EXIT
03499 
03500   Statement &flow_entry = _pgm_ref->stmts().first();
03501   Statement &flow_exit = _pgm_ref->stmts().last();
03502   cout<<"The flow exit statement is "<<endl; flow_exit.print(cout); cout<<endl;
03503 
03504 /// Save a copy of the list of entry statements for later
03505 
03506   RefSet<Statement> entry_refset = flow_entry.succ();
03507 
03508   /* If this entry doesn't follow the FLOW_ENTRY,
03509      more processing is needed. */
03510 
03511   if (flow_entry.next_ref() != &entry_statement) {
03512 
03513     Statement * next_stmt_ref = entry_statement.next_ref();
03514 
03515     /// ...  Determine where the code is for this entry
03516 
03517     switch (next_stmt_ref->stmt_class()) {
03518 
03519     case LABEL_STMT:
03520       break;
03521     case GOTO_STMT:
03522       {
03523     next_stmt_ref = next_stmt_ref->target_ref();
03524     break;
03525       }
03526     default:
03527       p_abort("Irregular entry point encountered in _remap_merge_stmts");
03528 
03529     }
03530 
03531     /// ...  Branch to this code from the FLOW_ENTRY
03532 
03533     Statement * goto_stmt = new GotoStmt(_pgm_ref->stmts().new_tag(),
03534                      next_stmt_ref);
03535     _pgm_ref->stmts().ins_after(goto_stmt, &flow_entry);
03536 
03537   }
03538 
03539 /// Remove the entry statements from the program
03540 
03541   _pgm_ref->stmts().del(entry_refset);
03542 
03543 /// Delete the RETURN statement at the end of the program
03544 
03545   Statement & routine_exit_stmt = *flow_exit.prev_ref();
03546   cout<<"The routine exit statement is "<<endl; routine_exit_stmt.print(cout); cout<<endl;
03547   switch (routine_exit_stmt.stmt_class()) {
03548   case STOP_STMT:
03549     break;
03550   case RETURN_STMT: {
03551     _pgm_ref->stmts().del(routine_exit_stmt);
03552     break;
03553   }
03554   default: 
03555     p_abort("Irregular exit point encountered in _remap_merge_stmts");
03556   }
03557   
03558 /// Remove all unreachable code and trivial gotos from program
03559 
03560   remove_unreachable_code(*_pgm_ref);
03561   remove_trivial_gotos(*_pgm_ref);
03562 
03563   RefSet<Symbol> candidate_set;
03564 
03565 /// If there are candidate precalculation variables saved, traverse
03566 /// _symbol_map and add them to candidate_set
03567 
03568   if (_precalc_vars) {
03569 
03570     for (KeyIterator<Symbol,SymRefElem> precalc_iter = _symbol_map;
03571      precalc_iter.valid(); ++precalc_iter) {
03572 
03573       SymRefElem & current_ref = precalc_iter.current_data();
03574 
03575       if (current_ref.precalc()==CAND_PRECALC_VAR) {
03576 
03577     Symbol & precalc_symbol = *current_ref.symref();
03578     candidate_set.ins(precalc_symbol);
03579       }
03580     }
03581   }
03582 
03583 /// Create block entry and exit statements around the existing statements
03584 
03585   Statement * flow_exit_prev = flow_exit.prev_ref();
03586   if (flow_exit_prev == &flow_entry)
03587     flow_exit_prev = 0;
03588 
03589   _pgm_ref->stmts().ins_BLOCK_after(&flow_entry,
03590                     flow_exit_prev);
03591 
03592   Statement * block_entry_stmt = flow_entry.next_ref();
03593   Statement * block_exit_stmt = flow_exit.prev_ref();
03594 
03595 /// Put a workspace on the block exit statement so inline driver
03596 /// knows it was created here
03597 
03598   block_exit_stmt->work_stack().push(new InlineWorkSpace(*_ws_ref));
03599 
03600 /// Move any assertions from the calling statement onto the BLOCK_ENTRY
03601 /// statement.  Remember an AssertPrivate for later.
03602 
03603   Assertion * private_assert_ref = 0;
03604 
03605   for (Mutator<Assertion> assert_mutr = s.assertions();
03606        assert_mutr.valid(); ++assert_mutr) {
03607     Assertion * assert_ref = assert_mutr.grab();
03608     if(assert_ref->type()==AS_PRIVATE)
03609       private_assert_ref = assert_ref;
03610     block_entry_stmt->assertions().ins_last(assert_ref);
03611   }
03612 
03613 /// Move private variable information into a new private assertion on the
03614 /// BLOCK_ENTRY statement
03615 
03616   if (_private_vars) {
03617 
03618     if (!private_assert_ref) {
03619       private_assert_ref = new AssertPrivate;
03620       block_entry_stmt->assertions().ins_last(private_assert_ref);
03621     }
03622 
03623     List<Expression> & private_list = private_assert_ref->arg_list_guarded();
03624 
03625     /// ...  Iterate over symbol map, processing only private variables
03626 
03627     for (KeyIterator<Symbol,SymRefElem> private_iter = _symbol_map;
03628      private_iter.valid(); ++private_iter) {
03629 
03630       SymRefElem & current_ref = private_iter.current_data();
03631 
03632       if (current_ref.privat()==PRIVATE) {
03633 
03634     Symbol & private_symbol = *current_ref.symref();
03635 
03636     if(private_symbol.is_array()) {
03637 
03638       // For now, build ArrayRefExpr with bound information for private
03639       // arrays (eventually, check switch)
03640 
03641       Expression * private_subscript = comma();
03642       List<Expression> & private_arg_list =
03643         private_subscript->arg_list();
03644 
03645       for (Iterator<ArrayBounds>private_bound_iter = private_symbol.dim();
03646            private_bound_iter.valid(); ++private_bound_iter) {
03647         ArrayBounds & private_bound = private_bound_iter.current();
03648         Expression * lower_ptr;
03649         if(private_bound.lower_exists())
03650           lower_ptr = private_bound.lower_guarded().clone();
03651         else
03652           lower_ptr = constant(1);
03653         Expression * upper_ptr;
03654         if(private_bound.upper_exists())
03655           upper_ptr = private_bound.upper_guarded().clone();
03656         else
03657           upper_ptr = constant(1);
03658         private_arg_list.ins_last(colon(lower_ptr, upper_ptr, NULL));
03659       }
03660       private_list.ins_last(array_reference(id(private_symbol),
03661                           private_subscript));
03662     }
03663     else
03664       private_list.ins_last(id(private_symbol));
03665       }
03666     }
03667   }
03668 
03669 /// Move any test expressions for subscripts into an assertion
03670 /// on the BLOCK_ENTRY statement
03671 
03672   if (_test_exprs.entries()) {
03673     AssertRelation * test_exprs_ref = new AssertRelation;
03674     List<Expression> & expr_args = test_exprs_ref->arg_list_guarded();
03675     for (Mutator<Expression> test_mutr = _test_exprs;
03676      test_mutr.valid(); ++test_mutr)
03677       expr_args.ins_last(test_mutr.grab());
03678     block_entry_stmt->assertions().ins_last(test_exprs_ref);
03679   }
03680 
03681   /* Clone InlineWorkSpace from inlined program to the BLOCK_ENTRY
03682      statement.
03683 
03684   (beginning of commented out code)
03685 
03686   InlineWorkSpace * inline_ws_ptr = 0;
03687   if (_ws_ref->count_active()) {
03688     InlineWorkSpace & inline_ref =
03689       *(InlineWorkSpace *)_pgm_ref->work_stack().top_ref(_ws_ref->pass_tag());
03690     inline_ws_ptr = new InlineWorkSpace(inline_ref);
03691     block_entry_stmt->work_stack().push(inline_ws_ptr);
03692   }
03693 
03694   (end of commented out code)
03695 
03696   */
03697 
03698 /// If debugging is on, move in comments around region
03699 
03700   if (_debug_flag) {
03701 
03702     AssertComment * begin_comment_ref = new AssertComment;
03703     List<StringElem> & begin_args =
03704       begin_comment_ref->string_arg_list_guarded();
03705     for (Mutator<StringElem> begin_mutr = _begin_comment_list;
03706      begin_mutr.valid(); ++begin_mutr)
03707       begin_args.ins_last(begin_mutr.grab());
03708     block_entry_stmt->assertions().ins_last(begin_comment_ref);
03709 
03710     AssertComment * end_comment_ref = new AssertComment;
03711     List<StringElem> & end_args =
03712       end_comment_ref->string_arg_list_guarded();
03713     for (Mutator<StringElem> end_mutr = _end_comment_list;
03714      end_mutr.valid(); ++end_mutr)
03715       end_args.ins_last(end_mutr.grab());
03716     block_exit_stmt->assertions().ins_last(end_comment_ref);
03717       
03718   }
03719 
03720 /// Remember statement after s for later insert of inlined code
03721 
03722   Statement * caller_next_ref = s.next_ref();
03723 
03724 /// Check statements preceding s in the main program for
03725 /// precalculation variables generated by clean_statement
03726 
03727   Statement * precalc_ref = s.prev_ref();
03728 
03729   Statement * first_precalc_ref = 0;
03730 
03731   while (precalc_ref &&
03732      (precalc_ref->stmt_class() == ASSIGNMENT_STMT) &&
03733      (precalc_ref->lhs().op()==ID_OP) &&
03734      (strncmp(precalc_ref->lhs().symbol().name_ref(),"PC",2) == 0)) {
03735 
03736     first_precalc_ref = precalc_ref;
03737 
03738     Symbol & precalc_symbol = precalc_ref->lhs().symbol();
03739 
03740     const Type & precalc_type = precalc_symbol.type();
03741 
03742     /// ...  If variable is an integer scalar, add it to the candidate list
03743 
03744     if ((precalc_type.data_type() == INTEGER_TYPE) &&
03745     (precalc_type.is_scalar()))
03746       candidate_set.ins(precalc_symbol);
03747 
03748     precalc_ref = precalc_ref->prev_ref();
03749   }
03750 
03751 /// If any precalculation statements were found, grab them and add
03752 /// them to the subprogram
03753 
03754   if (first_precalc_ref) {
03755     Statement & first_precalc_stmt = *first_precalc_ref;
03756     /// ...    Statement * prev_first_precalc_stmt = first_precalc_stmt.prev_ref();
03757     Statement & last_precalc_stmt = *s.prev_ref();
03758     StmtList & main_stmts = _pgm_main.stmts();
03759     List<Statement> * precalc_block = 
03760       main_stmts.grab(first_precalc_stmt, last_precalc_stmt, DONT_RELABEL);
03761     _pgm_ref->stmts().ins_after(precalc_block, &flow_entry);
03762   }
03763  
03764   if (candidate_set.entries()) {
03765 
03766     /// ...  Propagate the candidate variables if possible
03767 
03768     propagate_constants(*_pgm_ref, candidate_set, REMOVE_UNREACH_CODE);
03769 
03770     /// ...  Accept small substitutions
03771 
03772     expand_small_substituted(*_pgm_ref);
03773 
03774     /// ...  Clear any leftover substitutions
03775 
03776     clear_substituted(*_pgm_ref);
03777 
03778   }
03779 
03780 /// Remember return statement value
03781 
03782   Statement *first_stmt_ref = flow_entry.next_ref();
03783 
03784 /// Grab the statements between FLOW_ENTRY and FLOW_EXIT (if any)
03785 
03786   List<Statement> *grabbed_block = 
03787     _pgm_ref->stmts().grab(*first_stmt_ref,
03788                *flow_exit.prev_ref(),
03789                DONT_RELABEL);
03790 
03791   /* Count statements for the inline workspace
03792 
03793   (beginning of commented out code)
03794 
03795   if (inline_ws_ptr) {
03796     inline_ws_ptr->exec_lines_output(count_stmts(*grabbed_block));
03797     inline_ws_ptr->total_lines_output(grabbed_block->entries());
03798   }
03799 
03800   (end of commented out code)
03801 
03802   */
03803 
03804 /// Delete original calling statment
03805   _pgm_main.stmts().del(s);
03806 
03807 /// Add to main program
03808   _pgm_main.stmts().ins_before(grabbed_block, caller_next_ref);
03809 
03810 
03811 /// BEGIN ADDED SECTION (kjackson)
03812     /// ...  if this is a RECURSIVE_INLINE instance, search for any call
03813     /// ...  statements to which this assertion will be added
03814   if (recursive)  {
03815       Iterator<Statement>  stmt_iter(_pgm_main.stmts(),
03816                      block_entry_stmt,
03817                      block_exit_stmt);
03818 
03819       for (; stmt_iter.valid(); ++stmt_iter) {
03820       Statement & s_here = stmt_iter.current();
03821       STMT_TYPE   stype = s_here.stmt_class();
03822 
03823       switch (stype) {
03824           /// ...  Do not process assignment statement if it does not have
03825           /// ...  a function call expr as its rhs
03826       case ASSIGNMENT_STMT:
03827       case CALL_STMT:
03828           if ((stype != ASSIGNMENT_STMT) ||
03829           (s_here.rhs().op() == FUNCTION_CALL_OP)) {
03830           bool assert_noinline = false;
03831           bool no_assertions = true;
03832           for (Iterator<Assertion> assert_iter = s_here.assertions();
03833                assert_iter.valid(); ++assert_iter) {
03834         
03835               AssertionType current_type = assert_iter.current().type();
03836               if (current_type==AS_NOINLINE) {
03837               no_assertions = false;
03838               assert_noinline = true;
03839               }
03840               else if ((current_type == AS_INLINE) ||
03841                    (current_type == AS_RECURSIVEINLINE)) {
03842               no_assertions = false;
03843               }
03844           }
03845           if (!assert_noinline) {
03846               Assertion * s_here_assert = new AssertRecursiveInline;
03847 
03848               s_here.assertions().ins_last(s_here_assert);
03849           }
03850           }
03851           break;
03852       default: break;
03853       }
03854       }
03855   }
03856 /// END ADDED SECTION (kjackson)
03857 
03858 /// Return a reference to the first inlined statement
03859   return *first_stmt_ref;
03860 }
03861 
03862 /// Inline expansion of program represented by the InlineObject into the
03863 /// main program referred to by the InlineObject at statement s.
03864 /// recursive indicates if this is a RECURSIVE_INLINE expansion
03865 
03866 /// recursive added (kjackson)
03867 Statement & 
03868 InlineObject::inline_expand(Statement & s, bool recursive)
03869 {
03870 
03871     static String debug_switch("inline_debug");
03872     _debug_flag = switch_value(debug_switch);
03873     
03874     if (_debug_flag > 9) {
03875       int i = 0;
03876       cerr << "Inliner called to substitute the following statement:\n ";
03877       s.write(cerr, i);
03878       cerr.flush();
03879     }
03880 
03881     /// ...  If first inlining, make permanent changes
03882     if (!_permanent_changes) {
03883         float_entry_points(*_pgm_ref);
03884         sink_return_points(*_pgm_ref);
03885         _remap_local_variables();
03886     _precalc_adjustable_array_bounds();
03887     prepare_routines_for_arg_mapping();
03888         _remap_local_variables();
03889         _remap_and_move_formats();
03890     
03891         _permanent_changes = true;
03892     }
03893 
03894     /// ...  Allocate work InlineObject from saved one
03895     InlineObject    proto_work(*this);
03896 
03897     /// ...  Rename branch targets
03898     proto_work._rename_branch_targets();
03899 
03900     /// ...  Remap argument uses
03901     Statement & entry_statement = proto_work._remap_arg_uses(s);
03902 
03903     /// ...  Translate symbol references
03904     proto_work.translate_symbol_refs(CLEANUP_NEEDED);
03905 
03906     /// ...  Merge pgm_work into main program, adding RECURSIVE_INLINE assertions
03907     /// ...  to appropriate statements if necessary (kjackson)
03908     Statement & t = proto_work._remap_merge_stmts(entry_statement, s, recursive);
03909 
03910     /// ...  substitute any parameters which may have been inlined
03911     substitute_parameters(_pgm_main, IGNORE_REALS);
03912 
03913     /// ...  Return insertion point ref to caller
03914     return t;
03915 }
03916 
03917 void
03918 InlineObject::prepare_routines_for_arg_mapping()
03919 {
03920     substitute_parameters(*_pgm_ref, IGNORE_REALS);
03921 ///    _precalc_adjustable_array_bounds();  Moved back to inline_expand()
03922     _expand_IO_array_names();
03923     _remap_common_blocks();
03924     _remap_equivalences();
03925     _remap_and_move_data();
03926 }
03927 
03928 void
03929 InlineObject::_insert_arg_mapping( Symbol & formal, Expression * actual,
03930                   AbstractAccess * aa)
03931 {
03932     _formal_to_actual.ins(formal, actual);
03933     if (aa) {
03934     _formal_to_access_region.ins(formal, aa);
03935     }
03936 }
03937 
03938 const Expression *
03939 InlineObject::actual_arg(const Symbol & formal) const
03940 {
03941     return _formal_to_actual.find_ref(formal);
03942 }
03943 
03944 const AbstractAccess *
03945 InlineObject::access_region( const Symbol & formal) const
03946 {
03947     return _formal_to_access_region.find_ref(formal);
03948 }
 © 1995-2005 University of Illinois, Urbana-Champaign. All rights reserved.  Fri Mar 25 23:05:55 2005