OpenADFortTk (basic)
src/xaif2whirl/xaif2whirl.cxx
Go to the documentation of this file.
00001 // -*-Mode: C++;-*-
00002 
00003 #include <stdlib.h> // ANSI: cstdlib // for strtol
00004 #include <string.h> // ANSI: cstring // for strcmp, etc.
00005 #include <iostream>
00006 #include <vector>
00007 #include <set>
00008 #include <list> // FIXME: for TopologicalSort
00009 #include <map>  // FIXME: for TopologicalSort
00010 
00011 #include "xercesc/dom/DOMDocument.hpp"
00012 #include "xercesc/dom/DOMNode.hpp"
00013 #include "xercesc/dom/DOMElement.hpp"
00014 
00015 #include "Open64IRInterface/Open64BasicTypes.h"
00016 #include "Open64IRInterface/Open64IRInterface.hpp"
00017 #include "Open64IRInterface/SymTab.h"
00018 #include "Open64IRInterface/IFDiagnostics.h"
00019 #include "Open64IRInterface/wn_attr.h"
00020 #include "Open64IRInterface/stab_attr.h"
00021 #include "OpenAnalysis/Utils/DGraph/DGraphInterface.hpp"
00022 #include "OpenAnalysis/Utils/DGraph/DGraphImplement.hpp"
00023 
00024 
00025 #include "WhirlIDMaps.h"
00026 #include "WhirlParentize.h"
00027 #include "XAIFStrings.h"
00028 #include "Diagnostics.h"
00029 
00030 #include "xaif2whirl.h"
00031 #include "Args.h"
00032 #include "XlateExpression.h"
00033 #include "XlateStmt.h"
00034 #include "XAIF_DOMFilters.h"
00035 #include "XercesStrX.h"
00036 #include "InterfaceData.h"
00037 
00038 // *************************** Forward Declarations ***************************
00039 
00040 namespace xaif2whirl { 
00041 
00042   fortTkSupport::IntrinsicXlationTable   
00043   IntrinsicTable(fortTkSupport::IntrinsicXlationTable::X2W);
00044   fortTkSupport::WNIdToWNTabMap          WNIdToWNTableMap;
00045 
00046   // FIXME
00047   extern AlgorithmType opt_algorithm;
00048 
00049   // FIXME
00050   extern TY_IDX ActiveTypeTyIdx;            // OpenAD active pseudo type
00051   extern TY_IDX ActiveTypeInitializedTyIdx; // OpenAD active pseudo type
00052   TY_IDX ActiveTypeTyIdx;            
00053   TY_IDX ActiveTypeInitializedTyIdx;
00054 
00055   // *************************** Forward Declarations ***************************
00056   // ControlFlowGraph
00057 
00058   static void
00059   TranslateCFG(WN *wn_pu, const xercesc::DOMElement* cfgElem, PUXlationContext& ctxt);
00060 
00061   static WN*
00062   xlate_CFG(WN* wn_pu, OA::OA_ptr<OA::DGraph::DGraphInterface> cfg, 
00063             OA::OA_ptr<MyDGNode> root, PUXlationContext& ctxt,
00064             unsigned& startLabel_r, 
00065             bool structuredCF);
00066 
00067   static WN*
00068   TranslateBasicBlock(WN *wn_pu, 
00069                       const xercesc::DOMElement* bbElem, 
00070                       PUXlationContext& ctxt,
00071                       bool skipMarkeredGotoAndLabels,
00072                       unsigned endLabel);
00073 
00074   // *************************** Forward Declarations ***************************
00075 
00076   // ControlFlowGraph -- basic block patching algorithm
00077 
00078   static void
00079   TranslateBB_OLD(WN *wn_pu, const xercesc::DOMElement* bbElem, PUXlationContext& ctxt);
00080 
00081   static void
00082   xlate_BasicBlock_OLD(WN *wn_pu, const xercesc::DOMElement* bbElem, 
00083                        PUXlationContext& ctxt);
00084   static void
00085   xlate_BBCond_OLD(WN* wn_pu, const xercesc::DOMElement* bbElem, PUXlationContext& ctxt);
00086 
00087   static bool
00088   FindNextStmtInterval(const xercesc::DOMElement* bbElem, fortTkSupport::IdList<fortTkSupport::WNId>* bbIdList, 
00089                        fortTkSupport::WNIdToWNMap* wnmap, WN* blkWN,
00090                        xercesc::DOMElement* &begXAIF, xercesc::DOMElement* &endXAIF,
00091                        WN* &begWN, WN* &endWN);
00092 
00093   static WN*
00094   FindIntervalBoundary(const xercesc::DOMElement* elem, fortTkSupport::IdList<fortTkSupport::WNId>* bbIdList, 
00095                        fortTkSupport::WNIdToWNMap* wnmap, WN* blkWN, int boundary);
00096 
00097   static WN* 
00098   FindWNBlock(const xercesc::DOMElement* bbElem, fortTkSupport::IdList<fortTkSupport::WNId>* idlist, 
00099               PUXlationContext& ctxt);
00100 
00101   static WN* 
00102   FindSafeInsertionPoint(WN* blckWN, WN* stmtWN);
00103 
00104   static void
00105   RemoveFromWhirlIdMaps(WN* wn, fortTkSupport::WNToWNIdMap* wn2idmap, fortTkSupport::WNIdToWNMap* id2wnmap);
00106 
00107   // *************************** Forward Declarations ***************************
00108   // Scopes and Symbols
00109 
00110   static void
00111   xlate_SymbolTable(const xercesc::DOMElement* elem,
00112                     const char* scopeId, PU_Info* pu, 
00113                     PUXlationContext& ctxt);
00114 
00115   static void
00116   xlate_Symbol(const xercesc::DOMElement* elem, 
00117                const char* scopeId, 
00118                PU_Info* pu, 
00119                PUXlationContext& ctxt,
00120                bool doTempSymbols);
00121 
00122   // *************************** Forward Declarations ***************************
00123 
00124   // WHIRL Creation functions
00125 
00126   static WN*
00127   CreateOpenADReplacementBeg(const char* placeholder);
00128 
00129   static WN*
00130   CreateOpenADReplacementEnd();
00131 
00132   static WN* 
00133   CreateIfCondition(WN* condWN);
00134 
00135   static ST* 
00136   CreateST(const xercesc::DOMElement* elem, 
00137            SYMTAB_IDX level, 
00138            const char* nm,
00139            fortTkSupport::XAIFSymToSymbolMap& symMap,
00140            const char* scopeId);
00141 
00142   static ST* 
00143   ConvertIntoGlobalST(ST* st);
00144 
00145   static void 
00146   ConvertToActiveType(ST* st);
00147 
00148   static void 
00149   ConvertStructMemberToActiveType(TY_IDX base_ty, TY_IDX ref_ty,
00150                                   UINT field_id);
00151 
00152   static void 
00153   ConvertScalarizedRefToActiveType(WN* wn);
00154 
00155   static FLD_HANDLE
00156   TY_Lookup_FLD(TY_IDX struct_ty, TY_IDX ref_ty, UINT64 ref_ofst, unsigned short eqInst=1);
00157 
00158 
00159   // FIXME (Note: TYPE_ID and TY_IDX are typedef'd to the same type, so
00160   // overloading is not possible!)
00161   // static TY_IDX MY_Make_Array_Type1 (TYPE_ID elem_ty, INT32 ndim, INT64 len);
00162   static TY_IDX MY_Make_Array_Type (TY_IDX elem_ty, 
00163                                     INT32 ndim, 
00164                                     bool fixed,  
00165                                     const INT64* lower, 
00166                                     const INT64* upper);
00167 
00168   static TY_IDX
00169   XAIFTyToWHIRLTy(const char* type, const TYPE_ID mtype); 
00170 
00171   // *************************** Forward Declarations ***************************
00172 
00173   class ConvertModuleTypeFctr {
00174   public:
00175     ConvertModuleTypeFctr(TY_IDX struct_ty_, TY_IDX ref_ty_, UINT field_id_)
00176       : struct_ty(struct_ty_), ref_ty(ref_ty_), field_id(field_id_)
00177     { 
00178       ty_name  = TY_name(struct_ty);
00179       ty_mtype = TY_mtype(struct_ty);
00180       ty_size  = TY_size(struct_ty);
00181     }
00182     ~ConvertModuleTypeFctr() { }
00183   
00184     bool operator()(UINT32 idx, const TY* entry) const { 
00185       // If this is the non-external version of the type we seek, change it
00186       if (!TY_is_external(*entry) 
00187           && TY_mtype(*entry) == ty_mtype
00188           && TY_size(*entry) == ty_size
00189           && strcmp(TY_name(*entry), ty_name) == 0) {
00190         TY_IDX ty = make_TY_IDX(idx);
00191         ConvertStructMemberToActiveType(ty, ref_ty, field_id);
00192         return true; // early exit
00193       }
00194       return false; // continue
00195     }
00196   
00197   private:
00198     TY_IDX struct_ty;
00199     TY_IDX ref_ty;
00200     UINT field_id;
00201 
00202     // cached values
00203     const char* ty_name;
00204     MTYPE       ty_mtype;
00205     UINT64      ty_size;
00206   };
00207 
00208   // *************************** Forward Declarations ***************************
00209 
00210   // MyDGNode routines
00211 
00212   unsigned int MyDGNode::nextId = 1;
00213 
00214   // sort_CondVal: Used to sort operands of (arguments to) an expression
00215   // by the "condition_value" attribute
00216   struct sort_CondVal
00217   {
00218     sort_CondVal(bool ascending_ = true) : ascending(ascending_) { }
00219   
00220     // return true if e1 < e2; false otherwise
00221     bool operator()(const OA::OA_ptr<MyDGEdge> e1, 
00222                     const OA::OA_ptr<MyDGEdge> e2) const
00223     {
00224       unsigned int cond1 = GetCondAttr(e1->GetElem());
00225       unsigned int cond2 = GetCondAttr(e2->GetElem());
00226       return (ascending) ? (cond1 < cond2) : (cond1 > cond2);
00227     }
00228 
00229   private:
00230     bool ascending;
00231   };
00232 
00233   static OA::OA_ptr<OA::DGraph::DGraphInterface> 
00234   CreateCFGraph(const xercesc::DOMElement* elem);
00235 
00236   //static list<OA::OA_ptr<OA::DGraph::Interface::Node> >*
00237   //TopologicalSort(OA::OA_ptr<OA::DGraph::Interface> graph);
00238 
00239 
00240   // ****************************************************************************
00241   // Top level translation routines
00242   // ****************************************************************************
00243 
00244   // TranslateCFG: Translate XAIF CFG or XAIF Replacement to WHIRL
00245   void
00246   TranslateCFG(PU_Info* pu_forest, const xercesc::DOMElement* cfgElem,
00247                PUXlationContext& ctxt)
00248   {
00249     // -------------------------------------------------------
00250     // Find original PU and set globals
00251     // -------------------------------------------------------
00252     fortTkSupport::PUId puid = GetPUId(cfgElem);
00253     PU_Info* pu = ctxt.findPU(puid);
00254     if (!pu) { return; }
00255 
00256     // the PU_info is the original one. 
00257     // but we may have changed the name
00258     // so we should compare if the name 
00259     // matches and replace the symbol reference 
00260     // to the proper name.  UNLESS this is 
00261     // a module
00262     fortTkSupport::Symbol* symd = GetSymbol(cfgElem, ctxt);
00263     FORTTK_ASSERT(symd, "Could not find symbol for CFG element " << *cfgElem);
00264     ST* std = symd->GetST();
00265     bool isModuleName=(ST_is_in_module(*std) 
00266                        && 
00267                        (PU_lexical_level(Pu_Table[ST_pu(*std)])<3));
00268     if (ST_is_in_module(*std) 
00269         && 
00270         PU_lexical_level(Pu_Table[ST_pu(*std)])==3
00271         && 
00272         PU_Info_proc_sym(pu)!=ST_st_idx (*std)) { 
00273       // need to see if there is a corresponding interface and adjust it
00274       InterfaceData::findAndAdjustInterface(InterfaceData::getParentOf(pu),
00275                                             PU_Info_tree_ptr(pu),
00276                                             std);
00277     } 
00278     // compare this by comparing the symbol table index
00279     if (!isModuleName && PU_Info_proc_sym(pu)!=ST_st_idx (*std))
00280       PU_Info_proc_sym(pu)=ST_st_idx (*std);
00281 
00282     FORTTK_MSG(1,"TranslateCFG: starting on " << XercesStrX(cfgElem->getNodeName()) << ": " << ST_name(std));
00283   
00284     // Set globals
00285     WN *wn_pu = PU_Info_tree_ptr(pu);
00286     // set up the name in the FUNC_ENTRY too
00287     // compare this by comparing the symbol table index UNLESS this is 
00288     // a module
00289     if (!isModuleName && WN_st_idx(wn_pu)!=ST_st_idx (*std))
00290       WN_st_idx(wn_pu)=ST_st_idx (*std);
00291     PU_SetGlobalState(pu);
00292 
00293 
00294     // -------------------------------------------------------
00295     // Translate, modifying 'wn_pu'
00296     // -------------------------------------------------------
00297 
00298     ST* st = ST_ptr(PU_Info_proc_sym(pu));
00299     if (IsActivePU(st)) {
00300       TranslateCFG(wn_pu, cfgElem, ctxt);
00301     }
00302   
00303 #if 0
00304     fprintf(stderr, "\n----------------------------------------------------\n");
00305     fdump_tree(stderr, wn_pu);
00306 #endif
00307   }
00308 
00309 
00310   // ****************************************************************************
00311   // ControlFlowGraph
00312   // ****************************************************************************
00313 
00314   // Structured and Unstructured CFG Translation, with special reference
00315   // to WHIRL SWITCHes.
00316   //
00317   // WHIRL does not have a structured multiway branch and so Fortran
00318   // selects are translated into a jump table and several
00319   // label/case-specific-code/goto-select-end blocks.
00320   // 
00321   // Given a 'structured' WHIRL PU -- a PU without any GOTOs except for
00322   // CASE-block-related ones -- we can translate the SWITCH into an XAIF
00323   // structured multiway branch, complete with an EndBranch node.  (The
00324   // modified OpenAnalysis CFG provides the needed information.)
00325   // Assuming the XAIF retains the structured property, then the XAIF
00326   // can be translated back into a WHIRL switch node by removing all
00327   // original WHIRL LABELs/GOTOs and adding new LABELs/GOTOs to the
00328   // SWITCH case blocks.  (The original code must have had only 1)
00329   // SWITCH-related GOTOs/LABELs and 2) possibly some non-target LABELs
00330   // generated by mfef90.  It is safe to remove (2).  It is safe to
00331   // remove (2) because new LABELs/GOTOs will be generated.)
00332   // 
00333   // Given a non-structured WHIRL PU, we can translate multiway branches
00334   // into WHIRL SWITCHes in the same way as above.  A general and simple
00335   // solution is to replace all original LABELs (always at the beginning
00336   // of a basic block) and GOTOs (always at the end of a basic block)
00337   // with new ones.  This eliminates the need to develop a more complex
00338   // mechanism (such as label remapping) to ensure newly generated
00339   // labels to not conflict with original labels.
00340 
00341 
00342   static WN*
00343   xlate_CFG_BasicBlock(WN *wn_pu, OA::OA_ptr<MyDGNode> curBB, 
00344                        PUXlationContext& ctxt, 
00345                        bool skipMarkeredGotoAndLabels, 
00346                        unsigned newCurBBLbl, 
00347                        unsigned newNextBBLbl,
00348                        unsigned endLabel);
00349 
00350   static WN*
00351   xlate_CFG_BranchMulti(OA::OA_ptr<MyDGNode> curNode, WN* condWN, 
00352                         unsigned lastLbl,
00353                         vector<OA::OA_ptr<MyDGEdge> >& outedges,
00354                         map<OA::OA_ptr<MyDGNode>, unsigned>& nodeToLblMap);
00355 
00356 
00357   // TranslateCFG: Given an XAIF CFG or XAIF Replacement rooted at
00358   // 'cfgElem' and its corresponding WHIRL tree 'wn_pu', modify the
00359   // WHIRL to reflect the XAIF.
00360   static void
00361   TranslateCFG(WN *wn_pu, const xercesc::DOMElement* cfgElem, PUXlationContext& ctxt)
00362   {
00363     // -------------------------------------------------------
00364     // 1. Create auxiliary data structures
00365     // -------------------------------------------------------
00366   
00367     // 0. WHIRL parent map
00368     fortTkSupport::WhirlParentMap wnParentMap(wn_pu);
00369     ctxt.setWNParentMap(&wnParentMap);
00370   
00371     // 1. WHIRL<->ID maps
00372     fortTkSupport::WNToWNIdMap* wnmapx = new fortTkSupport::WNToWNIdMap();
00373     CreateWhirlIdMaps(wn_pu, wnmapx, NULL);
00374     ctxt.setWNToWNIdMap(wnmapx);
00375 
00376     fortTkSupport::WNIdToWNMap* wnmapy = WNIdToWNTableMap.Find(Current_PU_Info);
00377     ctxt.setWNIdToWNMap(wnmapy);
00378   
00379     // -------------------------------------------------------
00380     // 2. Update passing style for arguments (especially used in reverse
00381     // mode to change active arguments to pass-by-reference)
00382     // -------------------------------------------------------
00383     xercesc::DOMElement* arglst = GetChildElement(cfgElem, XAIFStrings.elem_ArgList_x());
00384     xercesc::DOMElement* arg = (arglst) ? 
00385       GetChildElement(arglst, XAIFStrings.elem_ArgSymRef_x()) : NULL;
00386     for ( ; arg; arg = GetNextSiblingElement(arg)) {
00387       // find corresponding WN and symbol
00388       fortTkSupport::WNId id = GetWNId(arg);
00389       WN* parmWN = ctxt.findWN(id, true /* mustFind */);
00390       fortTkSupport::Symbol* sym = GetSymbol(arg, ctxt);
00391       ST* parmST = sym->GetST();
00392     
00393       //bool active = GetActiveAttr(arg); 
00394       const XMLCh* intentX = arg->getAttribute(XAIFStrings.attr_intent_x());
00395       XercesStrX intent = XercesStrX(intentX);
00396     
00397       if (strcmp(intent.c_str(), "in") == 0) {
00398         WN_Set_Parm_In(parmWN);
00399         Set_ST_is_intent_in_argument(parmST);
00400       }
00401       else if (strcmp(intent.c_str(), "out") == 0) {
00402         WN_Set_Parm_Out(parmWN);
00403         Set_ST_is_intent_out_argument(parmST);          
00404       }
00405       else if (strcmp(intent.c_str(), "inout") == 0) {
00406         WN_Set_Parm_By_Reference(parmWN); // unnecessary for 'whirl2f'
00407         Clear_ST_is_intent_in_argument(parmST);
00408         Clear_ST_is_intent_out_argument(parmST);
00409       }
00410       else {
00411         FORTTK_DIE("Unknown intent to argument:\n" << *arg);
00412       }
00413     }
00414   
00415     // -------------------------------------------------------
00416     // 3. Translate each XAIF CFG into WHIRL
00417     // -------------------------------------------------------
00418   
00419     // Collect the list of CFGs we need to translate.  
00420     list<xercesc::DOMElement*> cfglist;
00421     if (XAIF_CFGElemFilter::IsReplaceList(cfgElem)) {
00422       XAIF_ElemFilter filter(XAIFStrings.elem_Replacement_x());
00423       for (xercesc::DOMElement* e = GetChildElement(cfgElem, &filter); 
00424            (e); e = GetNextSiblingElement(e, &filter)) {
00425         cfglist.push_back(e);
00426       }
00427     }
00428     else {
00429       cfglist.push_back(const_cast<xercesc::DOMElement*>(cfgElem));
00430     }
00431 
00432     // Translate
00433     WN* newstmtblkWN = WN_CreateBlock();
00434     unsigned startLabel=1;
00435     for (list<xercesc::DOMElement*>::iterator it = cfglist.begin(); 
00436          it != cfglist.end(); ++it) {
00437       xercesc::DOMElement* cfgelm = (*it);
00438       OA::OA_ptr<OA::DGraph::DGraphInterface> cfg = CreateCFGraph(cfgelm);
00439     
00440       if (opt_algorithm == ALG_BB_PATCHING) { 
00441         XAIF_BBElemFilter filt(false /* edges */);
00442         for (xercesc::DOMElement* elem = GetChildElement(cfgelm, &filt);
00443              (elem); elem = GetNextSiblingElement(elem, &filt)) {
00444           TranslateBB_OLD(wn_pu, elem, ctxt);
00445         }
00446       } 
00447       else {
00448         OA::OA_ptr<OA::DGraph::NodesIteratorInterface> enodeIter
00449           = cfg->getEntryNodesIterator();
00450         assert(enodeIter->isValid());
00451         OA::OA_ptr<OA::DGraph::NodeInterface> temp = enodeIter->current();
00452         OA::OA_ptr<MyDGNode> root = temp.convert<MyDGNode>();
00453         (*enodeIter)++; assert(!enodeIter->isValid());
00454         WN* cfgblkWN = xlate_CFG(wn_pu, 
00455                                  cfg, 
00456                                  root, 
00457                                  ctxt, 
00458                                  startLabel,
00459                                  GetBoolAttr(cfgelm, 
00460                                              XAIFStrings.attr_structured_x(),
00461                                              true/*default if not specified*/));
00462         if (XAIF_CFGElemFilter::IsReplacement(cfgelm)) {
00463           const XMLCh* pX = 
00464             cfgelm->getAttribute(XAIFStrings.attr_placeholder_x());
00465           XercesStrX p = XercesStrX(pX);
00466           WN* begWN = CreateOpenADReplacementBeg(p.c_str());
00467           WN* endWN = CreateOpenADReplacementEnd();
00468           WN_INSERT_BlockFirst(cfgblkWN, begWN);
00469           WN_INSERT_BlockLast(cfgblkWN, endWN);
00470         }
00471         WN_INSERT_BlockLast(newstmtblkWN, cfgblkWN);
00472       }
00473     }
00474   
00475     // -------------------------------------------------------
00476     // 4. Replace old WHIRL code with newly translated WHIRL
00477     // -------------------------------------------------------
00478     if (opt_algorithm != ALG_BB_PATCHING) { 
00479       // Delete old WHIRL
00480       WN* funcblk = WN_func_body(wn_pu);
00481       for (WN* kid = WN_first(funcblk); (kid); /* */) {
00482         WN* nextkid = WN_next(kid); // must find next 'kid' now!
00483         WN_DELETE_FromBlock(funcblk, kid);
00484         kid = nextkid;
00485       }
00486     
00487       // Splice in newly translated WHIRL 
00488       for (WN* kid = WN_first(newstmtblkWN); (kid); /* */) {
00489         WN* nextkid = WN_next(kid); // must find next 'kid' now!
00490         WN_EXTRACT_FromBlock(newstmtblkWN, kid);
00491         WN_INSERT_BlockLast(funcblk, kid);
00492         kid = nextkid;
00493       }
00494       WN_Delete(newstmtblkWN); // not recursive -- should be empty
00495     }
00496   
00497     // -------------------------------------------------------
00498     // 5. Cleanup
00499     // -------------------------------------------------------
00500     delete wnmapx;
00501   }
00502 
00503 
00504   // xlate_CFG: Given the original WHIRL tree, a CFG structure
00505   // representing the XAIF CFG, and the root CFG node, translate the CFG
00506   // into a block of WHIRL statements.  If the CFG contains only
00507   // structured control flow, 'structured' should be true; the WHIRL
00508   // will also contain goto-less nested and structured control flow.
00509   // Otherwise, 'structured' should be false and the WHIRL will contain
00510   // labels and gotos.
00511   //
00512   // During translation, the non-numerical WHIRL statements represented
00513   // by xaif:Marker will be copied from the original WHIRL tree and
00514   // placed in the returned block.  It is expected that the *caller*
00515   // will splice the returned block containing new statements back into
00516   // the WHIRL FUNC_ENTRY.
00517   //
00518   // Note: This routine will not translate any basic blocks in the CFG
00519   // that are unreachable from 'startNode' (i.e. dead code). 
00520   // [FIXME unstructured]
00521 
00522   static pair<WN*, OA::OA_ptr<MyDGNode> >
00523   xlate_CFGstruct(WN* wn_pu, OA::OA_ptr<OA::DGraph::DGraphInterface> cfg, 
00524                   OA::OA_ptr<MyDGNode> startNode, set<xercesc::DOMElement*>& xlated, 
00525                   PUXlationContext& ctxt,
00526                   unsigned int& startLabel_r);
00527 
00528   static WN*
00529   xlate_CFGunstruct(WN* wn_pu, OA::OA_ptr<OA::DGraph::DGraphInterface> cfg, 
00530                     OA::OA_ptr<MyDGNode> startNode, set<xercesc::DOMElement*>& xlated, 
00531                     PUXlationContext& ctxt,
00532                     unsigned int& startLabel_r);
00533 
00534   static WN*
00535   xlate_CFG(WN* wn_pu, OA::OA_ptr<OA::DGraph::DGraphInterface> cfg, 
00536             OA::OA_ptr<MyDGNode> root, PUXlationContext& ctxt, 
00537             unsigned int& startLabel_r,
00538             bool structuredCF)
00539   {
00540     WN* blkWN = NULL;
00541     set<xercesc::DOMElement*> xlated;
00542     if (structuredCF) {
00543       pair<WN*, OA::OA_ptr<MyDGNode> > ret = 
00544         xlate_CFGstruct(wn_pu, cfg, root, xlated, ctxt, startLabel_r);
00545       blkWN = ret.first;
00546     } else {
00547       blkWN = xlate_CFGunstruct(wn_pu, cfg, root, xlated, ctxt, startLabel_r);
00548     }
00549     return blkWN;
00550   }
00551 
00552 
00553   // xlate_CFGstruct: Helper for translating a structured CFG.  The
00554   // algorithm uses the structured CF and recursion to implicitly create
00555   // nested control flow.
00556   //
00557   // Return value: <new-WHIRL-stmt-block, ending-basic-block> (If the
00558   // latter is NULL, it means we saw the Exit basic block)
00559   static pair<WN*, OA::OA_ptr<MyDGNode> >
00560   xlate_CFGstruct(WN* wn_pu, OA::OA_ptr<OA::DGraph::DGraphInterface> cfg, 
00561                   OA::OA_ptr<MyDGNode> startNode, set<xercesc::DOMElement*>& xlated, 
00562                   PUXlationContext& ctxt,
00563                   unsigned int& startLabel_r)
00564   {
00565     using namespace OA::CFG;  
00566 
00567     WN* blkWN = WN_CreateBlock();
00568   
00569     // ---------------------------------------------------
00570     // We must generate labels FIXME
00571     // ---------------------------------------------------
00572     map<OA::OA_ptr<MyDGNode>, unsigned> nodeToLblMap;
00573   
00574     // Initialize label maps
00575     OA::OA_ptr<OA::DGraph::NodesIteratorInterface> nodeIt 
00576       = cfg->getNodesIterator();
00577     for ( ; nodeIt->isValid(); ++(*nodeIt)) {
00578       OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = nodeIt->current();
00579       OA::OA_ptr<MyDGNode> n = ntmp.convert<MyDGNode>();
00580 
00581       nodeToLblMap[n] = startLabel_r++;
00582     }
00583   
00584     // ---------------------------------------------------
00585     // Translate, beginning with 'startNode'
00586     // ---------------------------------------------------
00587     bool continueIteration = true;
00588     bool generateLbl = false;
00589     OA::OA_ptr<MyDGNode> curNode = startNode;
00590     while (!curNode.ptrEqual(NULL) && continueIteration) {
00591 
00592       xercesc::DOMElement* bbElem = curNode->GetElem();
00593       unsigned curLbl = nodeToLblMap[curNode];
00594    
00595       if (XAIF_BBElemFilter::IsBBEntry(bbElem) ||
00596           XAIF_BBElemFilter::IsBBExit(bbElem) ||
00597           XAIF_BBElemFilter::IsBB(bbElem)) {
00598         // ---------------------------------------------------
00599         // A non-control-flow basic block
00600         // ---------------------------------------------------
00601         OA::OA_ptr<MyDGNode> nextNode = GetSuccessor(curNode); // at most one outgoing edge
00602         unsigned lbl = (generateLbl) ? curLbl : 0;
00603         WN* stmts = xlate_CFG_BasicBlock(wn_pu, 
00604                                          curNode, 
00605                                          ctxt, 
00606                                          true, 
00607                                          lbl,
00608                                          0,
00609                                          0);
00610         WN_INSERT_BlockLast(blkWN, stmts);
00611         generateLbl = false;
00612         curNode = nextNode;
00613       }
00614       else if (XAIF_BBElemFilter::IsBBBranch(bbElem)) {
00615         // ---------------------------------------------------
00616         // Begin a structured branch.  Note: in XAIF branches are
00617         // 'structured switches'.
00618         // ---------------------------------------------------
00619         unsigned int numOutEdges = curNode->num_outgoing();
00620 
00621         // 1. Translate condition expression. 
00622         xercesc::DOMElement* cond = 
00623           GetChildElement(bbElem, XAIFStrings.elem_Condition_x());
00624         xercesc::DOMElement* condexpr = GetFirstChildElement(cond);      
00625         WN* condWN = XlateExpression::translateExpression(condexpr, 
00626                                                           ctxt);
00627         if (numOutEdges == 2) {
00628           // Because branches are 'structured switches', ensure we have
00629           // a boolean expression for an 'if'.
00630           condWN = CreateIfCondition(condWN);
00631         }
00632       
00633         // 2. Gather all outgoing edges, sorted by condition (specially
00634         // sort two-way branches into true-false order.)
00635         OA::OA_ptr<MyDGEdge> tmp; tmp = NULL;
00636         vector<OA::OA_ptr<MyDGEdge> > outedges(numOutEdges, tmp);
00637         OA::OA_ptr<OA::DGraph::EdgesIteratorInterface> it = 
00638           curNode->getOutgoingEdgesIterator();
00639         for (int i = 0; it->isValid(); ++(*it), ++i) {
00640           OA::OA_ptr<OA::DGraph::EdgeInterface> etmp = it->current();
00641           outedges[i] = etmp.convert<MyDGEdge>();
00642         }
00643         std::sort(outedges.begin(), outedges.end(), 
00644                   sort_CondVal((numOutEdges != 2)));
00645 
00646         // 3. Translate (recursively) each child block of this branch
00647         vector<WN*> childblksWN(numOutEdges, NULL);
00648         OA::OA_ptr<MyDGNode> endBrNode; endBrNode = NULL;
00649         for (unsigned i = 0; i < outedges.size(); ++i) {
00650           OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = outedges[i]->getSink();
00651           OA::OA_ptr<MyDGNode> n = ntmp.convert<MyDGNode>();
00652           pair<WN*, OA::OA_ptr<MyDGNode> > p 
00653             = xlate_CFGstruct(wn_pu, cfg, n, xlated, ctxt, startLabel_r);
00654           childblksWN[i] = p.first;
00655           endBrNode = p.second; // will be EndBranch for structured-CF
00656         }
00657         OA::OA_ptr<MyDGNode> nextNode = GetSuccessor(endBrNode);
00658       
00659         // 4. Create branch control flow
00660         if (numOutEdges == 2) {
00661           WN* ifWN = WN_CreateIf(condWN, childblksWN[0], childblksWN[1]);
00662           WN_INSERT_BlockLast(blkWN, ifWN);
00663         } 
00664         else {
00665           // Find the branch-around (or last) label
00666           unsigned lastLbl = nodeToLblMap[nextNode];
00667         
00668           // Add a LABEL/GOTO at the front/end of each successor block
00669           for (unsigned i = 0; i < outedges.size(); ++i) {
00670             OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = outedges[i]->getSink();
00671             OA::OA_ptr<MyDGNode> n = ntmp.convert<MyDGNode>();
00672             WN* nblkWN = childblksWN[i];
00673           
00674             WN* lblWN = WN_CreateLabel(nodeToLblMap[n], 0 /*label_flag*/, NULL);
00675             WN_INSERT_BlockFirst(nblkWN, lblWN);
00676             WN* gotoWN = WN_CreateGoto(lastLbl);
00677             WN_INSERT_BlockLast(nblkWN, gotoWN);
00678           }
00679           generateLbl = true; // add label to front of successor
00680         
00681           // Create SWITCH with CASEGOTOs
00682           WN* switchWN = xlate_CFG_BranchMulti(curNode, condWN, lastLbl,
00683                                                outedges, nodeToLblMap);
00684           WN_INSERT_BlockLast(blkWN, switchWN);
00685         
00686           // Add switch blocks right after SWITCH
00687           for (unsigned i = 0; i < childblksWN.size(); ++i) {
00688             WN_INSERT_BlockLast(blkWN, childblksWN[i]);
00689           }
00690         }
00691       
00692         curNode = nextNode;
00693       }
00694       else if (XAIF_BBElemFilter::IsBBEndBr(bbElem)) {
00695         // ---------------------------------------------------
00696         // End a structured branch
00697         // ---------------------------------------------------
00698         continueIteration = false;
00699       }
00700       else if (XAIF_BBElemFilter::IsBBForLoop(bbElem) ||
00701                XAIF_BBElemFilter::IsBBPreLoop(bbElem) ||
00702                XAIF_BBElemFilter::IsBBPostLoop(bbElem)) {
00703         // ---------------------------------------------------
00704         // Begin a structured loop
00705         // ---------------------------------------------------
00706       
00707         bool isDoLoop = (XAIF_BBElemFilter::IsBBForLoop(bbElem));
00708 
00709         // 1. Gather children23
00710         OA::OA_ptr<MyDGNode> body = GetSuccessorAlongEdge(curNode, 1);
00711         OA::OA_ptr<MyDGNode> fallthru = GetSuccessorAlongEdge(curNode, 0);
00712       
00713         // 2. Translate (recursively) loop body
00714         pair<WN*, OA::OA_ptr<MyDGNode> > p 
00715           = xlate_CFGstruct(wn_pu, cfg, body, xlated, ctxt, startLabel_r);
00716         WN* bodyWN = p.first;
00717       
00718         // 3. Translate condition expression (and update/init statements)
00719         xercesc::DOMElement* cond = 
00720           GetChildElement(bbElem, XAIFStrings.elem_Condition_x());
00721         xercesc::DOMElement* condexpr = GetFirstChildElement(cond);      
00722         WN* condWN = NULL;
00723         if (isDoLoop) {
00724           condWN = XlateExpression::translateExpressionSimple(condexpr, ctxt);
00725         } else {
00726           condWN = XlateExpression::translateExpression(condexpr, ctxt);
00727         }
00728       
00729         xercesc::DOMElement *init = NULL, *update = NULL;
00730         WN *initWN = NULL, *updateWN = NULL;
00731         if (XAIF_BBElemFilter::IsBBForLoop(bbElem)) {
00732           // Note: initWN and updateWN are STIDs
00733           init = GetChildElement(bbElem, XAIFStrings.elem_LpInit_x());
00734           update = GetChildElement(bbElem, XAIFStrings.elem_LpUpdate_x());
00735           initWN = XlateStmt::translateStmt(init, ctxt);
00736           updateWN = XlateStmt::translateStmt(update, ctxt);
00737         }
00738       
00739         // 4. Create control flow statement
00740         WN* stmtWN = NULL;
00741         if (isDoLoop) {
00742           WN* idxWN = WN_CreateIdname(WN_store_offset(initWN), WN_st(initWN));
00743           stmtWN = WN_CreateDO(idxWN, initWN, condWN, updateWN, bodyWN, NULL);
00744         }
00745         else if (XAIF_BBElemFilter::IsBBPreLoop(bbElem)) {
00746           stmtWN = WN_CreateWhileDo(condWN, bodyWN);
00747         }
00748         else if (XAIF_BBElemFilter::IsBBPostLoop(bbElem)) {
00749           stmtWN = WN_CreateDoWhile(condWN, bodyWN);
00750         }
00751       
00752         WN_INSERT_BlockLast(blkWN, stmtWN);
00753         curNode = fallthru;
00754       }      
00755       else if (XAIF_BBElemFilter::IsBBEndLoop(bbElem)) {
00756         // ---------------------------------------------------
00757         // End a structured loop
00758         // ---------------------------------------------------
00759         continueIteration = false;
00760       }
00761       else {
00762         FORTTK_DIE("Unknown XAIF basic block:\n" << *bbElem);
00763       }
00764     }
00765   
00766     return make_pair(blkWN, curNode);
00767   }
00768 
00772   OA::OA_ptr<std::list<OA::OA_ptr<OA::DGraph::NodeInterface> > >
00773   getOrderedSinkNodesList(OA::OA_ptr<OA::DGraph::DGraphInterface> cfg,
00774                           OA::OA_ptr<OA::DGraph::NodeInterface> pNode) {
00775     OA::OA_ptr<std::list<OA::OA_ptr<OA::DGraph::NodeInterface> > > retval;
00776     retval = new std::list<OA::OA_ptr<OA::DGraph::NodeInterface> >;
00777     // put all sink nodes in a list
00778     OA::OA_ptr<std::list<OA::OA_ptr<OA::DGraph::NodeInterface> > > tempList;
00779     tempList = new std::list<OA::OA_ptr<OA::DGraph::NodeInterface> >;
00780     std::list<OA::OA_ptr<OA::DGraph::EdgeInterface> >::iterator iter;
00781     OA::OA_ptr<MyDGNode> cfgNode = pNode.convert<MyDGNode>();
00782     xercesc::DOMElement* bbElem = cfgNode->GetElem();
00783     OA::OA_ptr<OA::DGraph::EdgesIteratorInterface>it=pNode->getOutgoingEdgesIterator();
00784     for(; it->isValid(); ++(*it)) {
00785       OA::OA_ptr<OA::DGraph::EdgeInterface> e = it->current();
00786       OA::OA_ptr<MyDGEdge> cfgEdge = e.convert<MyDGEdge>();
00787       // std::cout << "getOrderedSinkNodesList edge has cond: " <<  GetHasConditionAttr(cfgEdge->GetElem()) << " val " << GetCondAttr(cfgEdge->GetElem()) << std::endl; 
00788       if ((XAIF_BBElemFilter::IsBBForLoop(bbElem) 
00789            ||
00790            XAIF_BBElemFilter::IsBBPostLoop(bbElem))
00791           && 
00792           ( 
00793            (GetHasConditionAttr(cfgEdge->GetElem()) 
00794             && 
00795             GetCondAttr(cfgEdge->GetElem())==0 )
00796            || 
00797            ! GetHasConditionAttr(cfgEdge->GetElem()))) { 
00798         retval->push_front(e->getSink());
00799       }
00800       else { 
00801         retval->push_back(e->getSink());
00802       }
00803     }
00804     return retval;
00805   }
00806     
00810   void getReversePostDFSListR(OA::OA_ptr<OA::DGraph::DGraphInterface> cfg,
00811                               OA::OA_ptr<OA::DGraph::NodeInterface> pNode,
00812                               std::map<OA::OA_ptr<OA::DGraph::NodeInterface>,bool>& visitMap,
00813                               OA::OA_ptr<std::list<OA::OA_ptr<OA::DGraph::NodeInterface> > > pList ) { 
00814     OA::OA_ptr<MyDGNode> cfgNode = pNode.convert<MyDGNode>();
00815     xercesc::DOMElement* bbElem = cfgNode->GetElem();
00816     // std::cout << " getReversePostDFSListR invoked for " << bbElem->getNodeName() << " " << bbElem->getAttribute(XAIFStrings.attr_Vid_x()) << std::endl;   
00817 
00818     // mark as visited so that we don't get in an infinite
00819     // loop on cycles in the graph
00820     visitMap[pNode] = true;
00821     // loop over the successors or predecessors based on orientation
00822     OA::OA_ptr<std::list<OA::OA_ptr<OA::DGraph::NodeInterface> > > nodeList = getOrderedSinkNodesList(cfg,pNode); 
00823     std::list<OA::OA_ptr<OA::DGraph::NodeInterface> >::iterator it=nodeList->begin();
00824     for (; it!=nodeList->end(); ++it) {
00825       OA::OA_ptr<OA::DGraph::NodeInterface> n = *it;
00826       // if the node hasn't been visited then call recursively
00827       if (!visitMap[n]) {
00828         getReversePostDFSListR(cfg, n, visitMap, pList);
00829       }
00830     }
00831     // add ourselves to the beginning of the list
00832     // std::cout << " getReversePostDFSListR pushing for " << bbElem->getNodeName() << " " << bbElem->getAttribute(XAIFStrings.attr_Vid_x()) << std::endl;   
00833     pList->push_front(pNode);
00834   } 
00835 
00848   OA::OA_ptr<std::list<OA::OA_ptr<OA::DGraph::NodeInterface> > >
00849   getReversePostDFSList(OA::OA_ptr<OA::DGraph::DGraphInterface> cfg) { 
00850     std::map<OA::OA_ptr<OA::DGraph::NodeInterface>,bool> visitMap;
00851     // loop over all nodes and set their visit field to false
00852     OA::OA_ptr<OA::DGraph::NodesIteratorInterface> nodeIter = cfg->getNodesIterator();
00853     for ( ; nodeIter->isValid(); (*nodeIter)++ ) {
00854       OA::OA_ptr<OA::DGraph::NodeInterface> node = nodeIter->current();
00855       visitMap[node] = false;
00856     }
00857     // generate a list of nodes in the requested ordering
00858     OA::OA_ptr<std::list<OA::OA_ptr<OA::DGraph::NodeInterface> > > retval;
00859     retval = new std::list<OA::OA_ptr<OA::DGraph::NodeInterface> >;
00860     nodeIter = cfg->getEntryNodesIterator();
00861     for ( ; nodeIter->isValid(); (*nodeIter)++ ) {
00862       OA::OA_ptr<OA::DGraph::NodeInterface> on = nodeIter->current();
00863       getReversePostDFSListR(cfg,
00864                              nodeIter->current(), 
00865                              visitMap, 
00866                              retval);
00867     }
00868     return retval;
00869   } 
00870 
00871   // xlate_CFGunstruct: Helper for translating an unstructured CFG.  
00872   // 
00873   // Note: The CFG node (MyDGNode) id forms an implicit label number for
00874   // each basic block.  We do not worry about interfering with original
00875   // labels because we do not keep them.
00876   static WN*
00877   xlate_CFGunstruct(WN* wn_pu, OA::OA_ptr<OA::DGraph::DGraphInterface> cfg, 
00878                     OA::OA_ptr<MyDGNode> startNode, set<xercesc::DOMElement*>& xlated, 
00879                     PUXlationContext& ctxt,
00880                     unsigned int& startLabel_r)
00881   {
00882     //    using namespace OA::DGraph;
00883     //    using namespace OA::CFG;
00884 
00885 
00886     WN* blkWN = WN_CreateBlock();
00887 
00888     // Topological sort to ensure that, e.g., the exit node is last
00889 
00890     // ---------------------------------------------------
00891     // We must generate labels that do not conflict with other labels in
00892     // the WHIRL code.  We use two maps to remember label values.
00893     // ---------------------------------------------------
00894 
00895     map<OA::OA_ptr<MyDGNode>, unsigned> nodeToLblMap;
00896     map<OA::OA_ptr<MyDGNode>, unsigned> nodeToLoopContLblMap;
00897   
00898     // Initialize label maps
00899     OA::OA_ptr<std::list<OA::OA_ptr<OA::DGraph::NodeInterface> > > nodeList;
00900     nodeList=getReversePostDFSList(cfg);
00901     std::list<OA::OA_ptr<OA::DGraph::NodeInterface> >::iterator it= nodeList->begin();
00902     
00903     // the final label for this CFG guaranteed to be at the end
00904     unsigned endLabel=startLabel_r++;
00905     
00906     for (; it!=nodeList->end(); ++it) {
00907             
00908       OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = *it;
00909       OA::OA_ptr<MyDGNode> n = ntmp.convert<MyDGNode>();
00910       nodeToLblMap[n] = startLabel_r++;
00911     
00912       // See notes on translating loops below
00913       xercesc::DOMElement* bbElem = n->GetElem();
00914       if (XAIF_BBElemFilter::IsBBForLoop(bbElem) ||
00915           XAIF_BBElemFilter::IsBBPostLoop(bbElem)) {
00916         nodeToLoopContLblMap[n] = startLabel_r++;
00917       } 
00918       else if (XAIF_BBElemFilter::IsBBPreLoop(bbElem)) {
00919         nodeToLoopContLblMap[n] = nodeToLblMap[n];
00920       }
00921     }
00922   
00923     // ---------------------------------------------------
00924     // Translate in topological order
00925     // ---------------------------------------------------
00926     for (it= nodeList->begin(); it!=nodeList->end();++it) {
00927         
00928       OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = *it;
00929       OA::OA_ptr<MyDGNode> curNode = ntmp.convert<MyDGNode>();
00930       xercesc::DOMElement* bbElem = curNode->GetElem();
00931       unsigned curLbl = nodeToLblMap[curNode];
00932       // std::cout << " looking at " << bbElem->getNodeName() << std::endl;   
00933       if (XAIF_BBElemFilter::IsBBEntry(bbElem) ||
00934           XAIF_BBElemFilter::IsBBExit(bbElem) ||
00935           XAIF_BBElemFilter::IsBB(bbElem)) {
00936         // ---------------------------------------------------
00937         // A non-control-flow basic block
00938         // ---------------------------------------------------
00939         OA::OA_ptr<MyDGNode> nextNode = GetSuccessor(curNode); // at most one outgoing edge
00940         unsigned nextLbl = (!nextNode.ptrEqual(NULL)) ? nodeToLblMap[nextNode] : 0;
00941         if (XAIF_BBElemFilter::IsBBExit(bbElem))
00942           nextLbl=endLabel;
00943         WN* stmts = xlate_CFG_BasicBlock(wn_pu, 
00944                                          curNode, 
00945                                          ctxt, 
00946                                          true, 
00947                                          curLbl, 
00948                                          nextLbl,
00949                                          endLabel);
00950         WN_INSERT_BlockLast(blkWN, stmts);
00951       }
00952       else if (XAIF_BBElemFilter::IsBBBranch(bbElem)) {
00953         // ---------------------------------------------------
00954         // A branch with possibly unstructured control flow
00955         // ---------------------------------------------------
00956         unsigned int numOutEdges = curNode->num_outgoing();
00957 
00958         // 1. Translate condition expression
00959         xercesc::DOMElement* cond = 
00960           GetChildElement(bbElem, XAIFStrings.elem_Condition_x());
00961         xercesc::DOMElement* condexpr = GetFirstChildElement(cond);      
00962         WN* condWN = XlateExpression::translateExpression(condexpr, ctxt);
00963         if (numOutEdges == 2) {
00964           // Because branches are 'structured switches', ensure we have
00965           // a boolean expression for an 'if'.
00966           condWN = CreateIfCondition(condWN);
00967         }
00968       
00969         // 2. Gather all outgoing edges, sorted by condition (specially
00970         // sort two-way branches into true-false order.)
00971         OA::OA_ptr<MyDGEdge> tmp; tmp = NULL;
00972         vector<OA::OA_ptr<MyDGEdge> > outedges(numOutEdges, tmp);
00973         OA::OA_ptr<OA::DGraph::EdgesIteratorInterface> it
00974           = curNode->getOutgoingEdgesIterator();
00975         for (int i = 0; it->isValid(); ++(*it), ++i) {
00976           OA::OA_ptr<OA::DGraph::EdgeInterface> etmp = it->current();
00977           outedges[i] = etmp.convert<MyDGEdge>();
00978         }
00979         std::sort(outedges.begin(), outedges.end(), 
00980                   sort_CondVal((numOutEdges != 2)));
00981 
00982         // 3. Create branch control flow
00983         WN* lblWN = WN_CreateLabel(curLbl, 0 /*label_flag*/, NULL);
00984         WN_INSERT_BlockLast(blkWN, lblWN);
00985         if (numOutEdges == 2) {
00986           // Create GOTOs for each child block
00987           vector<WN*> childblksWN(numOutEdges, NULL);
00988           for (unsigned i = 0; i < outedges.size(); ++i) {
00989             OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = outedges[i]->getSink();
00990             OA::OA_ptr<MyDGNode> n = ntmp.convert<MyDGNode>();
00991             WN* gotoblkWN = WN_CreateBlock();
00992             WN* gotoWN = WN_CreateGoto(nodeToLblMap[n]);
00993             WN_INSERT_BlockFirst(gotoblkWN, gotoWN);
00994             childblksWN[i] = gotoblkWN;
00995           }
00996         
00997           // Create IF with GOTOs
00998           WN* ifWN = WN_CreateIf(condWN, childblksWN[0], childblksWN[1]);
00999           WN_INSERT_BlockLast(blkWN, ifWN);
01000         } 
01001         else {
01002           unsigned lastLbl = 0; // do not know last label
01003         
01004           // Create SWITCH with CASEGOTOs
01005           WN* switchWN = xlate_CFG_BranchMulti(curNode, condWN, lastLbl,
01006                                                outedges, nodeToLblMap);
01007           WN_INSERT_BlockLast(blkWN, switchWN);
01008         }
01009       }
01010       else if (XAIF_BBElemFilter::IsBBEndBr(bbElem)) {
01011         // ---------------------------------------------------
01012         // EndBranch: a dummy basic block
01013         // ---------------------------------------------------
01014         OA::OA_ptr<MyDGNode> nextNode = GetSuccessor(curNode); // at most one outgoing edge
01015         unsigned nextLbl = (!nextNode.ptrEqual(NULL)) ? nodeToLblMap[nextNode] : 0;
01016         WN* stmts = xlate_CFG_BasicBlock(wn_pu, 
01017                                          curNode, 
01018                                          ctxt, 
01019                                          true, 
01020                                          curLbl, 
01021                                          nextLbl,
01022                                          endLabel);
01023         WN_INSERT_BlockLast(blkWN, stmts);
01024       }
01025       else if (XAIF_BBElemFilter::IsBBForLoop(bbElem) ||
01026                XAIF_BBElemFilter::IsBBPreLoop(bbElem) ||
01027                XAIF_BBElemFilter::IsBBPostLoop(bbElem)) {
01028         // ---------------------------------------------------
01029         // A loop with possibly unstructured control flow
01030         // ---------------------------------------------------
01031       
01032         // XAIF Loop sub-graphs
01033         // --------------------
01034         //   ForLoop ---> [loopbody nodes...] ---> EndLoop--| 
01035         //     Init  \                                   <--| (backedge)
01036         //     Cond   \
01037           //     Update  \------------------------------------> fallthru block
01038         //             
01039         //   PreLoop and PostLoop are the same, but without special Init
01040         //   and Update statements.
01041         // 
01042         // Translation into unstructured WHIRL:
01043         // ForLoop               PreLoop               PostLoop
01044         // ----------------------------------------------------------------
01045         // label for_loop
01046         // Init
01047         // goto for_test                               
01048         // label for_cntnue                            label post_loop
01049         // Update                                      goto loop_body
01050         // label for_test        label pre_loop        label post_cntnue
01051         // if (Cond)             if (Cond)             if (Cond)
01052         //   goto loop_body        goto loop_body        goto loop_body
01053         // else                  else                  else
01054         //   goto fallthru_blk     goto fallthru_blk     goto fallthru_blk
01055         // 
01056         // ----------------------------------------------------------------
01057         //  [fallthru subgraph]  label loop_body
01058         //                       ... 
01059         //                       goto end_loop
01060         //
01061         //            [EndLoop]  label end_loop
01062         //                       goto for_cntnue/pre_loop/post_cntnue
01063         //
01064         // Note: Moving Init and Update statments out of the 'loop
01065         // scope' is not a problem -- i.e. there won't be symbol clashes
01066         // -- because in WHIRL the whole procedure is actually in the same
01067         // lexical scope.
01068       
01069         bool isDoLoop = (XAIF_BBElemFilter::IsBBForLoop(bbElem));
01070       
01071         // 1. Gather children
01072         OA::OA_ptr<MyDGNode> bodyNode = GetSuccessorAlongEdge(curNode, 1);
01073         OA::OA_ptr<MyDGNode> fallthruNode = GetSuccessorAlongEdge(curNode, 0);
01074       
01075         // 2. Translate condition expression (and update/init statements)
01076         xercesc::DOMElement* cond = 
01077           GetChildElement(bbElem, XAIFStrings.elem_Condition_x());
01078         xercesc::DOMElement* condexpr = GetFirstChildElement(cond);
01079         WN* condWN = NULL;
01080         if (isDoLoop) {
01081           condWN = XlateExpression::translateExpressionSimple(condexpr, ctxt);
01082         } else {
01083           condWN = XlateExpression::translateExpression(condexpr, ctxt);
01084         }
01085       
01086         xercesc::DOMElement *init = NULL, *update = NULL;
01087         WN *initWN = NULL, *updateWN = NULL;
01088         if (XAIF_BBElemFilter::IsBBForLoop(bbElem)) {
01089           // Note: initWN and updateWN are STIDs
01090           const XMLCh* lineNumberX = bbElem->getAttribute(XAIFStrings.attr_lineNumber_x());
01091           XercesStrX lineNumber = XercesStrX(lineNumberX);
01092           FORTTK_MSG(2, "doing loop with line number attribute: " << lineNumber.c_str())         
01093           init = GetChildElement(bbElem, XAIFStrings.elem_LpInit_x());
01094           update = GetChildElement(bbElem, XAIFStrings.elem_LpUpdate_x());
01095           initWN = XlateStmt::translateStmt(init, ctxt);
01096           updateWN = XlateStmt::translateStmt(update, ctxt);
01097         }
01098       
01099         // 3. Create loop control flow
01100         // Create loop label
01101         WN* lblWN = WN_CreateLabel(curLbl, 0 /*label_flag*/, NULL);
01102         WN_INSERT_BlockLast(blkWN, lblWN);
01103       
01104         // Create other special pre-loop statements
01105         WN* stmtWN = NULL;
01106         if (isDoLoop) {
01107           INT32 lbl_test = startLabel_r++;
01108           INT32 lbl_cntnue = nodeToLoopContLblMap[curNode];
01109         
01110           WN_INSERT_BlockLast(blkWN, initWN); // Init
01111           WN* gotoWN = WN_CreateGoto(lbl_test);
01112           WN_INSERT_BlockLast(blkWN, gotoWN);
01113           WN* lbl1WN = WN_CreateLabel(lbl_cntnue, 0 /*label_flag*/, NULL);
01114           WN_INSERT_BlockLast(blkWN, lbl1WN);
01115           WN_INSERT_BlockLast(blkWN, updateWN); // Update
01116           WN* lbl2WN = WN_CreateLabel(lbl_test, 0 /*label_flag*/, NULL);
01117           WN_INSERT_BlockLast(blkWN, lbl2WN);
01118         }
01119         else if (XAIF_BBElemFilter::IsBBPostLoop(bbElem)) {
01120           INT32 lbl_cntnue = nodeToLoopContLblMap[curNode];
01121 
01122           WN* gotoWN = WN_CreateGoto(nodeToLblMap[bodyNode]);
01123           WN_INSERT_BlockLast(blkWN, gotoWN);
01124           WN* lblWN = WN_CreateLabel(lbl_cntnue, 0 /*label_flag*/, NULL);
01125           WN_INSERT_BlockLast(blkWN, lblWN);
01126         }
01127       
01128         // Create 'if (Cond)'
01129         WN* thenblkWN = WN_CreateBlock();
01130         WN* elseblkWN = WN_CreateBlock();
01131         WN* thenWN = WN_CreateGoto(nodeToLblMap[bodyNode]);
01132         WN* elseWN = WN_CreateGoto(nodeToLblMap[fallthruNode]);
01133         WN_INSERT_BlockFirst(thenblkWN, thenWN);
01134         WN_INSERT_BlockFirst(elseblkWN, elseWN);
01135       
01136         WN* ifWN = WN_CreateIf(condWN, thenblkWN, elseblkWN);
01137         WN_INSERT_BlockLast(blkWN, ifWN);
01138       }
01139       else if (XAIF_BBElemFilter::IsBBEndLoop(bbElem)) {
01140         // ---------------------------------------------------
01141         // The loop back-branch: loop back to continue branch!
01142         // ---------------------------------------------------
01143         OA::OA_ptr<MyDGNode> nextNode = GetSuccessor(curNode); // at most one outgoing edge
01144         unsigned nextLbl = (!nextNode.ptrEqual(NULL)) ? nodeToLoopContLblMap[nextNode] : 0;
01145         WN* stmts = xlate_CFG_BasicBlock(wn_pu, 
01146                                          curNode, 
01147                                          ctxt, 
01148                                          true, 
01149                                          curLbl, 
01150                                          nextLbl,
01151                                          endLabel);
01152         WN_INSERT_BlockLast(blkWN, stmts);
01153       }
01154       else {
01155         FORTTK_DIE("Unknown XAIF basic block:\n" << *bbElem);
01156       }
01157     }
01158     WN* lblWN = WN_CreateLabel(endLabel, 0 /*label_flag*/, NULL);
01159     WN_INSERT_BlockLast(blkWN, lblWN);
01160     return blkWN;
01161   }  
01162 
01163 
01164   // xlate_CFG_BasicBlock: Translate a non-control-flow basic block.
01165   // Optionally skips GOTOs and LABELs within 'wn_pu'.
01166   // Optionally adds a label at the beginning of the block and a
01167   // 'fallthru-goto' at the end if non-zero labels are provided.
01168   static WN*
01169   xlate_CFG_BasicBlock(WN *wn_pu, OA::OA_ptr<MyDGNode> curBB, 
01170                        PUXlationContext& ctxt, 
01171                        bool skipMarkeredGotoAndLabels, 
01172                        unsigned newCurBBLbl, 
01173                        unsigned newNextBBLbl,
01174                        unsigned endLabel)
01175   {
01176     xercesc::DOMElement* bbElem = curBB->GetElem();
01177 
01178     // typically addNewGotoAndLabels is only true when
01179     // skipOldGotoAndLabels is also true
01180     bool skipOldGotoAndLabels = skipMarkeredGotoAndLabels;
01181     bool addNewGotoAndLabels = (newCurBBLbl != 0); 
01182   
01183     // 1. Translate (if we add our own goto's and labels, then we need
01184     // to throw away any original goto and label at the end and
01185     // beginning of the block)
01186     WN* stmtblk = TranslateBasicBlock(wn_pu, bbElem, ctxt, skipOldGotoAndLabels,endLabel);
01187   
01188     // 2. If necessary, add a label to front and goto at end
01189     if (addNewGotoAndLabels) {
01190       WN* lblWN = WN_CreateLabel(newCurBBLbl, 0 /*label_flag*/, NULL);
01191       WN_INSERT_BlockFirst(stmtblk, lblWN);
01192     
01193       if (newNextBBLbl != 0) {
01194         WN* gotoWN = WN_CreateGoto(newNextBBLbl);
01195         WN_INSERT_BlockLast(stmtblk, gotoWN); 
01196       }
01197     }
01198   
01199     return stmtblk;
01200   }
01201 
01202 
01203   // xlate_CFG_BranchMulti: abstract translation of multi-way branches
01204   static WN*
01205   xlate_CFG_BranchMulti(OA::OA_ptr<MyDGNode> curNode, WN* condWN, 
01206                         unsigned lastLbl,
01207                         vector<OA::OA_ptr<MyDGEdge> >& outedges,
01208                         map<OA::OA_ptr<MyDGNode>, unsigned>& nodeToLblMap)
01209   {
01210     // Case values are in ascending order; the default case (if any)
01211     // will be at the beginning and have a false condition attribute
01212   
01213     // Create default goto if necessary
01214     WN* defltWN = NULL;
01215     int defltIdx = -1;
01216     if (!GetHasConditionAttr(outedges[0]->GetElem())) {
01217       defltIdx = 0;
01218       OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = outedges[0]->getSink();
01219       OA::OA_ptr<MyDGNode> n = ntmp.convert<MyDGNode>();
01220       unsigned gotolbl = nodeToLblMap[n];
01221       defltWN = WN_CreateGoto(gotolbl);
01222     }
01223   
01224     // Create casegoto for each block
01225     WN* casegotoBlkWN = WN_CreateBlock();
01226     int numcases = outedges.size() - (defltIdx + 1);
01227     for (unsigned i = defltIdx + 1; i < outedges.size(); ++i) {
01228       xercesc::DOMElement* elemEdge = outedges[i]->GetElem();
01229       OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = outedges[i]->getSink();
01230       OA::OA_ptr<MyDGNode> n = ntmp.convert<MyDGNode>();
01231     
01232       INT64 caseval = GetCondAttr(elemEdge);
01233       WN* wn = WN_CreateCasegoto(caseval, nodeToLblMap[n]);
01234       WN_INSERT_BlockLast(casegotoBlkWN, wn);
01235     }
01236   
01237     // Create switch
01238     WN* switchWN = WN_CreateSwitch(numcases, condWN, casegotoBlkWN,
01239                                    defltWN, lastLbl);
01240   
01241     return switchWN;
01242   }
01243 
01244 
01245   // TranslateBasicBlock: Translate a non-control-flow basic block
01246   static WN*
01247   TranslateBasicBlock(WN *wn_pu, 
01248                       const xercesc::DOMElement* bbElem, 
01249                       PUXlationContext& ctxt,
01250                       bool skipMarkeredGotoAndLabels,
01251                       unsigned endLabel)
01252   {
01253     WN* blkWN = WN_CreateBlock();
01254 
01255     // -------------------------------------------------------
01256     // 1. Find some info now to prevent several recalculations
01257     // -------------------------------------------------------
01258     // FIXME: use parent map -- w2x does not need to generate this id list 
01259     fortTkSupport::IdList<fortTkSupport::WNId>* idlist = GetWNIdList(bbElem); // FIXME
01260     WN* origblkWN = FindWNBlock(bbElem, idlist, ctxt);
01261     if (idlist->size() > 0) { 
01262       FORTTK_ASSERT(origblkWN, "Could not find WHIRL block for:\n" << *bbElem);
01263     }
01264 
01265     // -------------------------------------------------------
01266     // 2. Translate statements
01267     // -------------------------------------------------------
01268     XAIF_BBStmtElemFilter filt;
01269     for (xercesc::DOMElement* stmt = GetChildElement(bbElem, &filt);
01270          (stmt); stmt = GetNextSiblingElement(stmt, &filt)) {
01271       WN* wn = NULL;
01272       if (XAIF_BBStmtElemFilter::IsMarker(stmt)) {
01273         bool isGotoOrLabel = (IsTagPresent(stmt, XAIFStrings.tag_StmtGoto()) ||
01274                               IsTagPresent(stmt, XAIFStrings.tag_StmtLabel()));
01275         bool skip = (isGotoOrLabel && skipMarkeredGotoAndLabels);
01276         if (!skip) {
01277           if (IsTagPresent(stmt, XAIFStrings.tag_StmtReturn())) { 
01278             // replace return with goto endlabel
01279             wn = WN_CreateGoto(endLabel);
01280           }
01281           else { 
01282             fortTkSupport::WNId id = GetWNId(stmt);
01283             WN* foundWN = ctxt.findWN(id, true /* mustFind */);
01284             wn = WN_COPY_Tree(foundWN);
01285             XlateStmt::patchWNStmt(wn, ctxt); // FIXME
01286           }
01287         }
01288       }
01289       else {
01290         wn = XlateStmt::translateStmt(stmt, ctxt);
01291       }
01292       if (wn) {
01293         WN_INSERT_BlockLast(blkWN, wn);
01294       }
01295     }
01296     return blkWN;
01297   }
01298 
01299 
01300   // ****************************************************************************
01301   // ControlFlowGraph -- basic block patching algorithm
01302   // ****************************************************************************
01303 
01304   static void
01305   TranslateBB_OLD(WN *wn_pu, const xercesc::DOMElement* bbElem, PUXlationContext& ctxt)
01306   {
01307     if (XAIF_BBElemFilter::IsBB(bbElem)) {
01308       xlate_BasicBlock_OLD(wn_pu, bbElem, ctxt);
01309     } 
01310     else if (XAIF_BBElemFilter::IsBBBranch(bbElem)
01311              || XAIF_BBElemFilter::IsBBPreLoop(bbElem)
01312              || XAIF_BBElemFilter::IsBBPostLoop(bbElem)) {
01313       xlate_BBCond_OLD(wn_pu, bbElem, ctxt);
01314     } 
01315     else if (XAIF_BBElemFilter::IsBBForLoop(bbElem)) {
01316       // FIXME: what to do with ForLoops?
01317     } 
01318     else {
01319       // skip anything else for now
01320     }
01321   }
01322 
01323 
01324   static void
01325   xlate_BasicBlock_OLD(WN *wn_pu, const xercesc::DOMElement* bbElem, PUXlationContext& ctxt)
01326   {
01327     // -------------------------------------------------------
01328     // 1. Find some info now to prevent several recalculations
01329     // -------------------------------------------------------
01330     fortTkSupport::IdList<fortTkSupport::WNId>* idlist = GetWNIdList(bbElem);
01331     WN* blkWN = FindWNBlock(bbElem, idlist, ctxt);
01332     if (idlist->size() > 0) { 
01333       FORTTK_ASSERT(blkWN, "Could not find WHIRL block for:\n" << *bbElem);
01334     }
01335   
01336     // -------------------------------------------------------
01337     // 2. Translate statements
01338     // -------------------------------------------------------  
01339     xercesc::DOMElement* begXAIF = NULL, *endXAIF = NULL;
01340     WN* begWN = NULL, *endWN = NULL;
01341     while (FindNextStmtInterval(bbElem, idlist, ctxt.getWNIdToWNMap(), blkWN,
01342                                 begXAIF, endXAIF, begWN, endWN)) {
01343     
01344       // We now have two non-NULL intervals.  [begWN, endWN] represents
01345       // the WHIRL statements that will be replaced with the XAIF
01346       // statements [begXAIF, endXAIF]
01347     
01348       // 1. Find (or create) a statement just prior to the interval to
01349       // serve as an insertion point.
01350       WN* ipWN = FindSafeInsertionPoint(blkWN, begWN);
01351 
01352       // 2. Delete all WHIRL statements within [begWN, endWN]
01353       WN* it1End = WN_next(endWN); // result may be NULL
01354       for (WN* wn = begWN; (wn != it1End); wn = WN_next(wn)) {
01355         // Remove from persistent id maps (to assist debugging)
01356         RemoveFromWhirlIdMaps(wn, ctxt.getWNToWNIdMap(), ctxt.getWNIdToWNMap());
01357         WN_DELETE_FromBlock(blkWN, wn);
01358       }
01359     
01360       // 3. For each new XAIF statement within [begXAIF, endXAIF],
01361       // create a WHIRL node and insert it
01362       xercesc::DOMElement* it2End = GetNextSiblingElement(endXAIF); // result may be NULL
01363       for (xercesc::DOMElement* stmt = begXAIF; (stmt != it2End); 
01364            stmt = GetNextSiblingElement(stmt)) {
01365       
01366         WN* wn = XlateStmt::translateStmt(stmt, ctxt);
01367         if (!wn) { continue; }
01368 
01369         // Find the soon-to-be new insertion point
01370         WN* newIP = (WN_operator(wn) == OPR_BLOCK) ? WN_last(wn) : wn;
01371 
01372         // If 'wn' is a OPR_BLOCK, the block is automatically deleted
01373         WN_INSERT_BlockAfter(blkWN, ipWN, wn); 
01374         ipWN = newIP; // update the new insertion point
01375       }
01376     }
01377 
01378     // -------------------------------------------------------
01379     // 3. Patch certain statements represented by xaif:Markers
01380     // -------------------------------------------------------
01381     for (xercesc::DOMElement* stmt = GetFirstChildElement(bbElem); (stmt); 
01382          stmt = GetNextSiblingElement(stmt, XAIFStrings.elem_Marker_x())) {
01383       fortTkSupport::WNId id = GetWNId(stmt);
01384       if (id != 0) {
01385         WN* wn = ctxt.findWN(id, true /* mustFind */);
01386         XlateStmt::patchWNStmt(wn, ctxt);
01387       }
01388     }
01389   
01390     // -------------------------------------------------------
01391     // 4. Cleanup
01392     // -------------------------------------------------------
01393     delete idlist;
01394   }
01395 
01396 
01397   static void
01398   xlate_BBCond_OLD(WN* wn_pu, const xercesc::DOMElement* bbElem, PUXlationContext& ctxt)
01399   {
01400     // -------------------------------------------------------
01401     // 1. Find corresponding WHIRL condition node
01402     // -------------------------------------------------------
01403     // Conveniently, XAIF 'if' or 'loop' condition is represented by the
01404     // WHIRL structured control flow node, i.e. the corresponding WHIRL
01405     // 'if' or 'loop'.
01406     fortTkSupport::IdList<fortTkSupport::WNId>* idlist = GetWNIdList(bbElem);
01407 
01408     xercesc::DOMElement* cond = GetChildElement(bbElem, XAIFStrings.elem_Condition_x());
01409     if (cond) {
01410       FORTTK_ASSERT(idlist->size() == 1, "Invalid id list:\n" << *cond);
01411     }
01412 
01413     WN* wn = ctxt.findWN(idlist->front(), true /* mustFind */);
01414 
01415     INT condKid = 0;
01416     OPERATOR opr = WN_operator(wn);
01417     switch (opr) {
01418     
01419     case OPR_DO_WHILE:
01420     case OPR_WHILE_DO:
01421       condKid = 0; // WN_kid0(wn) == WN_while_test(wn)
01422       break;
01423 
01424     case OPR_IF:
01425     case OPR_TRUEBR:
01426     case OPR_FALSEBR:
01427       condKid = 0; // WN_kid0(wn) == WN_if_test(wn)
01428       break;
01429 
01430     case OPR_SWITCH:
01431       condKid = -1;
01432       break; // integer expression
01433     
01434     default: 
01435       FORTTK_DIE(fortTkSupport::Diagnostics::UnexpectedOpr << OPERATOR_name(opr));
01436     }
01437   
01438     // -------------------------------------------------------
01439     // 2. Ensure the condition expression is patched
01440     // -------------------------------------------------------
01441     if (condKid >= 0) {
01442       XlateExpression::patchWNExpr(wn, condKid /* kidno */, ctxt);
01443     }
01444   }
01445 
01446 
01447   // FindNextStmtInterval: Finds the next translation interval within
01448   // the XAIF BB 'bbElem' given the current interval.  The current
01449   // interval's status is defined by [begXAIF, endXAIF] both of which
01450   // are NULL when no interval yet exists.  The function finds two new
01451   // intervals, the XAIF statements [begXAIF, endXAIF] and their
01452   // corresponding WHIRL statements [begWN, endWN].  Returns true if an
01453   // interval has been found and the interval boundaries appropriately
01454   // updated; otherwise, returns false.  Note that in the latter case,
01455   // original interval boundaries are not necessary preserved.
01456   //
01457   // Intervals within the BB are created by the presence of xaif:Marker
01458   // elements that contain a WhirlId annotation, but xaif:Marker's are
01459   // not actually within the interval.  If no explicit xaif:Marker
01460   // begins or ends the BB, its existence is assumed.  Consequently, for
01461   // non-NULL intervals, 'begXAIF' and 'endXAIF' will never point to an
01462   // xaif:Marker element with annotation attribute and will never be
01463   // NULL.
01464   static bool
01465   FindNextStmtInterval(const xercesc::DOMElement* bbElem, fortTkSupport::IdList<fortTkSupport::WNId>* bbIdList, 
01466                        fortTkSupport::WNIdToWNMap* wnmap, WN* blkWN,
01467                        xercesc::DOMElement* &begXAIF, xercesc::DOMElement* &endXAIF,
01468                        WN* &begWN, WN* &endWN)
01469   {
01470     // 1. Find beginning of the interval
01471     if (!begXAIF) {
01472       begXAIF = GetFirstChildElement(bbElem);   // first interval (tmp)
01473     } 
01474     else if (endXAIF) {
01475       begXAIF = GetNextSiblingElement(endXAIF); // successive intervals (tmp)
01476     } 
01477     else {
01478       begXAIF = NULL;                           // no more intervals exist
01479     }  
01480   
01481     // If 'begXAIF' is non-NULL, it points to a temporary beginning
01482     // point.  From this point, find the first non-xaif:Marker element.
01483     // This skips over consecutive sequences of xaif:Markers, a
01484     // necessary step to obtain a correct boundary begin point.
01485     while (begXAIF) {
01486       if (XAIF_BBStmtElemFilter::IsMarker(begXAIF) && GetWNId(begXAIF) != 0) {
01487         begXAIF = GetNextSiblingElement(begXAIF);
01488       } else {
01489         break; // not an xaif:Marker with WhirlId annotation!
01490       }
01491     } // Note: 'begXAIF' could be NULL now indicating a NULL interval  
01492     begWN = FindIntervalBoundary(begXAIF, bbIdList, wnmap, blkWN, 0 /* beg */);
01493   
01494     // 2. Find ending of the interval
01495     if (begXAIF) {
01496 
01497       // See if another xaif:Marker exists containing a WhirlId
01498       // annotation; if not, 'endXAIF' will be NULL.  (Note that we may
01499       // encounter an xaif:Marker without the annotation.)
01500       endXAIF = begXAIF; // of course, we start from the beginning!
01501       while ( (endXAIF = 
01502                GetNextSiblingElement(endXAIF, XAIFStrings.elem_Marker_x())) ) {
01503         if (GetWNId(endXAIF) != 0) {
01504           break; // found!
01505         }
01506       }
01507     
01508       // If 'endXAIF' is non-NULL, it points to the first xaif:Marker
01509       // after 'begXAIF'.  If it is NULL, we use the very last element
01510       // (which must be a non-xaif:Marker).
01511       if (endXAIF) {
01512         endXAIF = GetPrevSiblingElement(endXAIF);
01513       } else {
01514         endXAIF = GetLastChildElement(bbElem);
01515       }
01516       endWN = FindIntervalBoundary(endXAIF, bbIdList, wnmap, blkWN, 1 /* end */);
01517     
01518     } else {
01519       endXAIF = NULL;
01520       endWN = NULL;
01521     }  
01522   
01523     return (begXAIF && begWN);
01524   }
01525 
01526 
01527   // FindIntervalBoundary: Finds the appropriate WN* for the given
01528   // interval boundary statement 'elem' and boundary type (begin/end).
01529   // The boundary is assumed to be of the form [beg, end], where beg and
01530   // end are never xaif:Marker statements.  N.B.: It is assumed that
01531   // this function is called for the begin interval *before* being
01532   // called for the end interval.
01533   //
01534   // boundary: 0 (begin), 1 (end)
01535   //
01536   // For begin and end boundaries: If 'elem' is non-NULL the
01537   // corrresponding WN* should never be NULL.  If 'elem' is NULL, the
01538   // interval is NULL.
01539   static WN*
01540   FindIntervalBoundary(const xercesc::DOMElement* elem, fortTkSupport::IdList<fortTkSupport::WNId>* bbIdList, 
01541                        fortTkSupport::WNIdToWNMap* wnmap, WN* blkWN, int boundary)
01542   {
01543     if (!elem) {
01544       return NULL;
01545     }
01546 
01547     WN* wn = NULL;
01548     if (boundary == 0) {
01549       // For begin boundaries: If the previous element is an xaif:Marker
01550       // with WhirlId annotation, use it to find the WN*; otherwise try
01551       // to use 'bbIdList' to return the first WN* in the list.
01552       xercesc::DOMElement* adj = GetPrevSiblingElement(elem);
01553       if (adj && XAIF_BBStmtElemFilter::IsMarker(adj)) {
01554         fortTkSupport::WNId id = GetWNId(adj);
01555         if (id != 0) {
01556           wn = wnmap->Find(id, true /* mustFind */);
01557 
01558           // We used 'adj' (instead of 'elem') to find 'wn'.  Correct
01559           // the interval boundary by moving in the opposite direction.
01560           WN* nextWN = WN_next(wn); // Result may be NULL! (see above)
01561 
01562           if (nextWN) {
01563             wn = nextWN;
01564           } else {
01565             // The interval corresponding to 'elem' is the NULL interval
01566             // after 'wn'.  We must create a dummy WN* to represent it
01567             // with [beg, end) notation.
01568             WN* newWN = WN_CreateAssert(0, WN_CreateIntconst(OPC_I4INTCONST, 
01569                                                              (INT64)1));
01570             WN_INSERT_BlockAfter(blkWN, wn, newWN);
01571             wn = newWN; // set 'wn' to the new node
01572           }
01573         }
01574       }
01575       if (!wn && bbIdList->size() > 0) {
01576         wn = wnmap->Find(bbIdList->front(), true /* mustFind */);
01577       }
01578     } 
01579     else if (boundary == 1) {
01580       // For end boundaries: If the next element is an xaif:Marker
01581       // with WhirlId annotation, use it to find the WN*; otherwise try
01582       // to use 'bbIdList' to return the last WN* in the list.
01583       xercesc::DOMElement* adj = GetNextSiblingElement(elem);
01584       if (adj && XAIF_BBStmtElemFilter::IsMarker(adj)) {
01585         fortTkSupport::WNId id = GetWNId(adj);
01586         if (id != 0) {
01587           wn = wnmap->Find(id, true /* mustFind */);
01588 
01589           // We used 'adj' (instead of 'elem') to find 'wn'.  Correct
01590           // the interval boundary by moving in the opposite direction.
01591           WN* prevWN = WN_prev(wn); // never NULL b/c of insertion above!
01592           FORTTK_ASSERT(prevWN, "Internal error");
01593 
01594           wn = prevWN;
01595         }
01596       }
01597       if (!wn && bbIdList->size() > 0) {
01598         wn = wnmap->Find(bbIdList->back(), true /* mustFind */);
01599       }
01600     } 
01601     else {
01602       FORTTK_DIE("Internal error.");
01603     }
01604   
01605     return wn;
01606   }
01607 
01608 
01609   // FindWNBlock: Given an XAIF basic block element, find the
01610   // corresponding WHIRL block.
01611   static WN* 
01612   FindWNBlock(const xercesc::DOMElement* bbElem, fortTkSupport::IdList<fortTkSupport::WNId>* idlist, 
01613               PUXlationContext& ctxt)
01614   {
01615     // We pass 'idlist' to avoid continual reparsing
01616     WN* wn = NULL;
01617     if (idlist->size() > 0) {
01618       fortTkSupport::WNId id = idlist->front();
01619       wn = ctxt.findWN(id, true /* mustFind */);
01620     }
01621   
01622     WN* blk = NULL;
01623     if (wn) {
01624       blk = ctxt.findParentBlockWN(wn);
01625     }
01626     return blk;
01627   }
01628 
01629 
01630   // FindSafeInsertionPoint: Given a WHIRL statement node 'stmtWN' and
01631   // its containing block 'blckWN', find (or create) the statement just
01632   // prior to 'stmtWN'.
01633   static WN* 
01634   FindSafeInsertionPoint(WN* blckWN, WN* stmtWN)
01635   {
01636     WN* ipWN = NULL;
01637 
01638     // 1. Just return the previous statement, if available
01639     if ( (ipWN = WN_prev(stmtWN)) != NULL ) {
01640       return ipWN;
01641     }
01642 
01643     // 2. There is no previous statement so we insert a dummy stmt to
01644     // serve as a handle.  whirl2f should ignore this.  (If not, a
01645     // compiler will be able to optimize this away.)
01646     ipWN = WN_CreateAssert(0, WN_CreateIntconst(OPC_I4INTCONST, (INT64)1));
01647     WN_INSERT_BlockBefore(blckWN, stmtWN, ipWN);
01648     return ipWN;
01649   }
01650 
01651 
01652   // RemoveFromWhirlIdMaps: Remove 'wn' and all of its descendents from
01653   // the WhirlId maps.
01654   static void
01655   RemoveFromWhirlIdMaps(WN* wn, fortTkSupport::WNToWNIdMap* wn2idmap, fortTkSupport::WNIdToWNMap* id2wnmap)
01656   {
01657     WN_TREE_CONTAINER<PRE_ORDER> wtree(wn);
01658     WN_TREE_CONTAINER<PRE_ORDER>::iterator it;
01659     for (it = wtree.begin(); it != wtree.end(); ++it) {
01660       WN* curWN = it.Wn();
01661 
01662       fortTkSupport::WNId curId = 0;
01663       fortTkSupport::WNToWNIdMap::iterator it1 = wn2idmap->find(curWN);
01664       if (it1 != wn2idmap->end()) {
01665         curId = (*it1).second;
01666         wn2idmap->erase(it1);
01667       }
01668       id2wnmap->erase(curId);
01669     }
01670   }
01671 
01672 
01673   // ****************************************************************************
01674   // Scopes and Symbols
01675   // ****************************************************************************
01676 
01677   fortTkSupport::Symbol*
01678   GetSymbol(const xercesc::DOMElement* elem, PUXlationContext& ctxt)
01679   {
01680     const XMLCh* scopeIdX = elem->getAttribute(XAIFStrings.attr_scopeId_x());
01681     const XMLCh* symIdX = elem->getAttribute(XAIFStrings.attr_symId_x());
01682 
01683     XercesStrX scopeId = XercesStrX(scopeIdX);
01684     XercesStrX symId = XercesStrX(symIdX);
01685   
01686     FORTTK_ASSERT(strcmp(scopeId.c_str(), "") != 0 && 
01687                   strcmp(symId.c_str(), "") != 0,
01688                   "Invalid id attribute:\n" << *elem);
01689   
01690     return ctxt.findSym(scopeId.c_str(), symId.c_str());
01691   }
01692 
01693 
01694   fortTkSupport::Symbol*
01695   GetOrCreateSymbol(const char* sname, PUXlationContext& ctxt)
01696   {
01697     // FIXME: make more general
01698     bool active = false;
01699   
01700     // FIXME: need to associate current PU with a scope id...
01701     const char* scopeId = "1"; // assume global for now
01702   
01703     fortTkSupport::Symbol* sym = ctxt.getXAIFSymToSymbolMap().Find(scopeId, sname);
01704     if (!sym) {
01705       // FIXME: use CreateST...
01706       TY_IDX ty = MTYPE_To_TY(MTYPE_F8);
01707       SYMTAB_IDX level = GLOBAL_SYMTAB; // FIXME: coordinate with scopeId
01708       ST* st = New_ST(level);
01709       ST_Init(st, Save_Str(sname), CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL, ty);
01710     
01711       sym = new fortTkSupport::Symbol(st, 0, active);
01712       ctxt.getXAIFSymToSymbolMap().Insert(scopeId, sname, sym);
01713     }
01714     return sym;
01715   }
01716 
01717 
01718   fortTkSupport::Symbol*
01719   GetOrCreateBogusTmpSymbol(PUXlationContext& ctxt)
01720   {
01721     static const char* sname = "OpenAD_bogus";
01722     return GetOrCreateSymbol(sname, ctxt);
01723   }
01724 
01725 
01726   // ****************************************************************************
01727 
01728   void
01729   xlate_Scope(const xercesc::DOMElement* elem,
01730               PUXlationContext& ctxt) {
01731     // Find the corresponding WHIRL symbol table (ST_TAB)
01732     fortTkSupport::SymTabId symtabId = GetSymTabId(elem);
01733     pair<ST_TAB*, PU_Info*> stab = ctxt.findSymTab(symtabId);
01734   
01735     PU_Info* pu = stab.second;
01736     if (pu) { // This is a local symbol table; restore it's global state.
01737       PU_SetGlobalState(pu);
01738     
01739       // Need WHIRL<->ID maps for translating ScalarizedRefs
01740       fortTkSupport::WNIdToWNMap* wnmap = WNIdToWNTableMap.Find(pu);
01741       ctxt.setWNIdToWNMap(wnmap);
01742     }
01743   
01744     // Find the scope id
01745     const XMLCh* scopeIdX = elem->getAttribute(XAIFStrings.attr_Vid_x());
01746     XercesStrX scopeId = XercesStrX(scopeIdX);
01747 
01748     // Translate the xaif:SymbolTable (the only child)
01749     xercesc::DOMElement* symtabElem = GetFirstChildElement(elem);
01750     xlate_SymbolTable(symtabElem, scopeId.c_str(), pu, ctxt);
01751   }  
01752 
01753 
01754   static void
01755   xlate_SymbolTable(const xercesc::DOMElement* elem,
01756                     const char* scopeId, PU_Info* pu,
01757                     PUXlationContext& ctxt) {
01758     // For all xaif:fortTkSupport::Symbol in the xaif:SymbolTable
01759     XAIF_SymbolElemFilter filt;
01760     for (xercesc::DOMElement* e = GetChildElement(elem, &filt);
01761          (e); e = GetNextSiblingElement(e, &filt)) {
01762       // do the non-temporary ones first
01763       xlate_Symbol(e, scopeId, pu, ctxt, false);
01764     }
01765     for (xercesc::DOMElement* e = GetChildElement(elem, &filt);
01766          (e); e = GetNextSiblingElement(e, &filt)) {
01767       // now do the temporary ones since in the 
01768       // subroutine ones we refer to the original 
01769       // subroutine symbols so we had to translate those
01770       // first.
01771       xlate_Symbol(e, scopeId, pu, ctxt, true);
01772     }
01773   }
01774 
01775 
01776   // xlate_Symbol: Note that symbols can only be in a global or PU
01777   // scope; IOW, there are no block scopes.
01778   static void
01779   xlate_Symbol(const xercesc::DOMElement* elem, 
01780                const char* scopeId, 
01781                PU_Info* pu, 
01782                PUXlationContext& ctxt, 
01783                bool doTempSymbols) {
01784     // at this time do we do temporaries or not?
01785     if (doTempSymbols != GetBoolAttr(elem, XAIFStrings.attr_temp_x(), false /* default */)) { 
01786       return;
01787     }
01788     // 1. Initialize
01789     SYMTAB_IDX level = (pu) ? CURRENT_SYMTAB : GLOBAL_SYMTAB;
01790   
01791     // For symbols not introduced by xaifBooster, *one* of the following applies
01792     fortTkSupport::SymId symId = GetSymId(elem); // non-zero for a normal symbol
01793     fortTkSupport::WNId wnId = GetWNId(elem);    // non-zero for a scalarized symbol
01794   
01795     bool normalSym = (wnId == 0); // true if a non-scalarized symbol
01796     bool active = GetActiveAttr(elem);
01797   
01798     const XMLCh* symNmX = elem->getAttribute(XAIFStrings.attr_symId_x());
01799     XercesStrX symNm = XercesStrX(symNmX);
01800   
01801     // 2. Find or Create WHIRL symbol; change type if necessary
01802     ST* st = NULL;
01803     if (normalSym) {
01804       if (symId == 0) {
01805         // Create the symbol
01806         st = CreateST(elem, 
01807                       level, 
01808                       symNm.c_str(), 
01809                       ctxt.getXAIFSymToSymbolMap(),
01810                       scopeId);
01811         FORTTK_ASSERT(st != 0,
01812                       "CreateST returned a null pointer!");
01813       } 
01814       else {
01815         // Find the symbol and change type if necessary.  N.B. we skip
01816         // variables of structured type because they will be handled
01817         // through the scalarized references.
01818         st = &(Scope_tab[level].st_tab->Entry(symId));
01819         if (active && ST_class(st) == CLASS_VAR
01820             && (TY_kind(ST_type(st)) != KIND_STRUCT)) {
01821           ConvertToActiveType(st);
01822         }
01823       }
01824     } 
01825     else {
01826       // scalarized symbol
01827       FORTTK_ASSERT(level == CURRENT_SYMTAB,
01828                     "Scalarized symbols must be in a PU-scoped symbol table!");
01829       if (active) {
01830         WN* pathVorlage = ctxt.findWN(wnId, true /* mustFind */);
01831         ConvertScalarizedRefToActiveType(pathVorlage);
01832       }
01833     }
01834   
01835     // 3. Create our own symbol structure and add to the map
01836     fortTkSupport::Symbol* sym = new fortTkSupport::Symbol(st, wnId, active);
01837     ctxt.getXAIFSymToSymbolMap().Insert(scopeId, symNm.c_str(), sym);
01838   } 
01839 
01840 
01841   // ****************************************************************************
01842   // Attribute retrieval and 'annotation' attribute functions
01843   // ****************************************************************************
01844 
01845   bool
01846   GetBoolAttr(const xercesc::DOMElement* elem, XMLCh* attr, bool default_val)
01847   {
01848     const XMLCh* aX = elem->getAttribute(attr);
01849     XercesStrX a = XercesStrX(aX);
01850   
01851     // boolean values can be true/false or 1/0
01852     bool a_bool = default_val;
01853     if (strlen(a.c_str()) > 0) { // if attribute exists
01854       if (a.c_str()[0] == '0' || (strcmp(a.c_str(), "false") == 0)) {
01855         a_bool = false;
01856       } else {
01857         a_bool = true;
01858       }
01859     }
01860     return a_bool;
01861   }
01862 
01863 
01864   int
01865   GetIntAttr(const xercesc::DOMElement* elem, XMLCh* attr, int default_val)
01866   {
01867     const XMLCh* aX = elem->getAttribute(attr);
01868     XercesStrX a = XercesStrX(aX);
01869 
01870     int a_int = default_val;
01871     if (strlen(a.c_str()) > 0) { // if attribute exists
01872       a_int = strtol(a.c_str(), (char **)NULL, 10);
01873     }
01874     return a_int;
01875   }
01876 
01877 
01878   bool
01879   GetHasConditionAttr(const xercesc::DOMElement* elem)
01880   {
01881     return GetBoolAttr(elem, XAIFStrings.attr_hasCondval_x(), false /*default*/);
01882   }
01883 
01884 
01885   unsigned int
01886   GetCondAttr(const xercesc::DOMElement* elem)
01887   {
01888     unsigned int val = 0;
01889     if (GetHasConditionAttr(elem)) {
01890       val = GetIntAttr(elem, XAIFStrings.attr_condval_x(), 0 /* default */);
01891     }
01892     return val;
01893   }
01894 
01895 
01896   bool
01897   GetActiveAttr(const xercesc::DOMElement* elem)
01898   {
01899     return GetBoolAttr(elem, XAIFStrings.attr_active_x(), true /* default */);
01900   }
01901 
01902 
01903   bool
01904   GetDerivAttr(const xercesc::DOMElement* elem)
01905   {
01906     return GetBoolAttr(elem, XAIFStrings.attr_deriv_x(), false /* default */);
01907   }
01908 
01909 
01910   unsigned int
01911   GetPositionAttr(const xercesc::DOMElement* elem)
01912   {
01913     return GetIntAttr(elem, XAIFStrings.attr_position_x(), 0 /* default */);
01914   }
01915 
01916 
01917   bool
01918   IsTagPresent(const xercesc::DOMElement* elem, const char* tag)
01919   {
01920     const XMLCh* annot = (elem) ? elem->getAttribute(XAIFStrings.attr_annot_x())
01921       : NULL;
01922     XercesStrX annotStr = XercesStrX(annot);
01923     return IsTagPresent(annotStr.c_str(), tag);
01924   }
01925 
01926 
01927   bool
01928   IsTagPresent(const char* annotstr, const char* tag)
01929   {
01930     return (strstr(annotstr, tag) != NULL);
01931   }
01932 
01933 
01934   fortTkSupport::SymTabId GetSymTabId(const xercesc::DOMElement* elem) {
01935     return GetId<fortTkSupport::SymTabId>(elem, XAIFStrings.tag_SymTabId());
01936   }
01937 
01938 
01939   fortTkSupport::SymId GetSymId(const xercesc::DOMElement* elem) {
01940     return GetId<fortTkSupport::SymId>(elem, XAIFStrings.tag_SymId());
01941   }
01942 
01943 
01944   fortTkSupport::PUId GetPUId(const xercesc::DOMElement* elem) {
01945     return GetId<fortTkSupport::PUId>(elem, XAIFStrings.tag_PUId());
01946   }
01947 
01948 
01949   fortTkSupport::WNId GetWNId(const xercesc::DOMElement* elem) {
01950     return GetId<fortTkSupport::WNId>(elem, XAIFStrings.tag_WHIRLId());
01951   }
01952 
01953 
01954   fortTkSupport::IdList<fortTkSupport::WNId>*
01955   GetWNIdList(const xercesc::DOMElement* elem)
01956   {
01957     return GetIdList<fortTkSupport::WNId>(elem, XAIFStrings.tag_WHIRLId());
01958   }
01959 
01960 
01961   std::string
01962   GetIntrinsicKey(const xercesc::DOMElement* elem)
01963   {
01964     const XMLCh* annot = (elem) ? elem->getAttribute(XAIFStrings.attr_annot_x()) : NULL;
01965     XercesStrX annotStr_x = XercesStrX(annot);
01966     const char* annotStr = annotStr_x.c_str();
01967     std::string key;
01968     char *start = NULL, *end = NULL;
01969     start = strstr(const_cast<char*>(annotStr), XAIFStrings.tag_IntrinsicKey());
01970     if (start) {
01971       start = start + strlen(XAIFStrings.tag_IntrinsicKey());
01972       end = strstr(start, XAIFStrings.tag_End());
01973     }
01974     if (start && end) {
01975       for (char* p = start; p < end; ++p) { key += *p; }
01976     }
01977       return key;
01978   }
01979 
01980 
01981   PREG_IDX
01982   GetPregId(const xercesc::DOMElement* elem)
01983   {
01984     return GetId<PREG_IDX>(elem, XAIFStrings.tag_PregId());
01985   }
01986 
01987 
01988   // GetId, GetIdList: <see header>
01989   template <class T>
01990   T
01991   GetId(const xercesc::DOMElement* elem, const char* tag)
01992   {
01993     const XMLCh* annot = (elem) ? elem->getAttribute(XAIFStrings.attr_annot_x())
01994       : NULL;
01995     XercesStrX annotStr = XercesStrX(annot);
01996     T id = GetId<T>(annotStr.c_str(), tag);
01997     return id;
01998   }
01999 
02000 
02001   template <class T>
02002   fortTkSupport::IdList<T>*
02003   GetIdList(const xercesc::DOMElement* elem, const char* tag)
02004   {
02005     const XMLCh* annot = (elem) ? elem->getAttribute(XAIFStrings.attr_annot_x())
02006       : NULL;
02007     XercesStrX annotStr = XercesStrX(annot);
02008     fortTkSupport::IdList<T>* idlist = GetIdList<T>(annotStr.c_str(), tag);
02009     return idlist;
02010   }
02011 
02012 
02013   // GetId, GetIdList: <see header>
02014   template <class T>
02015   T
02016   GetId(const char* idstr, const char* tag)
02017   {
02018     T id = 0;
02019     if (!idstr) { return id; }
02020 
02021     // Find the tag indicating presence of id
02022     const char* start = strstr(idstr, tag);
02023     if (!start) { return id; }
02024     start += strlen(tag); // move pointer past tag
02025   
02026     char* endptr = NULL;
02027     id = strtol(start, &endptr, 10);
02028 
02029     unsigned int len = strlen(XAIFStrings.tag_End());
02030     FORTTK_ASSERT(endptr && strncmp(endptr, XAIFStrings.tag_End(), len) == 0,
02031                   "Could not find '" << tag << "' within " << idstr);
02032     return id;
02033   }
02034 
02035 
02036   template <class T>
02037   fortTkSupport::IdList<T>*
02038   GetIdList(const char* idstr, const char* tag)
02039   {
02040     fortTkSupport::IdList<T>* idlist = new fortTkSupport::IdList<T>;
02041 
02042     if (!idstr) { return idlist; }
02043   
02044     // Find the tag indicating presence of list
02045     const char* start = strstr(idstr, tag);
02046     if (!start) { return idlist; }
02047     start += strlen(tag); // move pointer past tag
02048   
02049     // Parse the colon separated id list.  The list is ended by
02050     // XAIFStrings.tag_End()
02051     char* tok = strtok(const_cast<char*>(start), ":");
02052     while (tok != NULL) {
02053     
02054       char* endptr = NULL;
02055       T id = strtol(tok, &endptr, 10);
02056       if (endptr != tok) { 
02057         FORTTK_ASSERT(id != 0, "Found invalid " << tag << " id " << id 
02058                       << " within " << idstr);
02059         idlist->push_back(id); // we found some digits to convert
02060       }
02061 
02062       tok = strtok((char*)NULL, ":");
02063       if (endptr && strcmp(endptr, XAIFStrings.tag_End()) == 0) {
02064         // we should be done with iteration now
02065         FORTTK_ASSERT(tok == NULL, "Could not find end of " << tag 
02066                       << " within " << idstr);
02067       }
02068     }
02069 
02070     return idlist;
02071   }
02072 
02073 
02074   // ****************************************************************************
02075   // WHIRL Creation functions
02076   // ****************************************************************************
02077 
02078   WN*
02079   CreateCallToIntrin(TYPE_ID rtype, const char* fname, unsigned int argc)
02080   {
02081     // cf. WN* cwh_intrin_build(...)
02082     // cf. WN* Gen_Call_Shell(...) in be/com/wn_instrument.cxx
02083   
02084     TY_IDX ty = Make_Function_Type(MTYPE_To_TY(rtype));
02085     ST* st = Gen_Intrinsic_Function(ty, fname); // create if non-existant
02086   
02087     WN* callWN = WN_Call(rtype, MTYPE_V, argc, st);
02088     WN_Set_Call_Default_Flags(callWN); // set conservative assumptions
02089   
02090     return callWN;
02091   }
02092 
02093 
02094   WN*
02095   CreateCallToIntrin(TYPE_ID rtype, const char* fname, std::vector<WN*>& args)
02096   {
02097     unsigned int numiArgs = 0; // implicit args if any
02098     for (unsigned int i = 0; i < args.size(); ++i) {
02099       if (args[i]) { 
02100         TY_IDX ty = WN_Tree_Type(args[i]);
02101         if (TY_Is_Character_Reference(ty) || TY_Is_Chararray_Reference(ty)) {
02102           numiArgs++;
02103         }
02104       }
02105     }
02106     WN* callWN = CreateCallToIntrin(rtype, fname, args.size()+numiArgs);
02107     for (unsigned int i = 0; i < args.size(); ++i) {
02108       if (args[i]) { 
02109         // conservatively assume pass by reference
02110         WN_actual(callWN, i) = CreateParm(args[i], WN_PARM_BY_REFERENCE);
02111         TY_IDX ty = WN_Tree_Type(args[i]);
02112         if (TY_Is_Character_Reference(ty) || TY_Is_Chararray_Reference(ty)) {
02113           numiArgs++;
02114         }
02115       }
02116     }
02117     if (WN_intrinsic(callWN)==INTRN_SCAN) { 
02118       for (unsigned i = args.size(); i < args.size()+numiArgs; ++i) {
02119         // Create bogus values, knowing that we only want to unparse the WHIRL
02120         WN_actual(callWN, i) = CreateParm(WN_CreateIntconst(OPC_I4INTCONST, 0),WN_PARM_BY_VALUE); // a white lie
02121       }
02122     }
02123     return callWN;
02124   }
02125 
02126 
02127   WN*
02128   CreateIntrinsicCall(OPERATOR opr, INTRINSIC intrn, 
02129                       TYPE_ID rtype, TYPE_ID dtype, std::vector<WN*>& args)
02130   {
02131     // Collect arguments into a temporary array for WN_Create_Intrinsic().
02132     WN** kids = new WN*[args.size()];
02133     for (unsigned int i = 0; i < args.size(); ++i) {
02134       kids[i] = args[i];
02135     }
02136   
02137     WN* wn = WN_Create_Intrinsic(opr, rtype, dtype, intrn, args.size(), kids);
02138   
02139     delete[] kids;
02140     return wn;
02141   }
02142 
02143 
02144   WN* 
02145   CreateBoolConst(unsigned int val)
02146   {
02147     // We use OPR_CONST instead of OPR_INTCONST so that we can set the
02148     // boolean flag for a TY.  Note, however, that an OPC_??CONST cannot
02149     // have the boolean rtype.
02150   
02151     // Use a boolean mtype for the new ST so that it is safe to set the
02152     // associated TY's 'is_logical' flag.
02153     TCON tcon = Host_To_Targ(MTYPE_B, val); // use boolean mtype here
02154     ST* st = New_Const_Sym(Enter_tcon(tcon), MTYPE_To_TY(TCON_ty(tcon)));
02155     Set_TY_is_logical(ST_type(st));
02156     WN* wn = WN_CreateConst(OPC_I4CONST, st);
02157     return wn;
02158   }
02159 
02160 
02161   static WN*
02162   CreateOpenADReplacementBeg(const char* placeholder)
02163   {
02164     std::string com = "$OpenAD$ BEGIN REPLACEMENT ";
02165     com += placeholder;
02166     WN* comWN = WN_CreateComment((char*)com.c_str());
02167     return comWN;
02168   }
02169 
02170 
02171   static WN*
02172   CreateOpenADReplacementEnd()
02173   {
02174     WN* comWN = WN_CreateComment((char*)"$OpenAD$ END REPLACEMENT");
02175     return comWN;
02176   }
02177 
02178 
02179   // CreateIfCondition: Convert an expression that is a var-reference to
02180   // a comparison.  E.g.
02181   //   if (OpenAD_Symbol_2303) --> if (OpenAD_Symbol_2303 .ne. 0)
02182   static WN* 
02183   CreateIfCondition(WN* condWN)
02184   {
02185     WN* newcondWN = condWN;
02186   
02187     TY_IDX ty = WN_Tree_Type(condWN);
02188     if (OPERATOR_is_load(WN_operator(condWN)) && !TY_is_logical(ty)) {
02189       WN* zeroWN = WN_Zerocon(Boolean_type); // CreateBoolConst(0);
02190       newcondWN = WN_NE(Boolean_type, condWN, zeroWN);
02191     }
02192   
02193     return newcondWN;
02194   }
02195 
02196 
02197   // CreateST: Creates and returns a WHIRL ST* at level 'level' with
02198   // name 'nm' using 'elem' to gather ST shape and storage class info.
02199   static ST* 
02200   CreateST(const xercesc::DOMElement* elem, 
02201            SYMTAB_IDX level, 
02202            const char* nm,
02203            fortTkSupport::XAIFSymToSymbolMap& symMap,
02204            const char* scopeId)
02205   {
02206     const XMLCh* kindX = elem->getAttribute(XAIFStrings.attr_kind_x());
02207     const XMLCh* typeX = elem->getAttribute(XAIFStrings.attr_type_x());
02208     const XMLCh* fetypeX = elem->getAttribute(XAIFStrings.attr_feType_x());
02209     const XMLCh* shapeX = elem->getAttribute(XAIFStrings.attr_shape_x());    
02210 
02211     XercesStrX kind = XercesStrX(kindX);
02212     XercesStrX type = XercesStrX(typeX);
02213     XercesStrX fetype = XercesStrX(fetypeX);
02214     XercesStrX shape = XercesStrX(shapeX);
02215   
02216     bool active = GetActiveAttr(elem);
02217 
02218     bool hasToBeAllocatable=false; // set to true for temp arrays without dimension bounds
02219   
02220     // FIXME: assume only
02221     FORTTK_ASSERT(strcmp(kind.c_str(), "variable") == 0 
02222                   || 
02223                   strcmp(kind.c_str(), "subroutine") == 0,
02224                   fortTkSupport::Diagnostics::Unimplemented << "Can create only symbols that are temporary variables or subroutine names derived from a given subroutine that has the specified prefix prepended");
02225     TY_IDX ty;
02226 
02227     ST_CLASS symbolClass;
02228 
02229     if (strcmp(kind.c_str(), "variable") == 0) { 
02230       symbolClass=CLASS_VAR;
02231       // 1. Find basic type according to 'type' and 'active'
02232       TY_IDX basicTy = XAIFTyToWHIRLTy(type.c_str(),
02233                                        XAIFFETypeToWHIRLMTy(fetype.c_str()));
02234       if (active) {
02235         basicTy = ActiveTypeTyIdx;
02236       } 
02237   
02238       // 2. Modify basic type according to the (non-scalar) shapes
02239       TY_IDX ty;
02240       if (strcmp(shape.c_str(), "scalar") == 0) {
02241         ty = basicTy;
02242       } 
02243       else {
02244         // Note: cf. be/com/wn_instrument.cxx:1253 for example creating vector
02245         INT32 ndim = 0;
02246         if (strcmp(shape.c_str(), "vector") == 0) {
02247           ndim = 1;
02248         } 
02249         else if (strcmp(shape.c_str(), "matrix") == 0) {
02250           ndim = 2;
02251         } 
02252         else if (strcmp(shape.c_str(), "three_tensor") == 0) {
02253           ndim = 3;
02254         } 
02255         else if (strcmp(shape.c_str(), "four_tensor") == 0) {
02256           ndim = 4;
02257         } 
02258         else if (strcmp(shape.c_str(), "five_tensor") == 0) {
02259           ndim = 5;
02260         } 
02261         else if (strcmp(shape.c_str(), "six_tensor") == 0) {
02262           ndim = 6;
02263         } 
02264         else {
02265           // FIXME: add other tensors
02266           FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "Cannot translate variables of shape " << shape.c_str() );
02267         }
02268     
02269         INT64 *lower, *upper;
02270         lower = new INT64[ndim];
02271         upper = new INT64[ndim];
02272 
02273         INT32 ndimIndex = 0;
02274         XAIF_DimensionBoundsElemFilter dbFilt;
02275         for (xercesc::DOMElement* dbElem = GetChildElement(elem, &dbFilt);
02276              (dbElem); 
02277              ++ndimIndex,
02278                dbElem = GetNextSiblingElement(dbElem, &dbFilt)) {
02279           if (ndimIndex==ndim) { 
02280             FORTTK_DIE("Cannot have more DimensionBounds than data type allows");
02281           }
02282           const XMLCh* lowerX = dbElem->getAttribute(XAIFStrings.attr_lower_x());
02283           XercesStrX lowerS = XercesStrX(lowerX);
02284           lower[ndimIndex]=strtol(lowerS.c_str(), (char **)NULL, 10);
02285           const XMLCh* upperX = dbElem->getAttribute(XAIFStrings.attr_upper_x());
02286           XercesStrX upperS = XercesStrX(upperX);
02287           upper[ndimIndex]=strtol(upperS.c_str(), (char **)NULL, 10);
02288         }
02289     
02290         if (ndimIndex>0 && ndimIndex!=ndim) { 
02291           FORTTK_DIE("Variable " << nm << " needs to have all or no DimensionBounds specified (have only " << ndimIndex << " for " << shape.c_str() << ")" );
02292         }
02293     
02294         bool haveDimensionBounds = false;
02295         if (ndimIndex) {
02296           haveDimensionBounds = true;
02297         }
02298         else {
02299           // if we don't know the dimension somebody has to allocate this 
02300           // since assumed shape arrays can otherwise only be formal parameters
02301           hasToBeAllocatable = true; 
02302         }
02303         ty = MY_Make_Array_Type(basicTy, ndim, haveDimensionBounds,lower,upper);
02304 
02305         delete[] lower;
02306         delete[] upper;
02307       }
02308       // 3. Find storage class and export scope 
02309       ST_SCLASS sclass = SCLASS_AUTO; // default: auto implies local storage
02310       ST_EXPORT escope = EXPORT_LOCAL_INTERNAL;
02311       if (level == GLOBAL_SYMTAB) {
02312         sclass = SCLASS_COMMON;
02313         escope = EXPORT_LOCAL;
02314       }
02315     
02316       // 4. Create the new symbol
02317       ST* st = New_ST(level);
02318       ST_Init(st, Save_Str(nm), symbolClass, sclass, escope, ty);
02319       if (hasToBeAllocatable)
02320         Set_ST_is_allocatable(*st);
02321     
02322       // 5. For global symbols, modify and add to a global/common block
02323       if (level == GLOBAL_SYMTAB) {
02324         //FIXME ConvertIntoGlobalST(st);
02325       }
02326       return st;
02327     }
02328     if (strcmp(kind.c_str(), "subroutine") == 0) { 
02329       // the prefix must be in front of the original name
02330       // remove the prefix 
02331       std::string newXAIFName(nm);
02332       if (newXAIFName.find(PUXlationContext::getPrefix())!=0) {
02333         FORTTK_DIE("Cannot only copy existing subroutine calls: "
02334                    << nm 
02335                    << " does not begin with the required prefix "
02336                    << PUXlationContext::getPrefix().c_str());
02337       }
02338       std::string origXAIFName(newXAIFName.substr(PUXlationContext::getPrefix().size()));
02339       fortTkSupport::Symbol* origNameSymbol_p = symMap.Find(scopeId, origXAIFName.c_str());
02340       if (!origNameSymbol_p) {
02341         FORTTK_DIE("Cannot find "
02342                    << origXAIFName.c_str()
02343                    << " in the temporary symbol map");
02344       }
02345       // the XAIFName has some _index number appended that we need to loose
02346       ST* origNameST_p = origNameSymbol_p->GetST();
02347       if (!origNameST_p) {
02348         FORTTK_DIE("Cannot find whirl symbol table entry. Can only copy existing subroutine names: "
02349                    << origXAIFName.c_str()
02350                    << " does not exist in the internal symbol table");
02351       }
02352       std::string origName(ST_name(*origNameST_p));
02353       ST* newNameST_p=Copy_ST(origNameST_p); // make a copy in the same scope
02354       // reset the name to the newName
02355       Set_ST_name_idx (*newNameST_p,Save_Str((PUXlationContext::getPrefix()+origName).c_str()));
02356       return newNameST_p;
02357     }
02358   }
02359 
02360 
02361   static ST* 
02362   ConvertIntoGlobalST(ST* st)
02363   {
02364     static ST* OpenADCommonBlockST = NULL;
02365     static TY_IDX OpenADCommonBlockTY = 0;
02366     static UINT64 OpenADCommonBlockOffset = 0;
02367     static FLD_HANDLE OpenADCommonBlockLastField = FLD_HANDLE();
02368   
02369     // Create common block ST if necessary
02370     bool isFirst = false;
02371     if (!OpenADCommonBlockST) {
02372       // cf. cwh_stab_common_ST()
02373       isFirst = true;
02374 
02375       INT64 sz = 0;
02376       TY& ty = New_TY(OpenADCommonBlockTY); // sets 'OpenADCommonBlockTY'
02377       TY_Init(ty, sz, KIND_STRUCT, MTYPE_M, Save_Str(".openad.common."));
02378       // Note: Common block fields are created below
02379     
02380       OpenADCommonBlockST = New_ST(GLOBAL_SYMTAB);
02381       ST_Init(OpenADCommonBlockST, Save_Str("OpenADGlobals"), CLASS_VAR, 
02382               SCLASS_COMMON, EXPORT_LOCAL, OpenADCommonBlockTY);
02383     
02384       //Set_ST_base(ST& s, *OpenADCommonBlock); // base symbol at the procedure?
02385       //Set_ST_ofst(ST& s, UINT64 offset);
02386     }
02387   
02388     // Create a new field for common block type
02389     FLD_HANDLE fld = New_FLD();
02390     TY_IDX fldTy = ST_type(st);
02391     FLD_Init(fld, Save_Str(ST_name(st)), fldTy, OpenADCommonBlockOffset);
02392     if (isFirst) {
02393       Set_TY_fld(OpenADCommonBlockTY, fld);
02394     } else {
02395       Clear_FLD_last_field(OpenADCommonBlockLastField); // fld is now the last
02396     }
02397     Set_FLD_last_field(fld);
02398     OpenADCommonBlockLastField = fld;
02399   
02400     // Increase size of common block
02401     UINT64 sz = TY_size(ST_type(st));
02402     OpenADCommonBlockOffset += sz;
02403     Set_TY_size(OpenADCommonBlockTY, sz);
02404   
02405     // Modify/Add 'st' to common block
02406     Set_ST_base(*st, *OpenADCommonBlockST);
02407     Set_ST_ofst(*st, OpenADCommonBlockOffset);
02408   
02409     return st;
02410   }
02411 
02412 
02413   void 
02414   DeclareActiveTypes()
02415   {
02416     // We create pseudo active types aliased to F8
02417     static char 
02418       activeTypeName[Args::ourActiveTypeNmLength], 
02419       activeInitializedTypeName[Args::ourActiveTypeNmLength+5];
02420     std::string activeInitializedTypeNameStr=Args::ourActiveTypeNm+std::string("_init");
02421     strncpy(activeTypeName,
02422             Args::ourActiveTypeNm.c_str(),
02423             Args::ourActiveTypeNmLength);
02424     strncpy(activeInitializedTypeName,
02425             activeInitializedTypeNameStr.c_str(),
02426             Args::ourActiveTypeNmLength+4);
02427     static const char* psTypeNames[] = 
02428       { activeTypeName, activeInitializedTypeName};
02429     static unsigned psTypeNamesSZ = sizeof(psTypeNames) / sizeof(char*);
02430   
02431     static TY_IDX* psTyIdx[] = 
02432       { &ActiveTypeTyIdx, &ActiveTypeInitializedTyIdx };
02433     static unsigned psTyIdxSZ = psTypeNamesSZ;
02434   
02435     for (unsigned i = 0; i < psTypeNamesSZ; ++i) {
02436       TY_IDX ty_idx;
02437       TY& ty = New_TY(ty_idx); // sets 'ty_idx'
02438       TY_Init(ty, 8, KIND_SCALAR, MTYPE_F8, Save_Str(psTypeNames[i]));
02439       Set_TY_align(ty_idx, 8);
02440       Set_TY_is_external(ty);
02441       *(psTyIdx[i]) = ty_idx;
02442     }
02443   }
02444 
02445   // ConvertToActiveType: Given a symbol, convert it to active type
02446   static void 
02447   ConvertToActiveType(ST* st) {
02448     static std::set<std::string> cbSymbolSet, eqSymbolSet;
02449     // Find the type that will be replaced
02450     TY_IDX typeIndex = ST_type(st);
02451     // -------------------------------------------------------
02452     // issue warnings
02453     // -------------------------------------------------------
02454     if ((TY_kind(typeIndex) == KIND_SCALAR 
02455          || 
02456          TY_kind(typeIndex) == KIND_ARRAY) 
02457         && Stab_Is_Valid_Base(st)) { 
02458       if (ST_is_equivalenced(st)) {
02459         if (eqSymbolSet.find(ST_name(st))==eqSymbolSet.end()) { 
02460           FORTTK_WMSG("EQUIVALENCE construct detected for " << ST_name(st) << " conflicts with default initialization within the active type (required for adjoint mode)");
02461           eqSymbolSet.insert(ST_name(st));
02462         }
02463       }
02464       if (Stab_Is_Equivalence_Block(ST_base(st))) {
02465         if (eqSymbolSet.find(ST_name(st))==eqSymbolSet.end()) { 
02466           FORTTK_WMSG("EQUIVALENCE construct detected for " << ST_name(st) << " conflicts with default initialization within the active type (required for adjoint mode)");
02467           eqSymbolSet.insert(ST_name(st));
02468         }
02469       }
02470       if (Stab_Is_Common_Block(ST_base(st))) {
02471         if (cbSymbolSet.find(ST_name(st))==cbSymbolSet.end()) { 
02472           FORTTK_WMSG("COMMON construct detected for " << ST_name(st) << " conflicts with default initialization within the active type (required for adjoint mode)");
02473           cbSymbolSet.insert(ST_name(st));
02474         }
02475       }
02476     }
02477     // -------------------------------------------------------
02478     // 1. Setup
02479     // -------------------------------------------------------
02480     if (TY_kind(typeIndex) == KIND_POINTER) { // only have one level of indirection
02481       typeIndex = TY_pointed(typeIndex);
02482     }
02483 
02484     // Get the replacement type
02485     TY_IDX newBaseTypeIndex = ActiveTypeTyIdx;
02486     if (ST_is_initialized(st)) {
02487       INITO_IDX inito = Find_INITO_For_Symbol(st);
02488       if (inito != (INITO_IDX)0) {
02489         newBaseTypeIndex = ActiveTypeInitializedTyIdx;
02490       }
02491     }
02492 
02493     // -------------------------------------------------------
02494     // 2. Change the type of this symbol
02495     // -------------------------------------------------------
02496     if (TY_kind(typeIndex) == KIND_SCALAR) {
02497       Set_ST_type(*st, newBaseTypeIndex);
02498       if (Stab_Is_Valid_Base(st)
02499           && 
02500           (Stab_Is_Equivalence_Block(ST_base(st))
02501            ||
02502            ST_is_equivalenced(st)
02503            ||
02504            Stab_Is_Common_Block(ST_base(st)))) { 
02505         TY_IDX baseTypeIndex = ST_type(ST_base(st));
02506         mUINT64 offset = ST_ofst(st); // offset into base symbol
02507         // find field with correct offset or symbol
02508         FLD_HANDLE fld = TY_Lookup_FLD(baseTypeIndex, 0, offset);
02509         Set_FLD_type(fld, newBaseTypeIndex);
02510         if (ST_is_equivalenced(st)) {
02511           // retrieve fields with the same offset
02512           unsigned short eqInst=2;
02513           FLD_HANDLE fld = TY_Lookup_FLD(baseTypeIndex, 0, offset,eqInst);
02514           while (!fld.Is_Null()) { 
02515             Set_FLD_type(fld, newBaseTypeIndex);
02516             fld = TY_Lookup_FLD(baseTypeIndex, 0, offset,++eqInst);
02517           }
02518         }
02519       }
02520     }
02521     else if (TY_kind(typeIndex) == KIND_ARRAY) {
02522       // get the element type index 
02523       TY_IDX elementTypeIndex = TY_etype(typeIndex);
02524       if (TY_kind(elementTypeIndex) == KIND_SCALAR) { 
02525         // we do this only for scalars because structures 
02526         // are supposed to activated element by element in the 
02527         // structure definition and arrays are supposed to be flat 
02528         // (i.e. no nesting arrays in arrays without a structure definition)
02529         // Note: because types may be shared, we cannot simply change the
02530         // element type.  For now we create a new type for each active
02531         // symbol.
02532         TY_IDX newArrayTypeIndex = Copy_TY(typeIndex); 
02533         Set_TY_etype(newArrayTypeIndex, newBaseTypeIndex); // alignment, etc. should be ok
02534       
02535         // Now find the appropriate type for the symbol
02536         TY_IDX newArraySymbolTypeIndex = newArrayTypeIndex;
02537         if (TY_kind(ST_type(st)) == KIND_POINTER) {
02538           newArraySymbolTypeIndex = Make_Pointer_Type(newArrayTypeIndex);
02539         }
02540         Set_ST_type(st,newArraySymbolTypeIndex);
02541         if (Stab_Is_Valid_Base(st)
02542             && 
02543             (Stab_Is_Equivalence_Block(ST_base(st))
02544              ||
02545              ST_is_equivalenced(st)
02546              ||
02547              Stab_Is_Common_Block(ST_base(st)))) { 
02548           TY_IDX baseTypeIndex = ST_type(ST_base(st));
02549           mUINT64 offset = ST_ofst(st); // offset into base symbol
02550           // find field with correct offset or symbol
02551           FLD_HANDLE fld = TY_Lookup_FLD(baseTypeIndex, 0, offset);
02552           Set_FLD_type(fld, newArraySymbolTypeIndex);
02553           if (ST_is_equivalenced(st)) {
02554             // retrieve fields with the same offset
02555             unsigned short eqInst=2;
02556             FLD_HANDLE fld = TY_Lookup_FLD(baseTypeIndex, 0, offset,eqInst);
02557             while (!fld.Is_Null()) { 
02558               Set_FLD_type(fld, newArraySymbolTypeIndex);
02559               fld = TY_Lookup_FLD(baseTypeIndex, 0, offset,++eqInst);
02560             }
02561           }
02562         }
02563       }
02564     } 
02565     else {
02566       // Note: We should never see a KIND_STRUCT; this is handled
02567       // through scalarization.
02568       FORTTK_DIE("Unexpected type kind: " << TY_kind(typeIndex));
02569     }
02570   }
02571 
02572   // ConvertStructMemberTouActiveType: Given a base structure type, a
02573   // referenced object type and the offset of the referenced object,
02574   // change the type of the referenced field.
02575   static void 
02576   ConvertStructMemberToActiveType(TY_IDX base_ty, TY_IDX ref_ty, 
02577                                   UINT field_id)
02578   {
02579     UINT cur_field_id=0;
02580     FLD_HANDLE fld = FLD_get_to_field (base_ty, field_id, cur_field_id);
02581     FORTTK_ASSERT(fld.Entry(), "Could not find field in " << TY_name(base_ty));
02582     TY_IDX fldTy=fld.Entry()->type;
02583     if (TY_kind(fldTy) == KIND_POINTER) {
02584       // replicate the pointer type but let it point to the active type
02585       TY_IDX fieldPointed = TY_pointed(fldTy);
02586       if (TY_kind(fieldPointed) == KIND_ARRAY) {
02587         TY_IDX newArrayTypeIndex = Copy_TY(fieldPointed); 
02588         Set_TY_etype(newArrayTypeIndex, ActiveTypeTyIdx);
02589         TY_IDX newArraySymbolTypeIndex = Make_Pointer_Type(newArrayTypeIndex);
02590         Set_FLD_type(fld, newArraySymbolTypeIndex);
02591       }
02592       else {
02593         TY_IDX newFldType=Copy_TY(fldTy);
02594         Set_TY_pointed(newFldType, ActiveTypeTyIdx);
02595         Set_FLD_type(fld, newFldType);
02596       }
02597     } 
02598     else if (TY_kind(fldTy) == KIND_ARRAY) {
02599       // replicate the pointer type but let it point to the active type 
02600       //      TY_IDX typeIndex=TY_pointed(fldTy);
02601       TY_IDX newArrayTypeIndex = Copy_TY(fldTy); 
02602       Set_TY_etype(newArrayTypeIndex, ActiveTypeTyIdx);
02603       TY_IDX newArraySymbolTypeIndex = Make_Pointer_Type(newArrayTypeIndex);
02604       Set_FLD_type(fld, newArraySymbolTypeIndex);
02605     } 
02606     else { 
02607       Set_FLD_type(fld, ActiveTypeTyIdx);
02608     }
02609   }
02610 
02611 
02612   // ConvertScalarizedRefToActiveType: Change type of the last component
02613   // of the scalarized path.  That is, for "a%b%c%d", change the type of
02614   // 'd'.  (This means we can safely ignore internal path components.)
02615   // 
02616   // Note that types from modules will be duplicated in the type table
02617   // for each 'use', with the duplicates receiving a 'TY_IS_EXTERNAL'
02618   // flag.  Because the duplicates are igored by whirl2f, the the
02619   // non-external version of the type needs to be changed so that the
02620   // module definition is changed.
02621   static void 
02622   ConvertScalarizedRefToActiveType(WN* wn)
02623   {
02624     TY_IDX baseobj_ty = WN_GetBaseObjType(wn);
02625     TY_IDX refobj_ty  = WN_GetRefObjType(wn);
02626     if (TY_Is_Array(baseobj_ty)) {
02627       // array reference, such as "s%b(i)"
02628       // must change type of ref-obj.
02629       // Note that we assume the WHIRL includes offsets instead of field ids
02630       WN* kid0;
02631       if (WN_operator(wn)==OPR_ISTORE) {
02632         wn=WN_kid1(wn);
02633       }
02634       // descend until the OPR_STRCTFLD
02635       while (WN_operator(wn)!=OPR_STRCTFLD && (NULL!=(kid0=WN_kid0(wn)))) { 
02636         wn=kid0;
02637       }
02638       // in case we descended
02639       baseobj_ty = WN_GetBaseObjType(wn);
02640       FORTTK_ASSERT(OPERATOR_has_field_id(WN_operator(wn)), "Uh-oh!");
02641       UINT field_id = WN_field_id(wn);
02642       ConvertStructMemberToActiveType(baseobj_ty, refobj_ty, field_id);
02643       if (TY_is_external(baseobj_ty)) {
02644         For_all_until(Ty_Table,
02645                       ConvertModuleTypeFctr(baseobj_ty, refobj_ty, field_id));
02646       }
02647     }
02648     else {
02649       // structure member reference, such as "s%a" or "b(i)%a"
02650       // must change type of ref-obj.
02651       FORTTK_ASSERT(OPERATOR_has_field_id(WN_operator(wn)), "Uh-oh!");
02652       UINT field_id = WN_field_id(wn);
02653       ConvertStructMemberToActiveType(baseobj_ty, refobj_ty, field_id);
02654       if (TY_is_external(baseobj_ty)) {
02655         For_all_until(Ty_Table,
02656                       ConvertModuleTypeFctr(baseobj_ty, refobj_ty, field_id));
02657       }
02658     }
02659   }
02660 
02661 
02662   // TY_Lookup_FLD: Given a base structure type, a referenced object type
02663   // and the offset of the referenced object, return the field entry.
02664   // The referenced object type may be 0.
02665   //
02666   // This is not an overly efficient method, but WHIRL doesn't make this
02667   // query easy.
02668   //
02669   // cf. FLD_get_to_field
02670   static FLD_HANDLE 
02671   TY_Lookup_FLD(TY_IDX struct_ty, TY_IDX ref_ty, UINT64 ref_ofst,unsigned short eqInst)
02672   {
02673     FLD_ITER fld_iter = Make_fld_iter(TY_fld(struct_ty));
02674     unsigned short foundInst=0;
02675     do {
02676       FLD_HANDLE fld(fld_iter);
02677       UINT64 ofst = FLD_ofst(fld);
02678       TY_IDX ty   = FLD_type(fld);
02679       if (ofst == ref_ofst) {
02680         ++foundInst;
02681         if (ref_ty == 0) {
02682           if (eqInst==foundInst)
02683             return fld;
02684         }
02685         else {
02686           if (Stab_Identical_Types(ref_ty, ty, FALSE /* check_quals */,
02687                                    FALSE /* check_scalars */, TRUE)) {
02688             return fld;
02689           }
02690         }
02691       }
02692     } while (!FLD_last_field(fld_iter++));
02693   
02694     return FLD_HANDLE(); // null field
02695   }
02696 
02697   // FIXME: Available in symtab_utils.h / symtab.cxx
02698   static TY_IDX
02699   MY_Make_Array_Type (TY_IDX elem_ty, 
02700                       INT32 ndim, 
02701                       bool fixed,  
02702                       const INT64* lower, 
02703                       const INT64* upper) {
02704     INT64 elem_sz = TY_size (elem_ty);
02705     UINT elem_align = TY_align(elem_ty);
02706     FORTTK_ASSERT(elem_sz > 0 && elem_align > 0,
02707                   "Cannot make an array of " 
02708                   << TY_name(elem_ty));
02709     ARB_HANDLE arb_h,arb_h_first;
02710     INT64 ty_size=0; // for variable length arrays this should stay 0
02711     for (INT i = 0; i < ndim; ++i) {
02712       arb_h = New_ARB ();
02713       if (i==0) {
02714         arb_h_first = arb_h;
02715       }
02716       if (!fixed) { 
02717         ARB * arb = arb_h.Entry();
02718         arb->flags = ARB_EMPTY_LBND | ARB_EMPTY_UBND | ARB_EMPTY_STRIDE;
02719         arb->dimension = 1;
02720         arb->co_dimension = 0;
02721         arb->unused = 0;
02722         arb->u1.lbnd_val = 0;
02723         arb->u2.ubnd_val = 0;
02724         arb->u3.stride_val = 0;
02725       }
02726       else { 
02727         ARB_Init (arb_h, lower[i], upper[i], elem_sz);
02728         ty_size+=(upper[i]-lower[i])*elem_sz;
02729       }
02730       Set_ARB_dimension (arb_h, ndim-i);
02731     }
02732     Set_ARB_last_dimen (arb_h);
02733     Set_ARB_first_dimen (arb_h_first);
02734     TY_IDX ty_idx;
02735     TY& ty = New_TY (ty_idx);
02736     TY_Init (ty, ty_size, KIND_ARRAY, MTYPE_UNKNOWN, 0);
02737     Set_TY_align (ty_idx, elem_align);
02738     Set_TY_etype (ty, elem_ty);
02739     Set_TY_arb (ty, arb_h_first);
02740     return ty_idx;
02741   } // Make_Array_Type
02742 
02743   static TY_IDX
02744   XAIFTyToWHIRLTy(const char* type, const TYPE_ID mtype)
02745   {
02746     TY_IDX ty = 0;
02747     if (mtype!=MTYPE_UNKNOWN)
02748       ty = MTYPE_To_TY(mtype);
02749     else if (strcmp(type, "real") == 0) {
02750       ty = MTYPE_To_TY(Args::ourDefaultMTypeReal);
02751     } 
02752     else if (strcmp(type, "integer") == 0) {
02753       ty = MTYPE_To_TY(Args::ourDefaultMTypeInt);
02754     } 
02755     else {
02756       // FIXME: don't know about anything else yet
02757       FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "Unknown XAIF type: " << type);
02758     }
02759     return ty;
02760   }
02761 
02762   TYPE_ID
02763   XAIFFETypeToWHIRLMTy(const char* anFETypeName) {
02764     if (strcmp(anFETypeName,"")==0) { 
02765       return MTYPE_UNKNOWN;
02766     }
02767     return Name_To_Mtype(anFETypeName);
02768   }
02769 
02770   // ****************************************************************************
02771   // MyDGNode routines
02772   // ****************************************************************************
02773 
02774   OA::OA_ptr<MyDGNode>
02775   GetSuccessor(OA::OA_ptr<MyDGNode> node, bool succIsOutEdge)
02776   {
02777     using namespace OA::DGraph;
02778     
02779     int numSucc = (succIsOutEdge) ? node->num_outgoing() : node->num_incoming();
02780     if (numSucc == 0) {
02781       OA::OA_ptr<MyDGNode> retval;  retval = NULL;
02782       return retval;
02783     }
02784     else if (numSucc > 1) {
02785       xercesc::DOMElement* elem = node->GetElem();
02786       FORTTK_DIE("Cannot find unique successor to graph node; found " << numSucc
02787                  << ":\n" << *elem);
02788     }
02789   
02790     // We know there is one successor
02791     OA::OA_ptr<MyDGNode> succ; succ = NULL;
02792     if (succIsOutEdge) {
02793       OA::OA_ptr<NodesIteratorInterface> it;
02794       it = node->getSinkNodesIterator();
02795       OA::OA_ptr<NodeInterface> ntmp = it->current();
02796       succ = ntmp.convert<MyDGNode>();
02797     }
02798     else {
02799       OA::OA_ptr<NodesIteratorInterface> it;
02800       it = node->getSourceNodesIterator();
02801       OA::OA_ptr<NodeInterface> ntmp = it->current();
02802       succ = ntmp.convert<MyDGNode>();
02803     }
02804     return succ;
02805   }
02806 
02807 
02808   OA::OA_ptr<MyDGNode>
02809   GetSuccessorAlongEdge(OA::OA_ptr<MyDGNode> node, unsigned int condition, 
02810                         bool succIsOutEdge)
02811   {
02812     using namespace OA::DGraph;
02813 
02814     OA::OA_ptr<MyDGNode> succ; succ = NULL;
02815     int numSucc = (succIsOutEdge) ? node->num_outgoing() : node->num_incoming();
02816   
02817     if (succIsOutEdge) {
02818       OA::OA_ptr<EdgesIteratorInterface> it;
02819       it = node->getOutgoingEdgesIterator();
02820       for ( ; it->isValid(); ++(*it)) {
02821         OA::OA_ptr<EdgeInterface> etmp = it->current();
02822         OA::OA_ptr<MyDGEdge> edge = etmp.convert<MyDGEdge>();
02823         xercesc::DOMElement* e = edge->GetElem();
02824       
02825         unsigned int cond = GetCondAttr(e);
02826         if (condition == cond) {
02827           OA::OA_ptr<NodeInterface> ntmp = edge->getSink();
02828           succ = ntmp.convert<MyDGNode>();
02829           break;
02830         }
02831       }
02832     }
02833     else {
02834       FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "Transform into a template.");
02835     }
02836     return succ;
02837   }
02838 
02839 
02840   // CreateCFGraph: Given an XAIF control flow graph, create and
02841   // return a CFG where CFG nodes point to XAIF CVG vertices.
02842   static OA::OA_ptr<OA::DGraph::DGraphInterface> 
02843   CreateCFGraph(const xercesc::DOMElement* cfgElem)
02844   {
02845     using namespace OA::DGraph;
02846   
02847     MyDGNode::resetIds();
02848     OA::OA_ptr<OA::DGraph::DGraphImplement> g; 
02849     g = new DGraphImplement();
02850     VertexIdToMyDGNodeMap m;
02851   
02852     // -------------------------------------------------------
02853     // Create the graph
02854     // -------------------------------------------------------
02855     XAIF_BBElemFilter filt;
02856     for (xercesc::DOMElement* elem = GetChildElement(cfgElem, &filt);
02857          (elem); elem = GetNextSiblingElement(elem, &filt)) {
02858       if (XAIF_BBElemFilter::IsEdge(elem)) {
02859         // Add an edge to the graph. 
02860       
02861         // Find src and target (sink) nodes. 
02862         const XMLCh* srcX = elem->getAttribute(XAIFStrings.attr_source_x());
02863         const XMLCh* targX = elem->getAttribute(XAIFStrings.attr_target_x());
02864         XercesStrX src = XercesStrX(srcX);
02865         XercesStrX targ = XercesStrX(targX);
02866 
02867         OA::OA_ptr<MyDGNode> gn1; gn1 = m[std::string(src.c_str())];  // source
02868         OA::OA_ptr<MyDGNode> gn2; gn2 = m[std::string(targ.c_str())]; // target
02869         FORTTK_ASSERT(!gn1.ptrEqual(NULL) && !gn2.ptrEqual(NULL), 
02870                       "Invalid edge in CFG:\n" << *elem);
02871 
02872         OA::OA_ptr<MyDGEdge> ge; ge = new MyDGEdge(gn1, gn2, elem); // src, targ
02873         g->addEdge(ge);
02874       } 
02875       else {
02876         // Add a vertex to the graph
02877         const XMLCh* vidX = elem->getAttribute(XAIFStrings.attr_Vid_x());
02878         XercesStrX vid = XercesStrX(vidX);
02879         FORTTK_ASSERT(strlen(vid.c_str()) > 0, 
02880                       "Invalid vertex in CFG:\n" << *elem);
02881 
02882         OA::OA_ptr<MyDGNode> gn; gn = new MyDGNode(elem);
02883         g->addNode(gn);
02884         m[std::string(vid.c_str())] = gn;
02885       } 
02886     }
02887   
02888     return g;
02889   }
02890 
02891 
02892   // DumpDotGraph:
02893 
02894   static std::string
02895   DumpDotGraph_GetNodeName(OA::OA_ptr<MyDGNode> n);
02896 
02897   void
02898   DDumpDotGraph(OA::OA_ptr<OA::DGraph::DGraphInterface> graph)
02899   {
02900     DumpDotGraph(std::cerr, graph);
02901   }
02902 
02903   void
02904   DumpDotGraph(std::ostream& os, OA::OA_ptr<OA::DGraph::DGraphInterface> graph)
02905   {
02906     using namespace OA::DGraph;
02907     
02908     os << "digraph MyGraph {\n";
02909     os << "  graph [ ];\n"
02910        << "  node [ fontsize = \"10\" ];\n"
02911        << "  edge [ ];\n"
02912        << std::endl;
02913   
02914     OA::OA_ptr<EdgesIteratorInterface> edgesItPtr;
02915     edgesItPtr = graph->getEdgesIterator();
02916     for (; edgesItPtr->isValid(); ++(*edgesItPtr)) {
02917       OA::OA_ptr<OA::DGraph::EdgeInterface> e = edgesItPtr->current();
02918       OA::OA_ptr<OA::DGraph::NodeInterface> srctmp = e->getSource();
02919       OA::OA_ptr<OA::DGraph::NodeInterface> snktmp = e->getSink();
02920       OA::OA_ptr<MyDGNode> src = srctmp.convert<MyDGNode>();
02921       OA::OA_ptr<MyDGNode> snk = snktmp.convert<MyDGNode>();
02922       std::string srcNm = DumpDotGraph_GetNodeName(src);
02923       std::string snkNm = DumpDotGraph_GetNodeName(snk);
02924       os << "  \"" << srcNm.c_str() << "\" -> \"" << snkNm.c_str() << "\";\n";
02925     }
02926     os << "}" << std::endl;
02927   }
02928 
02929   static std::string
02930   DumpDotGraph_GetNodeName(OA::OA_ptr<MyDGNode> n) 
02931   {
02932     std::string name;
02933   
02934     // MyDGNode portion
02935     const char* nodeIdStr = Num2Str(n->getId(), "%u");
02936     name += nodeIdStr;
02937 
02938     // XAIF portion
02939     xercesc::DOMElement* elem = n->GetElem();
02940     const XMLCh* xaifNameX = elem->getNodeName();
02941     XercesStrX   xaifName = XercesStrX(xaifNameX);
02942     const XMLCh* vidX = elem->getAttribute(XAIFStrings.attr_Vid_x());
02943     XercesStrX   vid = XercesStrX(vidX);  
02944     name += ", (";
02945     name += vid.c_str();
02946     name += ", ";
02947     name += xaifName.c_str();
02948     name += ")";
02949   
02950     return name;
02951   }
02952 
02953 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines