OpenADFortTk (basic)
src/whirl2xaif/wn2xaif.cxx
Go to the documentation of this file.
00001 #include <alloca.h>
00002 #include <stdlib.h> 
00003 #include <string>   
00004 #include <set> 
00005 #include <vector> 
00006 
00007 #include "OpenAnalysis/CFG/ManagerCFG.hpp"
00008 
00009 #include "Open64IRInterface/Open64BasicTypes.h"
00010 #include "Open64IRInterface/SymTab.h"
00011 #include "Open64IRInterface/Open64IRInterface.hpp"
00012 
00013 #include "wn2xaif.i"
00014 #include "wn2xaif.h"
00015 #include "wn2xaif_stmt.h"
00016 #include "wn2xaif_expr.h"
00017 #include "wn2xaif_mem.h"
00018 #include "wn2xaif_io.h"
00019 #include "st2xaif.h"
00020 #include "ty2xaif.h"
00021 #include "Args.h"
00022 
00023     
00024 namespace whirl2xaif { 
00025 
00026   static void
00027   xlate_EntryPoint(xml::ostream& xos, WN *wn, PUXlationContext& ctxt);
00028 
00029   static set<OA::SymHandle>* 
00030   GetParamSymHandleSet(WN* wn_pu);
00031 
00032   static const char*
00033   xlate_intent(WN* parm);
00034 
00035   static void
00036   xlate_BBStmt(xml::ostream& xos, WN *wn, PUXlationContext& ctxt);
00037 
00038   static void 
00039   xlate_CFCondition(xml::ostream& xos, WN *wn, PUXlationContext& ctxt);
00040 
00041   static void 
00042   xlate_LoopInitialization(xml::ostream& xos, WN *wn, PUXlationContext& ctxt);
00043 
00044   static void 
00045   xlate_LoopUpdate(xml::ostream& xos, WN *wn, PUXlationContext& ctxt);
00046 
00047   static void
00048   DumpCFGraphEdge(xml::ostream& xos, UINT eid, 
00049                   OA::OA_ptr<OA::CFG::EdgeInterface> edge);
00050 
00051   static const char*
00052   GetLoopReversalType(OA::OA_ptr<OA::CFG::CFGInterface> cfg, 
00053                       OA::OA_ptr<OA::CFG::NodeInterface> n);
00054 
00055   static std::string
00056   GetIDsForStmtsInBB(OA::OA_ptr<OA::CFG::NodeInterface> node, 
00057                      PUXlationContext& ctxt);
00058 
00059   // NOTE: removed static for Sun's compiler (supposed to be in unnamed
00060   // namespace now)
00061   pair<bool, INT64>
00062   GetCFGEdgeCondVal(const OA::OA_ptr<OA::CFG::EdgeInterface> edge);
00063 
00064   // lt_CFGEdge: Used to sort CFG::Edges by src, sink and condition value.
00065   struct lt_CFGEdge
00066   {
00067     // return true if e1 < e2; false otherwise
00068     bool operator()(const OA::OA_ptr<OA::CFG::EdgeInterface> e1, 
00069                     const OA::OA_ptr<OA::CFG::EdgeInterface> e2) const
00070     {
00071       unsigned int src1 = e1->getSource()->getId();
00072       unsigned int src2 = e2->getSource()->getId();
00073       if (src1 == src2) { 
00074         unsigned int sink1 = e1->getSink()->getId();
00075         unsigned int sink2 = e2->getSink()->getId();
00076         if (sink1 == sink2) {
00077           pair<bool, INT64> ret1 = GetCFGEdgeCondVal(e1);
00078           bool hasCondVal1 = ret1.first;
00079           INT64 condVal1 = ret1.second;
00080     
00081           pair<bool, INT64> ret2 = GetCFGEdgeCondVal(e2);
00082           bool hasCondVal2 = ret2.first;
00083           INT64 condVal2 = ret2.second;
00084         
00085           if (hasCondVal1 && hasCondVal2) {
00086             return (condVal1 < condVal2);
00087           } 
00088           else if (hasCondVal1 /* && !hasCondVal2 */) {
00089             return false;  // e1 > e2
00090           }
00091           else if (hasCondVal2 /* && !hasCondVal1 */) {
00092             return true; // e1 < e2
00093           }
00094           else /* !hasCondVal1 && !hasCondVal2 */ {
00095             return false; // e1 == e2
00096           }
00097         } 
00098         else { 
00099           return (sink1 < sink2); 
00100         }
00101       } 
00102       else {
00103         return (src1 < src2);
00104       }
00105     }
00106 
00107   };
00108 
00109   // the handlers
00110   typedef void (*Handler)(xml::ostream&, WN*, PUXlationContext&);
00111   static std::map<int,Handler> ourHandlerTable;
00112   static bool ourHandlerTableInit=false;
00113   void initOurHandlerTable();
00114 
00115   // TranslateWN: see header. The task of translation is dispatched to
00116   // the appropriate handler registered in the handler table.
00117   void 
00118   TranslateWN(xml::ostream& xos, WN *wn, PUXlationContext& ctxt)
00119   {   
00120 
00121     if (!wn) { return; }
00122 
00123     OPERATOR opr = WN_operator(wn);
00124   
00125 #if 0
00126     //xos << BegComment << "Translating " << OPERATOR_name(opr) << EndComment;
00127     fortTkSupport::WNId id = ctxt.findWNId(wn);
00128 #endif
00129   
00130     // Determine whether we are in a context where we expect this
00131     // expression to have logically valued arguments, or whether we are
00132     // entering a context where we expect this expression to be a
00133     // logically valued argument.
00134     OPCODE opc = WN_opcode(wn);
00135     if (OPCODE_is_boolean(opc) && WN2F_expr_has_boolean_arg(opc)) { 
00136       // We expect logical operands to this operator.  Note that this
00137       // may also be a logical argument, so
00138       // ctxt.currentXlationContext().isFlag(XlationContext::IS_LOGICAL_ARG) may also be true.
00139       ctxt.currentXlationContext().setFlag(XlationContext::HAS_LOGICAL_ARG);
00140     } 
00141     else if (ctxt.currentXlationContext().isFlag(XlationContext::HAS_LOGICAL_ARG)) { 
00142       // This is a logical argument.  This is the only place where we
00143       // should need to check whether this is expected to be a logical
00144       // valued expression. I.e. the only place where we apply
00145       // PUXlationContext_XlationContext::HAS_LOGICAL_ARG(context).  However, it may be
00146       // set at other places (e.g. in wn2f_stmt.c).
00147       ctxt.currentXlationContext().unsetFlag(XlationContext::HAS_LOGICAL_ARG);
00148       ctxt.currentXlationContext().setFlag(XlationContext::IS_LOGICAL_ARG);
00149     }
00150     else {
00151       ctxt.currentXlationContext().unsetFlag(XlationContext::HAS_LOGICAL_ARG);
00152       ctxt.currentXlationContext().unsetFlag(XlationContext::IS_LOGICAL_ARG);
00153     }
00154   
00155     // Dispatch to the appropriate handler for this construct.
00156     if (!ourHandlerTableInit)
00157       initOurHandlerTable();
00158     return ourHandlerTable[opr](xos, wn, ctxt);
00159   }
00160 
00161 
00162   // Function entry handlers
00163       
00164 
00165   // xlate_FUNC_ENTRY: Given the root of a WHIRL tree, and an
00166   // appropriate context 'ctxt', emits XAIF for the tree to the 'xos'
00167   // stream.  Assumes that Open64 symbol table globals are already set.
00168   void
00169   xlate_FUNC_ENTRY(xml::ostream& xos, WN *wn, PUXlationContext& ctxt)
00170   {
00171     using namespace OA::CFG;
00172     using namespace OA::DGraph;
00173 
00174     FORTTK_ASSERT(WN_operator(wn) == OPR_FUNC_ENTRY, fortTkSupport::Diagnostics::UnexpectedInput); 
00175   
00176     WN* fbody = WN_func_body(wn);
00177 
00178     // -------------------------------------------------------
00179     // Collect auxillary data
00180     // -------------------------------------------------------
00181   
00182     // 0. WHIRL parent map (FIXME: compute at callgraph)
00183     fortTkSupport::WhirlParentMap wnParentMap(wn);
00184     ctxt.setWNParentMap(&wnParentMap);
00185 
00186     // 1. OpenAnalysis info
00187     OA::ProcHandle proc((OA::irhandle_t)Current_PU_Info);
00188 
00189     fortTkSupport::IntraOAInfo* oaAnal = Whirl2Xaif::getOAAnalMap().Find(Current_PU_Info);
00190     OA::OA_ptr<OA::CFG::CFGInterface> cfg = 
00191       Whirl2Xaif::getOAAnalMap().getCFGEach()->getCFGResults(proc);
00192     ctxt.setUDDUChains(oaAnal->getUDDUChainsXAIF());
00193     ctxt.setAliasMapXAIF(oaAnal->getAliasXAIF());
00194     ctxt.setDoChains(oaAnal->getReachDefsOverwriteXAIF());
00195   
00196     // 2. Non-scalar symbol table
00197     fortTkSupport::ScalarizedRefTab_W2X* tab = Whirl2Xaif::getScalarizedRefTableMap().Find(Current_PU_Info);
00198     ctxt.setScalarizedRefTab(tab);
00199   
00200     // 3. WHIRL<->ID maps
00201     fortTkSupport::WNToWNIdMap* wnmap = Whirl2Xaif::getWNToWNIdTableMap().Find(Current_PU_Info);
00202     ctxt.setWNToIdMap(wnmap);
00203   
00204     // -------------------------------------------------------
00205     // Translate the function header
00206     // -------------------------------------------------------
00207     xlate_EntryPoint(xos, wn, ctxt); 
00208     xos << std::endl;
00209 
00210     // -------------------------------------------------------
00211     // Translate CFG (et al.) to XAIF
00212     // -------------------------------------------------------
00213     ctxt.createXlationContext(XlationContext::NOFLAG, wn);
00214   
00215     // Dump CFG vertices (basic blocks) in sorted order ('normalized')
00216     // Note: It might seem that instead of sorting, we could simply use
00217     // DGraphStandard::DFSIterator.  However, procedures can have
00218     // unreachable code that will not be found with a DFS.  A simple
00219     // example of this is that WHIRL often has two OPR_RETURNs at the
00220     // end of a procedure.
00221 #if 0 // FIXME
00222     //     DGraphNodeVec* nodes = SortDGraphNodes(&cfg);
00223     //     for (DGraphNodeVec::iterator nodeIt = nodes->begin(); 
00224     //   nodeIt != nodes->end(); ++nodeIt) {
00225 #endif
00226   
00227     // try a BFS iterator.  too bad for dead code. (actually DFS-- BFS
00228     // not yet implmented) -- toposort FIXME
00229     std::set<OA::OA_ptr<OA::CFG::NodeInterface> > usedNodes;
00230     
00231     OA::OA_ptr<OA::CFG::NodeInterface> entry = cfg->getEntry();
00232     OA::OA_ptr<OA::DGraph::NodesIteratorInterface> nodeItPtr = cfg->getDFSIterator(entry);
00233     for (; nodeItPtr->isValid(); ++(*nodeItPtr)) {
00234       OA::OA_ptr<OA::DGraph::NodeInterface> dn = nodeItPtr->current();
00235       OA::OA_ptr<OA::CFG::Node> n = dn.convert<OA::CFG::Node>();
00236       usedNodes.insert(n);
00237       // std::cout << "visiting " << n->getId() << std::endl;
00238       const char* vtype = fortTkSupport::GetCFGVertexType(cfg, n);
00239       fortTkSupport::SymTabId scopeId = ctxt.findSymTabId(Scope_tab[CURRENT_SYMTAB].st_tab);
00240       std::string ids = GetIDsForStmtsInBB(n, ctxt);
00241       // 1. BB element begin tag
00242       xos << xml::BegElem(vtype) << xml::Attr("vertex_id", n->getId());
00243       if (vtype == XAIFStrings.elem_BB()) {
00244         xos << xml::Attr("scope_id", scopeId);
00245       }
00246       else if (vtype == XAIFStrings.elem_BBForLoop()) {
00247         xos << xml::Attr("reversal", GetLoopReversalType(cfg,n));
00248       }
00249       if (vtype == XAIFStrings.elem_BBForLoop() 
00250           || 
00251           vtype == XAIFStrings.elem_BBPreLoop()
00252           || 
00253           vtype == XAIFStrings.elem_BBPostLoop()
00254           || 
00255           vtype == XAIFStrings.elem_BBBranch()) { 
00256         // to get the line number we need to get  
00257         // the whirl node which appears to be quite a chore
00258         OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtIt = n->getNodeStatementsIterator();
00259         bool found=false;
00260         for (; stmtIt->isValid() && !found; ++(*stmtIt)) {
00261           OA::StmtHandle st = stmtIt->current();
00262           WN* wstmt = (WN*)st.hval(); 
00263           // now we need to figure out which one of these it actually is: 
00264           OPERATOR opr = WN_operator(wstmt);
00265           switch (opr) {
00266           case OPR_DO_LOOP: 
00267           case OPR_DO_WHILE: 
00268           case OPR_WHILE_DO:
00269           case OPR_IF:
00270           case OPR_SWITCH: { 
00271             USRCPOS srcpos;
00272             USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wstmt);
00273             xos << xml::Attr("lineNumber",USRCPOS_linenum(srcpos));
00274             found=true;
00275             break;
00276           }
00277           default: 
00278             break; // fall through
00279           }
00280         }
00281       }
00282       // 2. BB element contents
00283       ctxt.createXlationContext();
00284       OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtItPtr
00285         = n->getNodeStatementsIterator();
00286       for (; stmtItPtr->isValid(); ++(*stmtItPtr)) {
00287         WN* wstmt = (WN *)stmtItPtr->current().hval();
00288         xlate_BBStmt(xos, wstmt, ctxt);
00289       }
00290       ctxt.deleteXlationContext();
00291       // 3. BB element end tag
00292       xos << xml::EndElem << std::endl;
00293     }
00294 #if 0
00295     delete nodes;
00296 #endif
00297 
00298     // Dump CFG edges (only those within the XAIF graph)
00299     CFGEdgeVec* edges = SortCFGEdges(cfg);
00300     for (CFGEdgeVec::iterator edgeIt = edges->begin(); 
00301          edgeIt != edges->end(); ++edgeIt) {
00302       OA::OA_ptr<OA::CFG::EdgeInterface> e = (*edgeIt);
00303       
00304       OA::OA_ptr<OA::DGraph::NodeInterface> dsrc = e->getSource();
00305       OA::OA_ptr<OA::CFG::Node> src = dsrc.convert<OA::CFG::Node>();
00306       OA::OA_ptr<OA::DGraph::NodeInterface> dsnk = e->getSink();
00307       OA::OA_ptr<OA::CFG::Node> snk = dsnk.convert<OA::CFG::Node>();
00308       if (usedNodes.find(src) != usedNodes.end() && 
00309           usedNodes.find(snk) != usedNodes.end()) {
00310         DumpCFGraphEdge(xos, ctxt.currentXlationContext().getNewEdgeId(), e);
00311       }
00312     }
00313 
00314     delete edges;
00315   
00316     // -------------------------------------------------------
00317     // Cleanup
00318     // -------------------------------------------------------
00319     ctxt.deleteXlationContext();
00320   
00321     
00322   }
00323 
00324   // xlate_ALTENTRY:
00325   void
00326   xlate_ALTENTRY(xml::ostream& xos, WN *wn, PUXlationContext& ctxt)
00327   {
00328     // Similar to a FUNC_ENTRY, but without the function body.
00329     FORTTK_ASSERT(WN_operator(wn) == OPR_ALTENTRY, fortTkSupport::Diagnostics::UnexpectedInput); 
00330   
00331     // Translate the function entry point (FIXME)
00332     xlate_EntryPoint(xos, wn, ctxt);
00333   
00334     
00335   }
00336 
00337 
00338   void
00339   xlate_ignore(xml::ostream& xos, WN *wn, PUXlationContext& ctxt)
00340   {
00341     
00342   }
00343 
00344   void
00345   xlate_STRCTFLD(xml::ostream& xos, 
00346                  WN *wn, 
00347                  PUXlationContext& ctxt) {
00348     xlate_MemRef(xos, 
00349                  wn, 
00350                  WN_Tree_Type(wn),  
00351                  WN_Tree_Type(wn),  
00352                  0, 
00353                  ctxt);
00354   }
00355 
00356   void
00357   xlate_unknown(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) {
00358     OPERATOR opr = WN_operator(wn);
00359     FORTTK_DIE(fortTkSupport::Diagnostics::UnexpectedOpr << OPERATOR_name(opr));
00360   }
00361 
00362 
00363   // FIXME: MOVE elsewhere
00364   bool
00365   IsActiveStmt(WN* wn, PUXlationContext& ctxt)
00366   {
00367     bool active = false;
00368   
00369     OPERATOR opr = WN_operator(wn);
00370 
00371     // if (OPERATOR_is_store(opr) || OPERATOR_is_call(opr)) { }
00372 
00373     if (OPERATOR_is_call(opr)) {
00374       // FIXME: For now we punt on calls and assume they are active.
00375       active = true;
00376     }
00377     else if (OPERATOR_is_store(opr)) {
00378       TY_IDX ty = WN_Tree_Type(wn);
00379       const char* ty_str = TranslateTYToSymType(ty); // FIXME
00380       active = (strcmp(ty_str, "real") == 0 || strcmp(ty_str, "complex") == 0);
00381     }
00382   
00383     return active;
00384   }
00385 
00386 
00387   // Variable references: xlate_SymRef, xlate_MemRef
00388 
00389   // Helper for xlate_MemRef
00390   /* just used to maintain the state of the recursions when */
00391   /* marking FLDs in nested addresses                       */
00392   class LOC_INFO {
00393   private:
00394     FLD_PATH_INFO * _flds_left;   /* points to tail of fld_path */
00395     STAB_OFFSET _off;             /* offset of last FLD used in fld_path */
00396     BOOL   _base_is_array;        /* was ST of address an array? */
00397   
00398   public:
00399     WN * _nested_addr;
00400   
00401     LOC_INFO(FLD_PATH_INFO * path)
00402       : _flds_left(path), _off(0), _base_is_array(FALSE), _nested_addr(NULL) { }
00403   
00404     void WN2F_Find_And_Mark_Nested_Address(WN * addr);
00405   };
00406 
00407 
00408   // xlate_PregRef: [FIXME: can we abstract witih xlate_SymRef]
00409   void
00410   xlate_PregRef(xml::ostream& xos, ST* st, TY_IDX preg_ty, 
00411                 PREG_IDX preg_idx, PUXlationContext& ctxt)
00412   {
00413     bool closeVarRef = false;
00414     if (!ctxt.currentXlationContext().isFlag(XlationContext::VARREF)) {
00415       xos << xml::BegElem(XAIFStrings.elem_VarRef())
00416           << xml::Attr("vertex_id", ctxt.currentXlationContext().getNewVertexId())
00417           << xml::Attr("du_ud", ctxt.findUDDUChainId(ctxt.getMostRecentWN()))
00418           << xml::Attr("alias", ctxt.getAliasMapKey(ctxt.getMostRecentWN()));
00419       closeVarRef = true; 
00420     }
00421 
00422     ST_TAB* sttab = Scope_tab[ST_level(st)].st_tab;
00423     fortTkSupport::SymTabId scopeid = ctxt.findSymTabId(sttab);
00424 
00425     xos << xml::BegElem("xaif:SymbolReference") 
00426         << xml::Attr("vertex_id", ctxt.currentXlationContext().getNewVertexId())
00427         << xml::Attr("scope_id", scopeid) << AttrSymId(st) << PregIdAnnot(preg_idx)
00428         << xml::EndElem;
00429   
00430     if (closeVarRef) {
00431       xos << xml::EndElem /* elem_VarRef() */;
00432     }
00433   
00434     
00435   }
00436 
00437 
00438   // xlate_SymRef: see header.
00439   void
00440   xlate_SymRef(xml::ostream& xos, 
00441                ST* base_st,        // base symbol
00442                TY_IDX baseptr_ty,  // type of base symbol ptr
00443                TY_IDX ref_ty,      // type of referenced object
00444                STAB_OFFSET offset, // offset within 'base_st'
00445                PUXlationContext& ctxt)
00446   {
00447     // FIXME: ugly, ugly, ugly
00448     /* The base symbol 'base_st' will be treated as having a lvalue
00449      * (address) type of 'baseptr_ty', except when "deref" is TRUE, when
00450      * the rvalue of 'base_st' is assumed to have the 'base_ty'
00451      * and must either explicitly (for POINTER variables) or implicitly
00452      * (for pass by reference arguments) be dereferenced.
00453 
00454      * Note that a compatible 'base_ty' and 'ref_ty' simply translates
00455      * into a reference to the given 'base_st'.  In all other cases we
00456      * expect 'ref_ty' to be a field or offset within the 'base_ty'
00457      * (structure or array).
00458      *
00459      * Note that we must have special handling for common-blocks and
00460      * equivalences.  Note that "base_ty" may be different from
00461      * "Stab_Pointer_To(ST_type(base_st))", both for "deref" cases and 
00462      * ptr_as_array variables.  */
00463 
00464     WN* ref_wn = ctxt.getMostRecentWN();
00465     TY_IDX base_ty = TY_pointed(baseptr_ty); 
00466 
00467     // -------------------------------------------------------
00468     // If we are not already within xaif:VariableReference... (FIXME: abstract)
00469     // -------------------------------------------------------
00470     bool constant = (ST_class(base_st) == CLASS_CONST);
00471     bool newContext = false;
00472     if (!constant && !ctxt.currentXlationContext().isFlag(XlationContext::VARREF)) {
00473       xos << xml::BegElem(XAIFStrings.elem_VarRef())
00474           << xml::Attr("vertex_id", ctxt.currentXlationContext().getNewVertexId())
00475           << xml::Attr("du_ud", ctxt.findUDDUChainId(ref_wn))
00476           << xml::Attr("alias", ctxt.getAliasMapKey(ref_wn));
00477       ctxt.createXlationContext(XlationContext::VARREF);
00478       newContext = true; 
00479     }
00480 
00481     /* Select variable-reference translation function */
00482     const BOOL deref_val = ctxt.currentXlationContext().isFlag(XlationContext::DEREF_ADDR);
00483     void (*translate_var_ref)(xml::ostream&, ST*, PUXlationContext&);
00484 
00485     if (deref_val && (ST_sclass(base_st) != SCLASS_FORMAL) 
00486         && TY_Is_Pointer(ST_type(base_st)) 
00487         && !TY_is_f90_pointer(ST_type(base_st))) {
00488       /* An explicit dereference */
00489       translate_var_ref = &ST2F_deref_translate;
00490     } 
00491     else {
00492       /* A direct reference or an implicit dereference */
00493       translate_var_ref = &TranslateSTUse;
00494     }
00495   
00496   
00497     // FIXME: for now, make sure this is only used for data refs 
00498     if (ST_class(base_st) == CLASS_FUNC) {
00499       std::cerr << "xlate_SymRef: translating function ref\n";
00500     } 
00501     else if (ST_class(base_st) == CLASS_BLOCK) { // FIXME
00502       TranslateSTUse(xos, base_st, ctxt);
00503       xos << "+ " << Num2Str(offset, "%lld");
00504     }
00505     
00506     // Note: top-var-refs will can be classified according to
00507     // IsRefSimple*() functions.  Things are a little more complicated
00508     // with sub-var-refs; hence the need for two tests in each 'if'.
00509 
00510     fortTkSupport::ScalarizedRef* sym = ctxt.findScalarizedRef(ref_wn);
00511     if (sym) { 
00512       // 1. A scalarized symbol
00513       ST_TAB* sttab = Scope_tab[CURRENT_SYMTAB].st_tab;
00514       fortTkSupport::SymTabId scopeid = ctxt.findSymTabId(sttab);
00515     
00516       xos << xml::BegElem("xaif:SymbolReference") 
00517           << xml::Attr("vertex_id", ctxt.currentXlationContext().getNewVertexId())
00518           << xml::Attr("scope_id", scopeid) 
00519           << xml::Attr("symbol_id", sym->getName()) << xml::EndElem;
00520     } 
00521     else if (fortTkSupport::ScalarizedRef::isRefScalar(base_ty, ref_ty) 
00522              || 
00523              fortTkSupport::ScalarizedRef::isRefSimpleScalar(ref_wn)) {
00524       // 2. Reference to a scalar symbol (==> offset into 'base_st' is zero)
00525       translate_var_ref(xos, base_st, ctxt);
00526     } 
00527     else if (TY_Is_Array(ref_ty) 
00528              || 
00529              fortTkSupport::ScalarizedRef::isRefSimpleArray(ref_wn)) {
00530       // 3. Reference to an array of scalars
00531       translate_var_ref(xos, base_st, ctxt);
00532     }
00533     else if (TY_Is_Array(base_ty) 
00534              || 
00535              fortTkSupport::ScalarizedRef::isRefSimpleArrayElem(ref_wn)) {
00536       // 4. Array element reference to a scalar
00537       translate_var_ref(xos, base_st, ctxt);
00538       if (!ctxt.currentXlationContext().isFlag(XlationContext::HAS_NO_ARR_ELMT)) { // FIXME: we expect arr elmt!
00539         TY2F_Translate_ArrayElt(xos, base_ty, offset);
00540         ctxt.currentXlationContext().unsetFlag(XlationContext::HAS_NO_ARR_ELMT);
00541       }
00542     }
00543     else {
00544       // 5. 
00545       //FORTTK_DIE("Unknown ref type.");
00546       translate_var_ref(xos, base_st, ctxt);
00547 
00548 #if 0 // FIXME:REMOVE
00549       /* We only dereference a field when the base need not be 
00550        * dereferenced.  We never need to have both dereferenced, 
00551        * since pointers cannot occur in RECORDS and common/
00552        * equivalence blocks cannot be referenced through pointer 
00553        * identifiers. */
00554       FLD_PATH_INFO *fld_path = NULL;
00555       BOOL deref_fld;
00556       if ( !(TY_IsRecord(ref_ty) /* && FIXME*/) ) {
00557         deref_fld = (deref_val && !TY_Is_Pointer(ST_type(base_st))) ? TRUE:FALSE;
00558         if (deref_fld) { ref_ty = Stab_Pointer_To(ref_ty); }
00559         fld_path = TY2F_Get_Fld_Path(base_ty, ref_ty, offset);
00560       }
00561     
00562       if (fld_path == NULL) {
00563         translate_var_ref(xos, base_st, ctxt);
00564       } 
00565       else if (Stab_Is_Common_Block(base_st)) {
00566         // Common block reference (do not translate as field ref)
00567         // FIXME: make sure the fld_path is length 1 
00568         ST_IDX st_idx = fld_path->fld.Entry()->st;
00569         ST* st = (st_idx != 0) ? ST_ptr(st_idx) : NULL;
00570         if (st) {
00571           translate_var_ref(xos, st, ctxt);
00572         } 
00573         else { // FIXME
00574           TY2F_Translate_Fld_Path(xos, fld_path, deref_fld, 
00575                                   // (Stab_Is_Common_Block(base_st) || 
00576                                   //  Stab_Is_Equivalence_Block(base_st)),
00577                                   TRUE, FALSE/*as_is*/, ctxt);
00578         }
00579 
00580       } else {
00581       
00582         // Structure: 
00583         /* Base the path at the 'base_st' object, and separate it from
00584          * the remainder of the path with the field selection operator. */
00585         translate_var_ref(xos, base_st, ctxt);
00586         TY2F_Fld_Separator(xos);
00587         TY2F_Translate_Fld_Path(xos, fld_path, deref_fld, 
00588                                 // (Stab_Is_Common_Block(base_st) || 
00589                                 //  Stab_Is_Equivalence_Block(base_st)),
00590                                 FALSE, FALSE/*as_is*/, ctxt);
00591       }
00592       if (fld_path) { TY2F_Free_Fld_Path(fld_path); }
00593 #endif
00594 
00595     }
00596 
00597     if (newContext) {
00598       ctxt.deleteXlationContext();
00599       xos << xml::EndElem /* elem_VarRef() */;
00600     }
00601   
00602     
00603   } /* xlate_SymRef */
00604 
00605 
00606   // xlate_MemRef: 
00607   void
00608   xlate_MemRef(xml::ostream& xos, 
00609                WN*    addr,        // base-address expr
00610                TY_IDX addr_ty,     // type of base-address
00611                TY_IDX ref_ty,      // type of referenced object
00612                STAB_OFFSET offset, // offset from base-address
00613                PUXlationContext& ctxt)
00614   {
00615     /* Given an address expression and an offset from this address,
00616      * append a Fortran expression to "xos" to reference an object of
00617      * type 'ref_ty' at this offset address.  In effect, we dereference
00618      * the address to 'ref_ty'.
00619     
00620      FIXME
00621      * is a dereferencing operation on the base-address. The resultant
00622      * value (e.g. after a struct-field access) may be further
00623      * dereferenced.
00624      *
00625      * The address expression is unconditionally treated as an expression
00626      * of the addr_ty.
00627      *
00628      * For non-zero offsets, or when "!WN2F_Can_Assign_Types(ref_ty,
00629      * TY_pointed(addr_ty))", we expect the base-address to denote the
00630      * address of a structure or an array, where an object of the given 
00631      * ref_ty can be found at the given offset.
00632      *
00633      * Since Fortran does not have an explicit (only implicit) dereference
00634      * operation we cannot first calculate the address and then 
00635      * dereference. This constrains the kind of expression we may handle
00636      * here.  Note that equivalences and common-blocks always should be 
00637      * accessed through an LDID or an LDA(?) node.  */
00638   
00639     WN* ref_wn = ctxt.getMostRecentWN();
00640     TY_IDX base_ty = TY_pointed(addr_ty);
00641     const BOOL deref_fld = ctxt.currentXlationContext().isFlag(XlationContext::DEREF_ADDR);
00642   
00643     // -------------------------------------------------------
00644     //
00645     // -------------------------------------------------------
00646     bool constant = (WN_operator(addr) == OPR_LDA 
00647                      && ST_class(WN_st(addr)) == CLASS_CONST);
00648     bool newContext = false; 
00649     if (!constant && !ctxt.currentXlationContext().isFlag(XlationContext::VARREF)) {
00650       // FIXME: for du_ud numbers; ARRAY, not ILOAD, is top of ref
00651       WN* wn = ref_wn;
00652       if (WN_operator(wn) == OPR_ILOAD 
00653           && WN_operator(WN_kid0(wn)) == OPR_ARRAY) {
00654         wn = WN_kid0(wn);
00655       }
00656     
00657       xos << xml::BegElem(XAIFStrings.elem_VarRef())
00658           << xml::Attr("vertex_id", ctxt.currentXlationContext().getNewVertexId())
00659           << xml::Attr("du_ud", ctxt.findUDDUChainId(wn))
00660           << xml::Attr("alias", ctxt.getAliasMapKey(wn));
00661       ctxt.createXlationContext(XlationContext::VARREF); // FIXME: do we need wn?
00662       newContext = true; 
00663     }
00664   
00665   
00666     // -------------------------------------------------------
00667     //
00668     // -------------------------------------------------------
00669   
00670     // FIXME: for now, make sure this is only used for data refs 
00671     if (TY_kind(base_ty) == KIND_FUNCTION) {
00672       FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "memref FIXME");
00673     }
00674 
00675 
00676     /* Prepare to dereference the base-address expression */
00677     ctxt.currentXlationContext().setFlag(XlationContext::DEREF_ADDR);
00678   
00679     if (WN2F_Is_Address_Preg(addr, addr_ty)) { // FIXME
00680       /* Optimizer may put address PREGS into ARRAYs */
00681       /* and high level type is more or less useless */
00682       /* just go with WN tree ADDs etc.              */
00683       TranslateWN(xos, addr, ctxt);    
00684       if (offset != 0) {
00685         xos << '+' << offset /* "%lld" */;
00686       }
00687     } 
00688     else {
00689       fortTkSupport::ScalarizedRef* sym = ctxt.findScalarizedRef(ref_wn);
00690       if (!sym && WN_operator(addr) == OPR_STRCTFLD) {
00691         sym = ctxt.findScalarizedRef(addr);
00692       }
00693       if (sym) { 
00694         // 1. A scalarized symbol
00695         ST_TAB* sttab = Scope_tab[CURRENT_SYMTAB].st_tab;
00696         fortTkSupport::SymTabId scopeid = ctxt.findSymTabId(sttab);
00697       
00698         xos << xml::BegElem("xaif:SymbolReference") 
00699             << xml::Attr("vertex_id", ctxt.currentXlationContext().getNewVertexId())
00700             << xml::Attr("scope_id", scopeid) 
00701             << xml::Attr("symbol_id", sym->getName().c_str()) << xml::EndElem;
00702       } 
00703       else if (fortTkSupport::ScalarizedRef::isRefScalar(base_ty, ref_ty) 
00704                || 
00705                fortTkSupport::ScalarizedRef::isRefSimpleScalar(ref_wn)) {
00706         // 2. Reference to a scalar symbol (==> offset into 'base_st' is zero)
00707         TranslateWN(xos, addr, ctxt);
00708       } 
00709       else if (TY_Is_Array(ref_ty) || TY_Is_Array(base_ty)) { // FIXME
00710         // 3. Array reference (non-scalar)
00711         bool hasArrayElmt = !ctxt.currentXlationContext().isFlag(XlationContext::HAS_NO_ARR_ELMT);
00712         if (TY_Is_Character_String(base_ty)) {
00713           TranslateWN(xos, addr, ctxt); /* String lvalue */
00714           if (hasArrayElmt) {
00715             TY2F_Translate_ArrayElt(xos, base_ty, offset);
00716           }
00717         } 
00718         else {
00719           TranslateWN(xos, addr, ctxt); /* Array */
00720           if (hasArrayElmt) {
00721             TY2F_Translate_ArrayElt(xos, base_ty, offset);
00722           }
00723           else {
00724             ctxt.currentXlationContext().unsetFlag(XlationContext::HAS_NO_ARR_ELMT);
00725           }
00726         }    
00727       } 
00728       else if ((WN_operator(addr) == OPR_LDA || WN_operator(addr) == OPR_LDID) 
00729                && (TY_kind(base_ty) != KIND_STRUCT)
00730                && (Stab_Is_Common_Block(WN_st(addr)) 
00731                    || Stab_Is_Equivalence_Block(WN_st(addr)))) {
00732       
00733         // 4. A common-block or equivalence-block, both of which we
00734         // handle only in xlate_SymRef().
00735         FORTTK_ASSERT_WARN(WN2F_Can_Assign_Types(ST_type(WN_st(addr)), base_ty),
00736                            "Incompatible types");
00737       
00738         if (WN_operator(addr) == OPR_LDA) {
00739           ctxt.currentXlationContext().unsetFlag(XlationContext::DEREF_ADDR);
00740         }
00741         xlate_SymRef(xos, WN_st(addr), addr_ty, ref_ty,
00742                      offset + WN_lda_offset(addr) /*offset*/, ctxt);
00743       }
00744       else {       
00745         // 5. Field access (Neither common-block nor equivalence)
00746         // Find the path to the field we wish to access and append
00747         // this path to the base-object reference.
00748       
00749         /* Get any offset given by an address ADDition node.  The type
00750          * of the addition, as given by WN_Tree_Type(), is the type
00751          * of base-object within which we are accessing, so the addr_ty
00752          * is already set up correctly to handle the combined offsets.
00753          */
00754         TranslateWN(xos, addr, ctxt);
00755 
00756 #if 0 // FIXME:REMOVE
00757         WN_OFFSET tmp = WN2F_Sum_Offsets(addr);
00758         if (tmp < TY_size(TY_pointed(addr_ty)))
00759           offset += tmp;
00760         else 
00761           offset = tmp;
00762       
00763         FLD_PATH_INFO* fld_path = TY2F_Get_Fld_Path(base_ty, ref_ty, offset);
00764         FORTTK_ASSERT_WARN(fld_path != NULL, "Non-existent FLD path");
00765       
00766         /* May have ARRAY(ADD(ARRAY(LDA),CONST)) or some such. */
00767         /* The deepest ARRAY (with the address) is handled     */
00768         /* by the xlate_ARRAY processing, but the others        */
00769         /* are field references with array components.         */
00770         LOC_INFO det(fld_path);
00771         det.WN2F_Find_And_Mark_Nested_Address(addr);
00772         addr = det._nested_addr;
00773       
00774         /* Get the base expression to precede the path */
00775         TranslateWN(xos, addr, ctxt);
00776         TY2F_Fld_Separator(xos);
00777       
00778         /* Append the path-name, perhaps w/o array subscripts. */
00779         if (fld_path != NULL) {
00780           TY2F_Translate_Fld_Path(xos, fld_path, deref_fld, 
00781                                   FALSE/*common*/, FALSE/*as_is*/, ctxt);
00782           TY2F_Free_Fld_Path(fld_path);
00783         } 
00784         else {
00785           xos << "field-at-offset=" << offset /* %lld */;
00786         }
00787 #endif
00788       }    
00789     }
00790 
00791     if (newContext) {
00792       ctxt.deleteXlationContext();
00793       xos << xml::EndElem /* elem_VarRef() */;
00794     }
00795 
00796     
00797   } /* xlate_MemRef */
00798 
00799 
00800   void 
00801   LOC_INFO::WN2F_Find_And_Mark_Nested_Address(WN * addr)
00802   {
00803     /* If this address expression contains nested ARRAY nodes */
00804     /* (and isn't a character expression), the ARRAYs refer   */
00805     /* to structure components, eg: aaa(1).kkk(3) yields      */
00806     /* ARRAY(ADD(const,ARRAY(LDA)). Add a pointer to the      */
00807     /* array elements of the fld path, associating each with  */
00808     /* corresponding OPC_ARRAY. TY2F_Translate_Fld_Path will  */
00809     /* write the subscript list.                              */
00810 
00811     /* In general, just the lowest LDID/LDA remains to be     */
00812     /* processed, however if the lowest ARRAY node is not a   */
00813     /* fld, and belongs to the address ST, then return that   */
00814     /* ARRAY.                                                 */
00815     OPERATOR opr = WN_operator(addr);
00816     switch (opr)
00817       {
00818       case OPR_ARRAY: 
00819       case OPR_ARRAYEXP: 
00820       case OPR_ARRSECTION:
00821         {
00822           WN * kid;     
00823 
00824           if (WN_operator(addr)==OPR_ARRAYEXP)
00825             addr = WN_kid0(addr);
00826 
00827           kid = WN_kid0(addr);
00828           WN2F_Find_And_Mark_Nested_Address(kid);
00829 
00830           if ((_flds_left && _flds_left->arr_elt) &&
00831               (!(_base_is_array)))
00832             {
00833               _flds_left-> arr_wn = addr;
00834               _flds_left = TY2F_Point_At_Path(_flds_left,_off);
00835             } 
00836           else 
00837             _nested_addr = addr;
00838 
00839           _base_is_array = FALSE;
00840         }
00841         break;
00842 
00843 
00844       case OPR_ADD:
00845         {
00846           WN * cnst = WN_kid0(addr);
00847           WN * othr = WN_kid1(addr);
00848 
00849           if (WN_operator(cnst) != OPR_INTCONST) 
00850             {
00851               cnst = WN_kid1(addr);
00852               othr = WN_kid0(addr);
00853             }
00854           WN2F_Find_And_Mark_Nested_Address(othr);
00855           _off = WN_const_val(cnst);
00856           _flds_left = TY2F_Point_At_Path(_flds_left,_off);
00857           _base_is_array = FALSE;
00858         }
00859         break;
00860 
00861       case OPR_LDID:
00862         _off = 0;
00863         _nested_addr = addr;
00864         _flds_left = TY2F_Point_At_Path(_flds_left,_off);
00865         _base_is_array = ((TY_kind(WN_ty(addr)) == KIND_POINTER) && 
00866                           (TY_kind(TY_pointed(WN_ty(addr))) == KIND_ARRAY));
00867         break;
00868 
00869       case OPR_LDA:
00870         _off = WN_lda_offset(addr);
00871         _nested_addr = addr;
00872         _flds_left = TY2F_Point_At_Path(_flds_left,_off);
00873         _base_is_array = ((TY_kind(WN_ty(addr)) == KIND_POINTER) && 
00874                           (TY_kind(TY_pointed(WN_ty(addr))) == KIND_ARRAY));
00875         break;
00876 
00877       case OPR_ILOAD:
00878         _off = 0;
00879         _nested_addr = addr;
00880         _flds_left = TY2F_Point_At_Path(_flds_left,0);
00881         _base_is_array = ((TY_kind(WN_ty(addr)) == KIND_POINTER) && 
00882                           (TY_kind(TY_pointed(WN_ty(addr))) == KIND_ARRAY));
00883         break;
00884 
00885       default:
00886         FORTTK_DIE(fortTkSupport::Diagnostics::UnexpectedOpr << OPERATOR_name(opr));
00887         break;
00888       }
00889     return;
00890   }
00891 
00892 
00893   WN_OFFSET
00894   WN2F_Sum_Offsets(WN *addr)
00895   {
00896     /* Accumulate any offsets (ADDs) in this address   */
00897     /* tree. Used for computing Fld paths              */
00898     BOOL sum = 0;
00899 
00900     switch (WN_operator(addr)) {
00901     case OPR_ARRAY: 
00902     case OPR_ARRAYEXP:
00903     case OPR_ARRSECTION:
00904       if (WN_operator(addr)==OPR_ARRAYEXP)
00905         addr = WN_kid0(addr);
00906     
00907       sum += WN2F_Sum_Offsets(WN_kid0(addr));
00908       break;
00909     
00910     case OPR_ADD:
00911       sum += WN2F_Sum_Offsets(WN_kid0(addr));
00912       sum += WN2F_Sum_Offsets(WN_kid1(addr));
00913       break;
00914     
00915     case OPR_INTCONST:
00916       sum = WN_const_val(addr);
00917       break;
00918 
00919     default: 
00920       break; // fall through
00921     }
00922     return sum;
00923   }
00924 
00925 
00926   void 
00927   WN2F_Address_Of(xml::ostream& xos)
00928   {
00929     //REMOVE Prepend_Token_Special(xos, '(');
00930     //REMOVE Prepend_Token_String(xos, "loc%");
00931     xos << "loc%()"; // FIXME
00932   }
00933 
00934   DGraphNodeVec*
00935   SortDGraphNodes(OA::OA_ptr<OA::DGraph::DGraphInterface> g)
00936   {
00937     DGraphNodeVec* vec = new DGraphNodeVec(g->getNumNodes());
00938 
00939     OA::OA_ptr<OA::DGraph::NodesIteratorInterface> it = g->getNodesIterator();
00940     for (int i = 0; it->isValid(); ++(*it), ++i) {
00941       (*vec)[i] = it->current();
00942     }
00943   
00944     // Sort by id (ascending)
00945     //std::sort(vec->begin(), vec->end(), (*(g->getNodeCompare())));
00946     std::sort(vec->begin(), vec->end(), OA::DGraph::lt_Node());
00947   
00948     return vec;
00949   }
00950 
00951   DGraphEdgeVec*
00952   SortDGraphEdges(OA::OA_ptr<OA::DGraph::DGraphInterface> g)
00953   {
00954     DGraphEdgeVec* vec = new DGraphEdgeVec(g->getNumEdges());
00955 
00956     OA::OA_ptr<OA::DGraph::EdgesIteratorInterface> it = g->getEdgesIterator();
00957     for (int i = 0; it->isValid(); ++(*it), ++i) {
00958       (*vec)[i] = it->current();
00959     }
00960   
00961     // Sort by source/target node ids (ascending)
00962     std::sort(vec->begin(), vec->end(), OA::DGraph::lt_Edge()); 
00963   
00964     return vec;
00965   }
00966 
00967 
00968   CFGEdgeVec*
00969   SortCFGEdges(OA::OA_ptr<OA::CFG::CFGInterface> g)
00970   {
00971     CFGEdgeVec* vec = new CFGEdgeVec(g->getNumEdges());
00972 
00973     OA::OA_ptr<OA::DGraph::EdgesIteratorInterface> it = g->getEdgesIterator();
00974     for (int i = 0; it->isValid(); ++(*it), ++i) {
00975       (*vec)[i] = it->current().convert<OA::CFG::Edge>();
00976     }
00977   
00978     // Sort by source/target node ids (ascending)
00979     std::sort(vec->begin(), vec->end(), lt_CFGEdge()); 
00980   
00981     return vec;
00982   }
00983 
00984 
00985   // DumpGraphEdge: see header.
00986   void 
00987   DumpGraphEdge(xml::ostream& xos, const char* nm, 
00988                 UINT eid, UINT srcid, UINT targid, UINT pos)
00989   {
00990     xos << xml::BegElem(nm) 
00991         << xml::Attr("edge_id", eid) 
00992         << xml::Attr("source", srcid) << xml::Attr("target", targid);
00993     if (pos >= 1) {
00994       xos << xml::Attr("position", pos);
00995     }
00996     xos << xml::EndElem;
00997   }
00998 
00999 
01000   // DumpCFGraphEdge: Dump a CFG edge
01001   static void
01002   DumpCFGraphEdge(xml::ostream& xos, UINT eid, 
01003                   OA::OA_ptr<OA::CFG::EdgeInterface> edge)
01004   {
01005     using namespace OA::CFG;
01006 
01007     OA::OA_ptr<OA::DGraph::NodeInterface> dn1 = edge->getSource();
01008     OA::OA_ptr<OA::CFG::Node> n1 = dn1.convert<OA::CFG::Node>();
01009     OA::OA_ptr<OA::DGraph::NodeInterface> dn2 = edge->getSink();
01010     OA::OA_ptr<OA::CFG::Node> n2 = dn2.convert<OA::CFG::Node>();
01011   
01012     pair<bool, INT64> ret = GetCFGEdgeCondVal(edge);
01013     bool hasCondVal = ret.first;
01014     INT64 condVal = ret.second;
01015 
01016     xos << xml::BegElem("xaif:ControlFlowEdge") 
01017         << xml::Attr("edge_id", eid) 
01018         << xml::Attr("source", n1->getId()) << xml::Attr("target", n2->getId());
01019     if (hasCondVal) {
01020       xos << xml::Attr("has_condition_value", "true")
01021           << xml::Attr("condition_value", condVal);
01022     }
01023     xos << xml::EndElem;
01024   }
01025 
01026   typedef std::set<ST *> SymbolPointerSet;
01027 
01028   void 
01029   xlate_SideEffectLocationPrint(ST* st, 
01030                                 SymbolPointerSet& coveredSymbols,
01031                                 fortTkSupport::SymTabId scopeid,
01032                                 xml::ostream& xos) {
01033     if (coveredSymbols.find(st)==coveredSymbols.end())
01034       coveredSymbols.insert(st);
01035     else { 
01036       const char* nm=ST_name(st);
01037       FORTTK_MSG(2, "xlate_SideEffectLocationPrint: ignoring duplicate symbol " << nm);
01038       return; 
01039     }
01040     // the wrapper for the VariableReference: 
01041     xos << xml::BegElem("xaif:SideEffectReference")
01042         << xml::Attr("vertex_id", "1");
01043   
01044     // the contents, i.e. the SymbolReference
01045     xos << xml::BegElem("xaif:SymbolReference")
01046         << xml::Attr("vertex_id", "1")
01047         << xml::Attr("scope_id", scopeid) 
01048         << AttrSymId(st)
01049         << xml::EndElem;
01050     xos << xml::EndElem;
01051   } 
01052 
01053 
01054   void 
01055   xlate_SideEffectNamedLocation(OA::OA_ptr<OA::NamedLoc> theNamedLoc,
01056                                 SymbolPointerSet& coveredSymbols,
01057                                 xml::ostream& xos, 
01058                                 WN *wn, 
01059                                 PUXlationContext& ctxt,
01060                                 OA::OA_ptr<OA::SymHandleIterator> formalArgSymHandleI) 
01061   { 
01062     // OA may include constants in the location lists.  We filter them
01063     // out because they are not in the XAIF symbol table.
01064     ST* st = (ST*)theNamedLoc->getSymHandle().hval();
01065     ST_TAB* sttab = Scope_tab[ST_level(st)].st_tab;
01066     fortTkSupport::SymTabId scopeid = ctxt.findSymTabId(sttab);
01067     // this is a temporary fix to a problem in the analysis 
01068     // for the following case: 
01069     // a symbol SY occurs in the sideffect list of routine R
01070     // as a consequence of R calling FOO, SY is declared within 
01071     // FOO (i.e. ST_level is 2) and referenced in BAR that is 
01072     // contained in FOO.  Because SY is from the enclosing scope
01073     // it is considered "not" local to BAR 
01074     // (see also comments in Open64IRInterface.cpp:3715 ff.)
01075     // Presumably somewhere in OA then the assumption is made 
01076     // that anything not local is global and it ends up 
01077     // in the R's side effect list. To be global, however,
01078     // it would have to have ST_level 1 or at least 
01079     // a level higher than the current PU. If it is not 
01080     // we will assume the above case and just return.
01081     // A similar problem also occurs when sideeffects are 
01082     // transferred from a module procedure to the place where the 
01083     // module is used. 
01084     UINT32 anIndex=ST_index(st);
01085     // we may not even have that index because the symbol comes from a large symbol table:
01086     if (anIndex>=sttab->Size()){ 
01087       ST* puStP = ST_ptr(PU_Info_proc_sym(Current_PU_Info));
01088       const char* puName = ST_name(puStP);
01089       FORTTK_WMSG("xlate_SideEffectNamedLocation: ignoring symbol " << ST_name(st) << " (symbol index " << anIndex << " is out of bounds of current symbol table indicating it is invisible in " << puName << ")"); 
01090       return;
01091     }
01092     // if the symbol is visible we should find it in sttab via level/index:
01093     ST& anotherST=St_Table[ST_st_idx(*st)];
01094     if (&anotherST != st) { 
01095       ST* puStP = ST_ptr(PU_Info_proc_sym(Current_PU_Info));
01096       const char* puName = ST_name(puStP);
01097       FORTTK_WMSG("xlate_SideEffectNamedLocation: ignoring symbol " << ST_name(st) << " (resolves in the current symbol table to " << ST_name(&anotherST) << " indicating it is invisible in " << puName << ")"); 
01098       return;
01099     }
01100     if (ST_class(st) == CLASS_CONST) {
01101       return;
01102     }
01103 
01104     if (theNamedLoc->isLocal()) { 
01105       // we don't want local variables except 
01106       // if it is a formal parameter
01107       bool foundAsFormalArgument=false;
01108       formalArgSymHandleI->reset();
01109       while (formalArgSymHandleI->isValid()) { 
01110         //       // JU: debugging prepare begin
01111         //       const char* nm=ST_name(st);
01112         //       ST* st1=(ST*)formalArgSymHandleI->current().hval();
01113         //       const char* nm1=ST_name(st1);
01114         //       // JU: debugging prepare end
01115         if (formalArgSymHandleI->current()==theNamedLoc->getSymHandle()) { 
01116           // is a formal paramter
01117           foundAsFormalArgument=true;
01118           //    // JU: debugging begin
01119           //    std::cout << "xlate_SideEffectNamedLocation: matched " << nm << " with " << nm1 << std::endl;  
01120           //    // JU: debugging end
01121           break;
01122         }
01123         //       // JU: debugging begin
01124         //       else { 
01125         //      std::cout << "xlate_SideEffectNamedLocation: did not match " << nm << " with " << nm1 << std::endl;  
01126         //       }
01127         //       // JU: debugging end
01128         ++(*formalArgSymHandleI);
01129       }
01130       if (!foundAsFormalArgument) { 
01131         return;
01132       }
01133     }
01134     else { 
01135       ST_IDX stLevel=ST_level(st), puStLevel=PU_lexical_level(ST_ptr(PU_Info_proc_sym(Current_PU_Info)));
01136       bool inCurrentSt=false;
01137       // third spot of weeding out invisible symbols: 
01138       if (stLevel==puStLevel) { 
01139         // see if we can find it...
01140         for (INT i = 1; 
01141              i < ST_Table_Size(stLevel) ; 
01142              ++i) { 
01143           // get the symbol from the table
01144           ST* an_ST_p=&(St_Table(stLevel,i));
01145           if (an_ST_p==st) {// same (not just equal) instance
01146             inCurrentSt=true; 
01147             break; 
01148           }
01149         }
01150       }
01151       if((stLevel==puStLevel && !inCurrentSt) || stLevel>puStLevel) { 
01152         ST* puStP = ST_ptr(PU_Info_proc_sym(Current_PU_Info));
01153         const char* puName = ST_name(puStP);
01154         FORTTK_WMSG("xlate_SideEffectNamedLocation: ignoring symbol " << ST_name(st) << " (nesting level " << (unsigned short)stLevel << ") which is invisible in " << puName << " (nesting level " << (unsigned short)puStLevel << ")"); 
01155         return; 
01156       }
01157     } 
01158     xlate_SideEffectLocationPrint(st,coveredSymbols,scopeid, xos);
01159   }
01160 
01161   void 
01162   xlate_SideEffectEntry(OA::OA_ptr<OA::Location> theTopLocation,
01163                         OA::OA_ptr<OA::Location> theLocation,
01164                         SymbolPointerSet& coveredSymbols,
01165                         xml::ostream& xos, 
01166                         WN *wn, 
01167                         PUXlationContext& ctxt,
01168                         OA::OA_ptr<OA::SymHandleIterator> formalArgSymHandleI) { 
01169     if (theLocation->isaNamed()) { 
01170       // get the named location
01171       OA::OA_ptr<OA::NamedLoc> namedLoc=
01172         theLocation.convert<OA::NamedLoc>();
01173       xlate_SideEffectNamedLocation(namedLoc,
01174                                     coveredSymbols,
01175                                     xos, 
01176                                     wn, 
01177                                     ctxt,
01178                                     formalArgSymHandleI);
01179     }
01180     else if (theLocation->isaInvisible()) { 
01181       // get the invisible location's symbol
01182       OA::OA_ptr<OA::InvisibleLoc> theInvisibleLoc=
01183         theLocation.convert<OA::InvisibleLoc>();
01184       ST* st = (ST*)theInvisibleLoc->getBaseSym().hval();
01185       ST_TAB* sttab = Scope_tab[ST_level(st)].st_tab;
01186       fortTkSupport::SymTabId scopeid = ctxt.findSymTabId(sttab);
01187       xlate_SideEffectLocationPrint(st,coveredSymbols,scopeid, xos);
01188     }
01189     else if (theLocation->isaSubSet()) { 
01190       OA::OA_ptr<OA::LocSubSet> subSetLoc=
01191         theLocation.convert<OA::LocSubSet>();
01192       xlate_SideEffectEntry(theTopLocation,
01193                             subSetLoc->getLoc(),
01194                             coveredSymbols,
01195                             xos, 
01196                             wn, 
01197                             ctxt,
01198                             formalArgSymHandleI);
01199     }
01200     else if (theLocation->isaUnnamed()) { 
01201       OA::OA_ptr<OA::UnnamedLoc> theUnnamedLoc=
01202         theLocation.convert<OA::UnnamedLoc>();
01203       // save the context because "toString" may change it
01204       PU_Info* thisPU=Current_PU_Info;
01205       WN* wn_p((WN*)theUnnamedLoc->getExprHandle().hval());
01206       if (wn_p 
01207           && 
01208           (WN_operator(wn_p)==OPR_CONST
01209            ||
01210            WN_operator(wn_p)==OPR_INTCONST
01211            ||
01212            (WN_has_sym(wn_p) 
01213             &&
01214             ST_class(WN_st(wn_p))==CLASS_CONST))) { 
01215         FORTTK_MSG(2, "xlate_SideEffectEntry: side effect list contains an unnamed location for: " << ctxt.getIrInterface().toString(theUnnamedLoc->getExprHandle()));
01216       }
01217       else { 
01218         FORTTK_MSG(1, "xlate_SideEffectEntry: side effect list contains an unnamed location for: " << ctxt.getIrInterface().toString(theUnnamedLoc->getExprHandle()));
01219       }
01220       if (Current_PU_Info!=thisPU) 
01221         PU_SetGlobalState(thisPU);
01222     } 
01223     else if (theLocation->isaUnknown()) { 
01224       ST* pu_st = ST_ptr(PU_Info_proc_sym(Current_PU_Info));
01225       const char* pu_nm = ST_name(pu_st);
01226       FORTTK_MSG(2,"xlate_SideEffectEntry: side effect list for " << pu_nm << " contains an unknown location.");
01227     } 
01228     else { 
01229       ST* pu_st = ST_ptr(PU_Info_proc_sym(Current_PU_Info));
01230       const char* pu_nm = ST_name(pu_st);
01231       FORTTK_MSG(0,"xlate_SideEffectEntry: descended from top location:");
01232       theTopLocation->dump(std::cerr);
01233       FORTTK_MSG(0,"xlate_SideEffectEntry: down to locaton:");
01234       theLocation->dump(std::cerr);
01235       FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "side effect list for " << pu_nm << " contains an unexpected location (see location dumps above)");
01236     }
01237   } 
01238 
01243   static void findVarSymbolsInTree(WN *wn, 
01244                                    SymbolPointerSet& requiredSymbols) {
01245     if (WN_has_sym(wn)) { 
01246       ST* st=WN_st(wn); 
01247       if ( ST_class(st)==CLASS_VAR && !ST_is_temp_var(st))
01248         // we need to avoid picking up things like integer conversion calls
01249         requiredSymbols.insert(st);
01250     }
01251     for (INT kid = 0; kid < WN_kid_count(wn); kid++) { 
01252       WN *kidWN_p=WN_kid(wn,kid);
01253       if (kidWN_p)
01254         findVarSymbolsInTree(kidWN_p,
01255                              requiredSymbols);
01256     }
01257   } 
01258 
01264   static void findRequiredProgramSymbols(WN* wn,
01265                                          PUXlationContext& ctxt,
01266                                          SymbolPointerSet& requiredTempSymbols,
01267                                          SymbolPointerSet& requiredProgramSymbols) { 
01268     FORTTK_ASSERT(WN_operator(wn) == OPR_FUNC_ENTRY, fortTkSupport::Diagnostics::UnexpectedInput);
01269     // go to the body
01270     WN* theLastBlock=WN_kid(wn,WN_kid_count(wn)-1);
01271     FORTTK_ASSERT(WN_operator(theLastBlock)==OPR_BLOCK, fortTkSupport::Diagnostics::UnexpectedInput); 
01272     if (WN_first(theLastBlock)==0) 
01273       return;
01274     WN* childWN=WN_first(theLastBlock);
01275     while (childWN!=0) { 
01276       OPERATOR childOpr=WN_operator(childWN);
01277       if (childOpr==OPR_STID) { 
01278         ST* st=WN_st(childWN); 
01279         if (requiredTempSymbols.find(st)!=requiredTempSymbols.end()) { 
01280           findVarSymbolsInTree(childWN,
01281                             requiredProgramSymbols);
01282           requiredTempSymbols.erase(st);
01283         }
01284       } 
01285       childWN=WN_next(childWN);
01286     }
01287   } 
01288 
01289 
01295   class SearchSymbolTableEntry {
01296   public:
01297     SearchSymbolTableEntry(PUXlationContext& ctxt,
01298                            SymbolPointerSet& requiredSymbols) :
01299       myCtxt(ctxt),
01300       myRequiredSymbols(requiredSymbols){ 
01301     } 
01302 
01307     void operator()(UINT32 idx, ST* st) const {
01308       // must be formal parameter of local variable declaration
01309       if (ST_class(st)!=CLASS_VAR)
01310         return;
01311       TY_IDX tyIdx=ST_type(st); 
01312       TY_KIND tyKind=TY_kind(tyIdx);
01313       // must be a local array or a pointer to an array (for formal parameters)
01314       // except for strings
01315       if (tyKind!=KIND_ARRAY && tyKind!=KIND_POINTER
01316           ||
01317           TY_Is_Character_String(tyIdx)) 
01318         return; 
01319       while (tyKind==KIND_POINTER) { 
01320         tyIdx=TY_pointed(tyIdx);
01321         tyKind=TY_kind(tyIdx);
01322         if (tyKind!=KIND_POINTER) { 
01323           if (tyKind==KIND_ARRAY
01324               && 
01325               !TY_Is_Character_String(tyIdx))
01326             break; 
01327           else
01328             return; 
01329         }
01330       }
01331       // now we are looking at an array and can search the array bounds
01332       TY& ty = Ty_Table[tyIdx];
01333       ARB_HANDLE arbBaseHandle = TY_arb(ty);
01334       INT32 dim = ARB_dimension(arbBaseHandle) ;
01335       INT32 coDim = ARB_co_dimension(arbBaseHandle);
01336       FORTTK_ASSERT(coDim == 0,
01337                     fortTkSupport::Diagnostics::UnexpectedInput);      
01338       for (int i=0; i<dim; i++) {
01339         // lbound: 
01340         if (!ARB_const_lbnd(arbBaseHandle[i])
01341             && 
01342             !ARB_empty_lbnd(arbBaseHandle[i])) {
01343           // get the array bounds entry
01344           ST_IDX stIdx=ARB_lbnd_var(arbBaseHandle[i]);
01345           if (stIdx!=0) { 
01346             myRequiredSymbols.insert(&(St_Table[stIdx]));
01347           } 
01348         }
01349         // ubound: 
01350         if (!ARB_const_ubnd(arbBaseHandle[i])
01351             && 
01352             !ARB_empty_ubnd(arbBaseHandle[i])) {
01353           // get the array bounds entry
01354           ST_IDX stIdx=ARB_ubnd_var(arbBaseHandle[i]);
01355           if (stIdx!=0) { 
01356             myRequiredSymbols.insert(&(St_Table[stIdx]));
01357           }
01358         }
01359         // stride: 
01360         if (!ARB_const_stride(arbBaseHandle[i])
01361             && 
01362             !ARB_empty_stride(arbBaseHandle[i])) { 
01363           // get the array bounds entry
01364           ST_IDX stIdx=ARB_stride_var(arbBaseHandle[i]);
01365           if (stIdx!=0) { 
01366             myRequiredSymbols.insert(&(St_Table[stIdx]));
01367           }
01368         }
01369       }
01370     }
01371   
01372   private:
01373     SYMTAB_IDX      mySymtab;
01374     PUXlationContext& myCtxt;  
01375     SymbolPointerSet& myRequiredSymbols;
01376   };
01377 
01383   static void findRequiredSymbolsInSymbolTable(SYMTAB_IDX symtab_lvl, 
01384                                                PUXlationContext& ctxt,
01385                                                SymbolPointerSet& requiredSymbols) {
01386     For_all(St_Table, symtab_lvl, SearchSymbolTableEntry(ctxt,
01387                                                          requiredSymbols));
01388   }
01389 
01390 
01391   // xlate_EntryPoint: Translates a function entry or alternate entry
01392   // point, with parameter declarations.  
01393   // FIXME: XAIF doesn't support alt-entry.
01394   static void
01395   xlate_EntryPoint(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) {
01396     OPERATOR opr = WN_operator(wn);
01397     FORTTK_ASSERT(opr == OPR_ALTENTRY || opr == OPR_FUNC_ENTRY,
01398                   fortTkSupport::Diagnostics::UnexpectedInput);
01399   
01400     ST* func_st = &St_Table[WN_entry_name(wn)];
01401     TY_IDX func_ty = ST_pu_type(func_st);
01402     TY_IDX return_ty = Func_Return_Type(func_ty);
01403   
01404     // Accumulate the parameter ST entries  // FIXME: GetParamSymHandleSet
01405     INT nparam = (opr == OPR_ALTENTRY) ? WN_kid_count(wn) : WN_num_formals(wn);
01406     ST** params_st = (ST **)alloca((nparam + 1) * sizeof(ST *));  
01407     for (INT parm = 0; parm < nparam; parm++) {
01408       params_st[parm] = WN_st(WN_formal(wn, parm));
01409     }
01410     params_st[nparam] = NULL; // terminate the list
01411 
01412     // Parameter name-list. Skip any implicit "length" parameters
01413     // associated with character strings.  Such implicit parameters
01414     // should be at the end of the parameter list. FIXME
01415     xos << xml::BegElem("xaif:ArgumentList");
01416   
01417     INT first_parm = ST2F_FIRST_PARAM_IDX(func_ty);
01418     INT implicit_parms = 0;
01419     UINT position = 1;
01420     for (INT parm = first_parm; parm < (nparam - implicit_parms); parm++) {
01421 
01422       WN* parm_wn = WN_formal(wn, parm);    
01423       ST* parm_st = params_st[parm]; //WN_st(parm_wn);
01424     
01425       if (!ST_is_return_var(parm_st)) {
01426         ST_TAB* sttab = Scope_tab[ST_level(parm_st)].st_tab;
01427         fortTkSupport::SymTabId scopeid = ctxt.findSymTabId(sttab);
01428         xos << xml::BegElem("xaif:ArgumentSymbolReference")
01429             << xml::Attr("position", position) 
01430             << xml::Attr("scope_id", scopeid) 
01431             << AttrSymId(parm_st)
01432             << xml::Attr("intent", xlate_intent(parm_wn))
01433             << WhirlIdAnnot(ctxt.findWNId(parm_wn))
01434             << xml::EndElem;
01435         position++;
01436       }
01437     
01438       if (STAB_PARAM_HAS_IMPLICIT_LENGTH(parm_st)) {
01439         implicit_parms++;
01440       
01441         /* FIXME: is function returning character_TY? if length follows */
01442         /* address - skip over it, but account for ',' in arg list */
01443         if ( ((parm == first_parm) && (params_st[parm+1] != NULL)) 
01444              && (ST_is_value_parm(parm_st) 
01445                  && ST_is_value_parm(params_st[parm+1]))
01446              && (return_ty != (TY_IDX)0 && TY_kind(return_ty) == KIND_VOID) ) {
01447           parm++;
01448           params_st[parm] = NULL; 
01449           implicit_parms--;
01450         }
01451       }
01452     }
01453   
01454     xos << xml::EndElem /* xaif:ArgumentList */;
01455 
01456     // add the side effect lists here: 
01457     // the analysis result: 
01458     OA::OA_ptr<OA::SideEffect::InterSideEffectStandard> interSideEffects=
01459       Whirl2Xaif::getOAAnalMap().getInterSideEffect();
01460 
01461     // an iterator over locations: 
01462     OA::OA_ptr<OA::LocIterator> anOALocIterOAPtr;
01463     OA::ProcHandle proc((OA::irhandle_t)Current_PU_Info);
01464 
01465     // symbol handle iterator from parameter bindings to distinguish the formal parameters 
01466     // from the strictly local variables 
01467     OA::OA_ptr<OA::SymHandleIterator> symHandleI=Whirl2Xaif::getOAAnalMap().
01468       getParamBindings()->getFormalIterator(proc);
01469 
01470     //   // begin debugging stuff
01471     //   ST* st = ST_ptr(PU_Info_proc_sym(Current_PU_Info));
01472     //   const char* nm = ST_name(st);
01473     //   if (!symHandleI->isValid())
01474     //     std::cout << "Note: in xlate_EntryPoint empty symHandleI for " << nm << std::endl;
01475     //   else 
01476     //     std::cout << "Note: in xlate_EntryPoint non-empty symHandleI for " << nm << std::endl;
01477     //   // end debugging stuff
01478 
01479     symHandleI->reset();
01480     xos << xml::BegElem("xaif:ModLocal");
01481     anOALocIterOAPtr = interSideEffects->getLMODIterator(proc);
01482     SymbolPointerSet coveredSymbols;
01483     for ( ; anOALocIterOAPtr->isValid(); ++(*anOALocIterOAPtr) ) {
01484       xlate_SideEffectEntry(anOALocIterOAPtr->current(),
01485                             anOALocIterOAPtr->current(), 
01486                             coveredSymbols,
01487                             xos, 
01488                             wn, 
01489                             ctxt, 
01490                             symHandleI);
01491     }
01492     xos << xml::EndElem; // xaif:ModLocal
01493     coveredSymbols.clear();
01494     symHandleI->reset();
01495     xos << xml::BegElem("xaif:Mod");
01496     anOALocIterOAPtr = interSideEffects->getMODIterator(proc);
01497     for ( ; anOALocIterOAPtr->isValid(); ++(*anOALocIterOAPtr) ) {
01498       xlate_SideEffectEntry(anOALocIterOAPtr->current(),
01499                             anOALocIterOAPtr->current(), 
01500                             coveredSymbols,
01501                             xos, 
01502                             wn, 
01503                             ctxt, 
01504                             symHandleI);
01505     }
01506     xos << xml::EndElem; // xaif:ModLocal
01507     coveredSymbols.clear();
01508     symHandleI->reset();
01509     xos << xml::BegElem("xaif:ReadLocal");
01510     anOALocIterOAPtr = interSideEffects->getLUSEIterator(proc);
01511     for ( ; anOALocIterOAPtr->isValid(); ++(*anOALocIterOAPtr)) {
01512       xlate_SideEffectEntry(anOALocIterOAPtr->current(),
01513                             anOALocIterOAPtr->current(), 
01514                             coveredSymbols,
01515                             xos, 
01516                             wn, 
01517                             ctxt, 
01518                             symHandleI);
01519     }
01520     xos << xml::EndElem; // xaif:ModLocal
01521     coveredSymbols.clear();
01522     symHandleI->reset();
01523     xos << xml::BegElem("xaif:Read");
01524     anOALocIterOAPtr = interSideEffects->getUSEIterator(proc);
01525     for ( ; anOALocIterOAPtr->isValid(); ++(*anOALocIterOAPtr)) {
01526       xlate_SideEffectEntry(anOALocIterOAPtr->current(),
01527                             anOALocIterOAPtr->current(), 
01528                             coveredSymbols,
01529                             xos, 
01530                             wn, 
01531                             ctxt, 
01532                             symHandleI);
01533     }
01534     xos << xml::EndElem; // xaif:ModLocal
01535     // populate the onEntry list: 
01536     SymbolPointerSet requiredTempSymbols; 
01537     findRequiredSymbolsInSymbolTable(CURRENT_SYMTAB, 
01538                                      ctxt,
01539                                      requiredTempSymbols);
01540     // now look at all the variables we found which 
01541     // presumably are all temporaries like t__1, t__2, ...
01542     // which are defined somewhere in the beginning of 
01543     // the body
01544     SymbolPointerSet requiredProgramSymbols;
01545     findRequiredProgramSymbols(wn,
01546                                ctxt,
01547                                requiredTempSymbols,
01548                                requiredProgramSymbols);
01549     if (!requiredTempSymbols.empty()) {
01550       ST* st = ST_ptr(PU_Info_proc_sym(Current_PU_Info));
01551       const char* puName = ST_name(st);
01552       const char* symbolName = ST_name(*(requiredTempSymbols.begin()));
01553       FORTTK_MSG(1,"cannot find a definition for temporary symbol \"" << symbolName << "\" in " << puName);
01554     }
01555     FORTTK_ASSERT(requiredTempSymbols.empty(),fortTkSupport::Diagnostics::UnexpectedInput << " not all symbols required in local declarations have a definition"); 
01556     if (!requiredProgramSymbols.empty()) { 
01557       coveredSymbols.clear();
01558       xos << xml::BegElem("xaif:OnEntry");
01559       for (SymbolPointerSet::iterator si=requiredProgramSymbols.begin();
01560            si!=requiredProgramSymbols.end();
01561            ++si) { 
01562         ST_TAB* sttab = Scope_tab[ST_level(*si)].st_tab;
01563         fortTkSupport::SymTabId scopeid = ctxt.findSymTabId(sttab);
01564         xlate_SideEffectLocationPrint(*si,
01565                                       coveredSymbols,
01566                                       scopeid,
01567                                       xos);
01568       }
01569       xos << xml::EndElem; // xaif:OnEntry
01570     }
01571   }
01572 
01573   // GetParamSymHandleSet: Return a set of SymHandles representing the
01574   // parameters of the OPR_FUNC_ENTRY.
01575   static set<OA::SymHandle>* 
01576   GetParamSymHandleSet(WN* wn_pu)
01577   {
01578     // Accumulate the ST* for parameters
01579     set<OA::SymHandle>* params = new set<OA::SymHandle>;
01580     INT nparam = WN_num_formals(wn_pu);
01581     for (int i = 0; i < nparam; ++i) {
01582       ST* st = WN_st(WN_formal(wn_pu, i));
01583       params->insert(OA::SymHandle((OA::irhandle_t)st));
01584     }
01585     return params;
01586   }
01587 
01588   static const char*
01589   xlate_intent(WN* parm)
01590   {
01591     // Note: WN_parm flags are typically not set 
01592     // WN_parm_flag(parm), WN_Parm_Dummy(parm)
01593     ST* st = WN_st(parm);
01594     if (ST_is_intent_in_argument(st) || WN_Parm_In(parm)) {
01595       return "in";
01596     } 
01597     else if (ST_is_intent_out_argument(st) || WN_Parm_Out(parm)) {
01598       return "out";
01599     }
01600     else { // WN_Parm_By_Reference(parm)
01601       return "inout"; 
01602     }
01603   }
01604 
01605   // xlate_BBStmt: Given a statement within an XAIF basic block,
01606   // properly translate it.
01607   static void
01608   xlate_BBStmt(xml::ostream& xos, WN *wn, PUXlationContext& ctxt)
01609   {
01610     if (!wn) { return; }
01611   
01612     // If a structured statement, it must be translated specially.
01613     // Otherwise simply dispatch to TranslateWN(...).
01614     const char* vty = fortTkSupport::GetCFGControlFlowVertexType(wn);
01615     OPERATOR opr = WN_operator(wn);
01616     const char* opr_str = OPERATOR_name(opr);
01617   
01618     if (vty == XAIFStrings.elem_BBForLoop()) {
01619       if (WN_operator(WN_end(wn))==OPR_NE) { 
01620         FORTTK_WMSG("xlate_BBStmt: loop with variable stride");
01621       }
01622       xlate_LoopInitialization(xos, WN_start(wn), ctxt);
01623       xlate_CFCondition(xos, WN_end(wn), ctxt);
01624       xlate_LoopUpdate(xos, WN_step(wn), ctxt);
01625     } 
01626     else if (vty == XAIFStrings.elem_BBPostLoop() ||
01627              vty == XAIFStrings.elem_BBPreLoop()) {
01628       xlate_CFCondition(xos, WN_while_test(wn), ctxt);
01629     }
01630     else if (vty == XAIFStrings.elem_BBBranch()) {
01631       WN* condWN = NULL;
01632       if (opr == OPR_IF || opr == OPR_TRUEBR || opr == OPR_FALSEBR) {
01633         condWN = WN_if_test(wn);
01634       } 
01635       else if (opr == OPR_SWITCH || opr == OPR_COMPGOTO) {
01636         condWN = WN_switch_test(wn);
01637       }
01638       FORTTK_ASSERT(condWN, fortTkSupport::Diagnostics::UnexpectedOpr << OPERATOR_name(opr));
01639       xlate_CFCondition(xos, condWN, ctxt);
01640     } 
01641     else if (vty == XAIFStrings.elem_BBEndBranch() ||
01642              vty == XAIFStrings.elem_BBEndLoop()) {
01643       // skip bogus comment statement
01644       //xos << Comment(vty);
01645     }
01646     else {
01647       if (IsActiveStmt(wn, ctxt) || (opr==OPR_STID && ! ST_is_temp_var(WN_st(wn)))) {
01648         TranslateWN(xos, wn, ctxt);
01649       } 
01650       else {
01651         xlate_PassiveStmt(xos, wn, ctxt);
01652       }
01653     }
01654   }
01655 
01656 
01657   // xlate_CFCondition: Translate the BB's control flow condition (Loops, Ifs)
01658   static void 
01659   xlate_CFCondition(xml::ostream& xos, WN *wn, PUXlationContext& ctxt)
01660   {
01661     xos << xml::BegElem("xaif:Condition");
01662     ctxt.createXlationContext();
01663     TranslateWN(xos, wn, ctxt);
01664     ctxt.deleteXlationContext();
01665     xos << xml::EndElem;
01666   }
01667 
01668 
01669   // xlate_LoopInitialization: 
01670   static void 
01671   xlate_LoopInitialization(xml::ostream& xos, WN *wn, PUXlationContext& ctxt)
01672   {
01673     xos << xml::BegElem("xaif:Initialization")
01674         << xml::Attr("statement_id", ctxt.findWNId(wn))
01675         << xml::Attr("do_chain", ctxt.findDoChainId(wn));
01676     ctxt.createXlationContext(XlationContext::ASSIGN); // implicit for this element
01677     TranslateWN(xos, wn, ctxt);
01678     ctxt.deleteXlationContext();
01679     xos << xml::EndElem;
01680   }
01681 
01682   // xlate_LoopUpdate: 
01683   static void 
01684   xlate_LoopUpdate(xml::ostream& xos, WN *wn, PUXlationContext& ctxt)
01685   {
01686     xos << xml::BegElem("xaif:Update")
01687         << xml::Attr("statement_id", ctxt.findWNId(wn))
01688         << xml::Attr("do_chain", ctxt.findDoChainId(wn));
01689     ctxt.createXlationContext(XlationContext::ASSIGN); // implicit for this element
01690     TranslateWN(xos, wn, ctxt);
01691     ctxt.deleteXlationContext();
01692     xos << xml::EndElem;
01693   }
01694 
01695   // GetLoopReversalType:
01696   static const char*
01697   GetLoopReversalType(OA::OA_ptr<OA::CFG::CFGInterface> cfg, 
01698                       OA::OA_ptr<OA::CFG::NodeInterface> n)
01699   {
01700     const char* loopTy = "anonymous";
01701 
01702     // Find the WN corresponding to xaif:ForLoop
01703     WN* loopWN = NULL;
01704     OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtIt
01705       = n->getNodeStatementsIterator();
01706     for (; stmtIt->isValid(); ++(*stmtIt)) {
01707       OA::StmtHandle st = stmtIt->current();
01708       WN* wstmt = (WN*)st.hval();
01709       const char* vty = fortTkSupport::GetCFGControlFlowVertexType(wstmt);
01710       if (vty == XAIFStrings.elem_BBForLoop()) { 
01711         loopWN = wstmt;
01712         break;
01713       }
01714     }
01715   
01716     FORTTK_ASSERT(loopWN, "Could not find WN corresponding to xaif:ForLoop");
01717 
01718     // Check for a PRAGMA  right before the loop node
01719     // but skip possible STID nodes assigning temporaries
01720     // that the front-end may have inserted between the 
01721     // loop node and the pragma: 
01722     WN* prevWN_p=WN_prev(loopWN); 
01723     while (prevWN_p 
01724            && 
01725            WN_operator(prevWN_p) == OPR_STID
01726            && 
01727            ST_is_temp_var(WN_st(prevWN_p))) 
01728       prevWN_p=WN_prev(prevWN_p);
01729     if (prevWN_p && WN_operator(prevWN_p) == OPR_PRAGMA) {
01730       WN_PRAGMA_ID prag = (WN_PRAGMA_ID)WN_pragma(prevWN_p);
01731       if (prag == WN_PRAGMA_OPENAD_XXX) {
01732         static const char* TXT = "\"simple loop";
01733         const char* txt = Targ_Print(NULL, WN_val(prevWN_p)); // CLASS_CONST
01734         if (strncasecmp(txt, TXT, strlen(TXT)) == 0) {
01735           loopTy = "explicit";
01736         }
01737       }
01738     }
01739 
01740     if (Args::ourSimpleLoopFlag)
01741       loopTy = "explicit";
01742 
01743     return loopTy;
01744   }
01745 
01746   // GetIDsForStmtsInBB: Returns a colon separated list for ids of
01747   // statements within the basic block.  In the event that a statement
01748   // id maps to zero, it is *not* included in the list.
01749   static std::string
01750   GetIDsForStmtsInBB(OA::OA_ptr<OA::CFG::NodeInterface> node, 
01751                      PUXlationContext& ctxt)
01752   {
01753     using namespace OA::CFG;
01754   
01755     std::string idstr;
01756     bool emptystr = true;
01757   
01758     OA::OA_ptr<OA::CFG::NodeStatementsIteratorInterface> stmtItPtr
01759       = node->getNodeStatementsIterator();
01760     for (; stmtItPtr->isValid(); ++(*stmtItPtr)) {
01761       WN* wstmt = (WN *)stmtItPtr->current().hval();
01762       fortTkSupport::WNId id = ctxt.findWNId(wstmt);
01763     
01764       // Skip statements without a valid id
01765       if (id == 0) { continue; }
01766 
01767       const char* str = Num2Str(id, "%lld");
01768       //std::cout << id << " --> " << str << " // ";
01769     
01770       if (!emptystr) {
01771         idstr += ":";
01772       }
01773       idstr += str;
01774       emptystr = false;
01775     }
01776  
01777     return idstr;
01778   }
01779 
01780 
01781   // GetCFGEdgeCondVal: Given a CFG edge, returns a pair indicating
01782   // whether the edge has a condition value, and if so, its value.
01783   // (There is no reserved NULL value for the condition value; it should
01784   // only be used when the first part of the pair is true!)
01785   pair<bool, INT64>
01786   GetCFGEdgeCondVal(const OA::OA_ptr<OA::CFG::EdgeInterface> edge)
01787   {
01788     using namespace OA::CFG;
01789   
01790     EdgeType ety = edge->getType();
01791     WN* eexpr = (WN*)edge->getExpr().hval();
01792   
01793     bool hasCondVal = false;
01794     INT64 condVal = 0;
01795     if (ety == TRUE_EDGE) {
01796       hasCondVal = true;
01797       condVal = 1;
01798     } 
01799     else if (ety == MULTIWAY_EDGE && eexpr) {
01800       hasCondVal = true;
01801       OPERATOR opr = WN_operator(eexpr);
01802       if (opr == OPR_CASEGOTO) { // from an OPR_SWITCH
01803         condVal = WN_const_val(eexpr);
01804       } 
01805       else if (opr == OPR_GOTO) { // from an OPR_COMPGOTO
01806         // to find condVal, must find parent COMPGOTO and then find the
01807         // index of this GOTO in the jumptable.
01808         FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "Conditions for COMPGOTO");
01809       } 
01810       else {
01811         FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "Unknown multiway branch");
01812       }
01813     }
01814     return pair<bool, INT64>(hasCondVal, condVal);
01815   }
01816 
01817   void initOurHandlerTable() { 
01818 
01819     // Note: Organization generally corresponds to that in
01820     // Open64/documentation/whirl.tex
01821   
01822     // Structured control flow
01823     ourHandlerTable[OPR_FUNC_ENTRY]=           &xlate_FUNC_ENTRY ;
01824     ourHandlerTable[OPR_BLOCK]=                &xlate_BLOCK ;
01825     ourHandlerTable[OPR_REGION]=               &WN2F_region ;
01826     ourHandlerTable[OPR_REGION_EXIT]=          &xlate_GOTO ;
01827     ourHandlerTable[OPR_DO_LOOP]=              &xlate_DO_LOOP ;
01828     ourHandlerTable[OPR_DO_WHILE]=             &xlate_DO_WHILE ;
01829     ourHandlerTable[OPR_WHILE_DO]=             &xlate_WHILE_DO ;
01830     ourHandlerTable[OPR_IF]=                   &xlate_IF ;
01831   
01832     // Other control flow
01833     ourHandlerTable[OPR_IMPLIED_DO]=           &WN2F_noio_implied_do ;
01834     ourHandlerTable[OPR_GOTO]=                 &xlate_GOTO ;
01835     ourHandlerTable[OPR_SWITCH]=               &xlate_SWITCH ;
01836     ourHandlerTable[OPR_CASEGOTO]=             &xlate_unknown ;
01837     ourHandlerTable[OPR_COMPGOTO]=             &xlate_unknown ;
01838     ourHandlerTable[OPR_AGOTO]=                &xlate_unknown ;
01839     ourHandlerTable[OPR_ALTENTRY]=             &xlate_ALTENTRY ;
01840     ourHandlerTable[OPR_TRUEBR]=               &xlate_condBR ;
01841     ourHandlerTable[OPR_FALSEBR]=              &xlate_condBR ;
01842     ourHandlerTable[OPR_RETURN]=               &xlate_RETURN ;
01843     ourHandlerTable[OPR_RETURN_VAL]=           &xlate_RETURN_VAL ;
01844     ourHandlerTable[OPR_LABEL]=                &xlate_LABEL ;
01845 
01846     // Statements: Calls
01847     ourHandlerTable[OPR_CALL]=                 &xlate_CALL ;
01848     ourHandlerTable[OPR_ICALL]=                &xlate_CALL ;
01849     ourHandlerTable[OPR_PICCALL]=              &xlate_CALL ;
01850     ourHandlerTable[OPR_INTRINSIC_CALL]=       &xlate_INTRINSIC_CALL ;
01851     ourHandlerTable[OPR_IO]=                   &xlate_IO ;
01852 
01853     // Statements: Other
01854     ourHandlerTable[OPR_EVAL]=                 &WN2F_eval ;
01855     ourHandlerTable[OPR_PRAGMA]=               &xlate_PRAGMA ;
01856     ourHandlerTable[OPR_XPRAGMA]=              &xlate_PRAGMA ;
01857     ourHandlerTable[OPR_PREFETCH]=             &xlate_PREFETCH ;
01858     ourHandlerTable[OPR_PREFETCHX]=            &xlate_PREFETCH ;
01859     ourHandlerTable[OPR_COMMENT]=              &xlate_COMMENT ;
01860     ourHandlerTable[OPR_TRAP]=                 &xlate_ignore ; // FIXME
01861     ourHandlerTable[OPR_ASSERT]=               &xlate_ignore ; // FIXME
01862     ourHandlerTable[OPR_FORWARD_BARRIER]=      &xlate_ignore ; // FIXME
01863     ourHandlerTable[OPR_BACKWARD_BARRIER]=     &xlate_ignore ; // FIXME
01864     ourHandlerTable[OPR_DEALLOCA]=             &WN2F_dealloca ;
01865 
01866     ourHandlerTable[OPR_USE]=                  &xlate_USE ;
01867     ourHandlerTable[OPR_NAMELIST]=             &WN2F_namelist_stmt ;
01868     ourHandlerTable[OPR_IMPLICIT_BND]=         &WN2F_implicit_bnd ;  
01869     ourHandlerTable[OPR_NULLIFY]=              &WN2F_nullify_stmt ;
01870     ourHandlerTable[OPR_INTERFACE]=            &WN2F_interface_blk ;
01871     ourHandlerTable[OPR_ARRAY_CONSTRUCT]=      &WN2F_ar_construct ;
01872   
01873     // Memory Access (or assignment and variable references)
01874     ourHandlerTable[OPR_LDA]=                  &xlate_LDA ;    // Leaf
01875     ourHandlerTable[OPR_LDID]=                 &xlate_LDID ;
01876     ourHandlerTable[OPR_STID]=                 &xlate_STID ;
01877     ourHandlerTable[OPR_ILOAD]=                &xlate_ILOAD ;
01878     ourHandlerTable[OPR_ILOADX]=               &xlate_ILOADX ;
01879     ourHandlerTable[OPR_MLOAD]=                &WN2F_mload ;
01880     ourHandlerTable[OPR_ISTORE]=               &xlate_ISTORE ;
01881     ourHandlerTable[OPR_ISTOREX]=              &xlate_ISTOREX ;
01882     ourHandlerTable[OPR_MSTORE]=               &WN2F_mstore ;
01883     ourHandlerTable[OPR_STRCTFLD]=             &xlate_STRCTFLD ;
01884     ourHandlerTable[OPR_PSTID]=                &WN2F_pstid ;  // pointer STID 
01885     ourHandlerTable[OPR_PSTORE]=               &WN2F_pstore ; // pointer STORE
01886 
01887     // Type conversion
01888     ourHandlerTable[OPR_CVT]=                  &WN2F_cvt ;
01889     ourHandlerTable[OPR_CVTL]=                 &WN2F_cvtl ;
01890     ourHandlerTable[OPR_TAS]=                  &WN2F_tas ;
01891   
01892     // Expressions: Unary operations
01893     ourHandlerTable[OPR_INTCONST]=             &xlate_INTCONST ; // Leaf
01894     ourHandlerTable[OPR_CONST]=                &xlate_CONST ;    // Leaf
01895 
01896     ourHandlerTable[OPR_NEG]=                  &xlate_UnaryOp ;
01897     ourHandlerTable[OPR_ABS]=                  &xlate_UnaryOp ;
01898     ourHandlerTable[OPR_SQRT]=                 &xlate_UnaryOp ;
01899     ourHandlerTable[OPR_RSQRT]=                &WN2F_rsqrt ;
01900     ourHandlerTable[OPR_RECIP]=                &xlate_RECIP ;
01901     ourHandlerTable[OPR_REALPART]=             &WN2F_realpart ; // OPR_FIRSTPART
01902     ourHandlerTable[OPR_IMAGPART]=             &WN2F_imagpart ; // OPR_SECONDPART
01903     ourHandlerTable[OPR_PAREN]=                &xlate_PAREN ;
01904     ourHandlerTable[OPR_RND]=                  &xlate_UnaryOp ;
01905     ourHandlerTable[OPR_TRUNC]=                &xlate_UnaryOp ;
01906     ourHandlerTable[OPR_CEIL]=                 &xlate_UnaryOp ;
01907     ourHandlerTable[OPR_FLOOR]=                &xlate_UnaryOp ;
01908     ourHandlerTable[OPR_BNOT]=                 &xlate_UnaryOp ;
01909     ourHandlerTable[OPR_LNOT]=                 &xlate_UnaryOp ;
01910     ourHandlerTable[OPR_PARM]=                 &WN2F_parm ;
01911     ourHandlerTable[OPR_ALLOCA]=               &WN2F_alloca ;
01912 
01913     // Expressions: Binary operations
01914     ourHandlerTable[OPR_COMPLEX]=              &xlate_BinaryOp ; // OPR_PAIR
01915     ourHandlerTable[OPR_ADD]=                  &xlate_BinaryOp ;
01916     ourHandlerTable[OPR_SUB]=                  &xlate_BinaryOp ;
01917     ourHandlerTable[OPR_MPY]=                  &xlate_BinaryOp ;
01918     ourHandlerTable[OPR_DIV]=                  &xlate_BinaryOp ;
01919     ourHandlerTable[OPR_MOD]=                  &xlate_BinaryOp ;
01920     ourHandlerTable[OPR_REM]=                  &xlate_BinaryOp ;
01921     ourHandlerTable[OPR_MAX]=                  &xlate_BinaryOp ;
01922     ourHandlerTable[OPR_MIN]=                  &xlate_BinaryOp ;
01923     ourHandlerTable[OPR_EQ]=                   &xlate_BinaryOp ;
01924     ourHandlerTable[OPR_NE]=                   &xlate_BinaryOp ;
01925     ourHandlerTable[OPR_GE]=                   &xlate_BinaryOp ;
01926     ourHandlerTable[OPR_GT]=                   &xlate_BinaryOp ;
01927     ourHandlerTable[OPR_LE]=                   &xlate_BinaryOp ;
01928     ourHandlerTable[OPR_LT]=                   &xlate_BinaryOp ;
01929     ourHandlerTable[OPR_BAND]=                 &xlate_BinaryOp ;
01930     ourHandlerTable[OPR_BIOR]=                 &xlate_BinaryOp ;
01931     ourHandlerTable[OPR_BNOR]=                 &WN2F_bnor ;
01932     ourHandlerTable[OPR_BXOR]=                 &xlate_BinaryOp ;
01933     ourHandlerTable[OPR_LAND]=                 &xlate_BinaryOp ;
01934     ourHandlerTable[OPR_LIOR]=                 &xlate_BinaryOp ;
01935     ourHandlerTable[OPR_CAND]=                 &xlate_BinaryOp ;
01936     ourHandlerTable[OPR_CIOR]=                 &xlate_BinaryOp ;
01937     ourHandlerTable[OPR_SHL]=                  &xlate_BinaryOp ;
01938     ourHandlerTable[OPR_ASHR]=                 &xlate_BinaryOp ;
01939     ourHandlerTable[OPR_LSHR]=                 &WN2F_lshr ;
01940   
01941     // Expressions: Ternary operations
01942     ourHandlerTable[OPR_SELECT]=               &WN2F_select ;
01943     ourHandlerTable[OPR_MADD]=                 &WN2F_madd ;
01944     ourHandlerTable[OPR_MSUB]=                 &WN2F_msub ;
01945     ourHandlerTable[OPR_NMADD]=                &WN2F_nmadd ;
01946     ourHandlerTable[OPR_NMSUB]=                &WN2F_nmsub ;
01947 
01948     // Expressions: N-ary operations
01949     ourHandlerTable[OPR_ARRAY]=                &xlate_ARRAY ;
01950     ourHandlerTable[OPR_INTRINSIC_OP]=         &xlate_INTRINSIC_OP ;
01951     ourHandlerTable[OPR_TRIPLET]=              &WN2F_triplet ;
01952     ourHandlerTable[OPR_SRCTRIPLET]=           &WN2F_src_triplet ;
01953     ourHandlerTable[OPR_ARRAYEXP]=             &WN2F_arrayexp ;
01954     ourHandlerTable[OPR_ARRSECTION]=           &WN2F_arrsection ;
01955     ourHandlerTable[OPR_WHERE]=                &WN2F_where ;
01956 
01957     // just for convenience
01958     ourHandlerTable[OPERATOR_UNKNOWN]=         &xlate_unknown; 
01959   } 
01960 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines