OpenADFortTk (basic)
src/whirl2xaif/whirl2xaif.cxx
Go to the documentation of this file.
00001 // ##########################################################
00002 // # This file is part of OpenADFortTk.                     #
00003 // # The full COPYRIGHT notice can be found in the top      #
00004 // # level directory of the OpenADFortTk source tree.       #
00005 // # For more information visit                             #
00006 // # http://www.mcs.anl.gov/openad                          #
00007 // ##########################################################
00008 #include <ctime>
00009 #include <fstream>
00010 
00011 #include "Open64IRInterface/Open64BasicTypes.h"
00012 #include "Open64IRInterface/Open64IRInterface.hpp"
00013 #include "whirl2xaif.h"
00014 #include "wn2xaif.h"
00015 #include "st2xaif.h"
00016 #include "Args.h"
00017 
00018 namespace whirl2xaif { 
00019 
00020   fortTkSupport::IntrinsicXlationTable   
00021   Whirl2Xaif::ourIntrinsicTable(fortTkSupport::IntrinsicXlationTable::W2X);
00022 
00023   fortTkSupport::InterOAInfoMap       Whirl2Xaif::ourOAAnalMap;
00024   fortTkSupport::ScalarizedRefTabMap_W2X Whirl2Xaif::ourScalarizedRefTableMap;
00025   fortTkSupport::WNToWNIdTabMap          Whirl2Xaif::ourWNToWNIdTableMap;
00026   const std::string       Whirl2Xaif::ourDividerComment("********************************************************************");
00027 
00028   fortTkSupport::IntrinsicXlationTable& Whirl2Xaif::getIntrinsicXlationTable() { 
00029     return ourIntrinsicTable;
00030   }
00031 
00032   fortTkSupport::InterOAInfoMap& Whirl2Xaif::getOAAnalMap() { 
00033     return ourOAAnalMap;
00034   }
00035 
00036   fortTkSupport::ScalarizedRefTabMap_W2X& Whirl2Xaif::getScalarizedRefTableMap() { 
00037     return ourScalarizedRefTableMap;
00038   }
00039 
00040   fortTkSupport::WNToWNIdTabMap& Whirl2Xaif::getWNToWNIdTableMap() { 
00041     return ourWNToWNIdTableMap;
00042   }
00043 
00044   void Whirl2Xaif::translateIR(std::ostream& os, 
00045                                PU_Info* pu_forest,
00046                                const char* tmpVarPrefix) {
00047     using namespace OA::CallGraph;
00048     Diag_Set_Phase("WHIRL to XAIF: translate IR");
00049     if (!pu_forest) { return; }
00050     if (Args::ourDoNotFilterFlag) { 
00051       fortTkSupport::IntraOAInfo::setDoNotFilterFlag();
00052     }
00053     // -------------------------------------------------------
00054     // 1. Initialization (Much of this information must be collected
00055     // here because it is part of the CallGraph instead of a
00056     // ControlFlowGraph)
00057     // -------------------------------------------------------
00058     OA::OA_ptr<Open64IRInterface> irInterface; irInterface=new Open64IRInterface; 
00059     Open64IRInterface::initContextState(pu_forest);
00060     Open64IRInterface::setIgnoreBlackBoxRoutines();
00061     xml::ostream xos(os.rdbuf());
00062     PUXlationContext ctxt("whirl2xaif::translateIR",*irInterface);
00063     if (!Args::ourNoTimeStampFlag) 
00064         dumpTranslationHeaderComment(xos);
00065     // Initialize global id maps
00066     // NOTE: Do this first so that ids will match in back-translation
00067     fortTkSupport::SymTabToSymTabIdMap stabmap(pu_forest);
00068     ctxt.setSymTabToIdMap(&stabmap);
00069     fortTkSupport::PUToPUIdMap pumap(pu_forest);
00070     ctxt.setPUToIdMap(&pumap);
00071     ourWNToWNIdTableMap.Create(pu_forest); // Note: could make this local
00072     // Initialize and create inter/intra analysis information
00073     ourOAAnalMap.init(pu_forest,irInterface,Args::ourVariedOnlyFlag);
00074     ctxt.setActivity(ourOAAnalMap.getInterActiveFortran());
00075     ctxt.setAlias(ourOAAnalMap.getInterAlias());
00076     // Create scalarized var reference table
00077     ourScalarizedRefTableMap.Create(pu_forest);
00078     // -------------------------------------------------------
00079     // 2. Generate XAIF CallGraph
00080     // -------------------------------------------------------
00081     OA::OA_ptr<OA::CallGraph::CallGraph> cgraph = 
00082       ourOAAnalMap.getCallGraph();
00083     // CallGraph header info
00084     xos << xml::BegElem("xaif:CallGraph")
00085         << xml::Attr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
00086         << xml::Attr("xmlns:xaif", "http://www.mcs.anl.gov/XAIF")
00087         << xml::Attr("xsi:schemaLocation", "http://www.mcs.anl.gov/XAIF xaif.xsd")
00088         << xml::Attr("program_name", "***myprog***")
00089         << xml::Attr("prefix", tmpVarPrefix);
00090     // ScopeHierarchy
00091     ctxt.createXlationContext();
00092     translateScopeHierarchy(xos, pu_forest, ctxt);
00093     ctxt.deleteXlationContext();
00094     // Analysis Info Maps
00095     translateAnalMaps(xos, pu_forest, ctxt);
00096     // CallGraph vertices
00097     DGraphNodeVec* nodes = SortDGraphNodes(cgraph);
00098     for (DGraphNodeVec::iterator nodeIt = nodes->begin();
00099          nodeIt != nodes->end(); ++nodeIt) {
00100       ctxt.createXlationContext();
00101       OA::OA_ptr<OA::DGraph::NodeInterface> ntmp = *nodeIt;
00102       OA::OA_ptr<Node> n = 
00103         ntmp.convert<Node>();
00104       translatePU(xos, n, n->getId(), ctxt);
00105       ctxt.deleteXlationContext();
00106     }
00107     delete nodes;
00108     // CallGraph edges
00109     DGraphEdgeVec* edges = SortDGraphEdges(cgraph);
00110     for (DGraphEdgeVec::iterator edgeIt = edges->begin(); 
00111          edgeIt != edges->end(); ++edgeIt) {
00112       OA::OA_ptr<OA::DGraph::EdgeInterface> e = (*edgeIt);
00113       OA::OA_ptr<OA::DGraph::NodeInterface> n1 = e->getSource();
00114       OA::OA_ptr<OA::DGraph::NodeInterface> n2 = e->getSink();
00115       DumpCallGraphEdge(xos, ctxt.currentXlationContext().getNewEdgeId(), n1->getId(), n2->getId());
00116     }
00117     delete edges;
00118     // Done!
00119     xos << xml::EndElem; /* xaif:CallGraph */
00120   }
00121 
00122   void Whirl2Xaif::translateScopeHierarchy(xml::ostream& xos, 
00123                                            PU_Info* pu_forest, 
00124                                            PUXlationContext& ctxt) {
00125     // We implicitly create the ScopeHierarchy/ScopeGraph using
00126     // DFS-style iteration of PUs.  In addition to the global scope,
00127     // there is one scope for each PU.
00128     xos << xml::BegElem("xaif:ScopeHierarchy");
00129     // translate global symbol table
00130    fortTkSupport::SymTabId scopeId = ctxt.findSymTabId(Scope_tab[GLOBAL_SYMTAB].st_tab);
00131     xos << xml::BegElem("xaif:Scope") << xml::Attr("vertex_id", scopeId)
00132         << SymTabIdAnnot(scopeId) << xml::EndAttrs;
00133     xlate_SymbolTables(xos, GLOBAL_SYMTAB, NULL, ctxt);
00134     xos << xml::EndElem << std::endl;
00135     // translate each PU, descending into children first
00136     for (PU_Info *pu = pu_forest; pu != NULL; pu = PU_Info_next(pu)) {
00137       translateScopeHierarchyPU(xos, pu, scopeId, ctxt);
00138     }
00139     xos << xml::EndElem; /* xaif:ScopeHierarchy */
00140     xos << std::endl;
00141   }
00142 
00143   void Whirl2Xaif::translateScopeHierarchyPU(xml::ostream& xos, 
00144                                              PU_Info* pu, 
00145                                              UINT32 parentId, 
00146                                              PUXlationContext& ctxt) {
00147     PU_SetGlobalState(pu);
00148     // Need WHIRL<->ID maps for translating ScalarizedRefs
00149     fortTkSupport::WNToWNIdMap* wnmap = ourWNToWNIdTableMap.Find(pu);
00150     ctxt.setWNToIdMap(wnmap);
00151     fortTkSupport::ScalarizedRefTab_W2X* tab = ourScalarizedRefTableMap.Find(pu);
00152    fortTkSupport::SymTabId scopeId = ctxt.findSymTabId(Scope_tab[CURRENT_SYMTAB].st_tab);  
00153     // translate symbol tables 
00154     xos << xml::BegElem("xaif:Scope") << xml::Attr("vertex_id", scopeId) 
00155         << SymTabIdAnnot(scopeId) << xml::EndAttrs;
00156     xlate_SymbolTables(xos, CURRENT_SYMTAB, tab, ctxt);
00157     xos << xml::EndElem << std::endl;
00158     // Generate an edge to parent
00159     DumpScopeGraphEdge(xos, ctxt.currentXlationContext().getNewEdgeId(), scopeId, parentId);
00160     xos << std::endl;
00161     // Recursively translate all children
00162     for (PU_Info *child = PU_Info_child(pu); child != NULL;
00163          child = PU_Info_next(child)) {
00164       translateScopeHierarchyPU(xos, child, scopeId, ctxt);
00165     }
00166   }
00167 
00168   void Whirl2Xaif::translateAnalMaps(xml::ostream& xos, 
00169                                      PU_Info* pu_forest, 
00170                                      PUXlationContext& ctxt) {
00171     // -------------------------------------------------------
00172     // AliasSetList: The first element has to be there
00173     // -------------------------------------------------------
00174     xos << xml::BegElem("xaif:AliasSetMap");
00175 
00176     // print info for set 0 (unknown) and set 1 (empty loc set)
00177     xos << xml::BegElem("xaif:AliasSet") << xml::Attr("key", 0) << xml::EndElem;
00178     xos << xml::BegElem("xaif:AliasSet") << xml::Attr("key", 1) << xml::EndElem;
00179 
00180     Open64IRProcIterator procIt(pu_forest);
00181     // iterate over processed units
00182     for (int procCnt = 1; procIt.isValid(); ++procIt, ++procCnt) {
00183       PU_Info* pu = (PU_Info*)procIt.current().hval();
00184       fortTkSupport::IntraOAInfo* oaAnal = ourOAAnalMap.Find(pu);
00185       fortTkSupport::WNToWNIdMap* wnmap = ourWNToWNIdTableMap.Find(pu);
00186       OA::OA_ptr<OA::XAIF::AliasMapXAIF> aliasSets = oaAnal->getAliasXAIF();
00187       // iterate over alias sets
00188       for (OA::OA_ptr<OA::XAIF::IdIterator> aliasSetIdsIter = aliasSets->getIdIterator(); aliasSetIdsIter->isValid(); ++(*aliasSetIdsIter)) {
00189         int setId = aliasSetIdsIter->current();
00190         //if ((setId == 0 || setId == 1) && procCnt != 1) continue;
00191         if (setId == 0 || setId == 1) continue;
00192         xos << xml::BegElem("xaif:AliasSet") << xml::Attr("key", setId);
00193         // iterate over alias ranges
00194         for (OA::OA_ptr<OA::XAIF::LocTupleIterator> aLocTupleIter = aliasSets->getLocIterator(setId); aLocTupleIter->isValid(); ++(*aLocTupleIter) ) {
00195           xos << xml::BegElem("xaif:AliasRange");
00196           xos << xml::Attr("from_virtual_address", aLocTupleIter->current().getLocRange().getStart());
00197           xos << xml::Attr("to_virtual_address", aLocTupleIter->current().getLocRange().getEnd());
00198           xos << xml::Attr("partial", !(aLocTupleIter->current().isFull()));
00199           xos << xml::EndElem;
00200         }
00201         xos << xml::EndElem; // xaif:AliasSet
00202       }
00203     }
00204     xos << xml::EndElem; 
00205     xos << std::endl;
00206     // -------------------------------------------------------
00207     // DUUDSetMap: The first two elements are the *same* for each procedure.
00208     // -------------------------------------------------------
00209     xos << xml::BegElem("xaif:DUUDSetMap");
00210     procIt.reset();
00211     for (int procCnt = 1; procIt.isValid(); ++procIt, ++procCnt) {
00212       PU_Info* pu = (PU_Info*)procIt.current().hval();
00213       fortTkSupport::IntraOAInfo* oaAnal = ourOAAnalMap.Find(pu);
00214       fortTkSupport::WNToWNIdMap* wnmap = ourWNToWNIdTableMap.Find(pu);
00215       OA::OA_ptr<OA::XAIF::UDDUChainsXAIF> udduchains = oaAnal->getUDDUChainsXAIF();
00216       for (OA::OA_ptr<OA::XAIF::UDDUChainsXAIF::ChainsIterator> chainsIter = udduchains->getChainsIterator(); chainsIter->isValid(); ++(*chainsIter)) {
00217         OA::OA_ptr<OA::XAIF::ChainsXAIF::ChainIterator> chainIter = chainsIter->currentChainIterator();
00218         int chainid = chainsIter->currentId(); // 0-2 are same for each proc
00219         if ((0 <= chainid && chainid <= 2) && procCnt != 1) { continue; }
00220         xos << xml::BegElem("xaif:StmtIdSet") << xml::Attr("key", chainid);
00221         for ( ; chainIter->isValid(); (*chainIter)++ ) {
00222           OA::StmtHandle stmt = chainIter->current();
00223           WN* stmtWN = (WN*)(stmt.hval());
00224           fortTkSupport::WNId stmtid = wnmap->Find(stmtWN);
00225           xos << xml::BegElem("xaif:StatementId");
00226           if (stmtWN == NULL) {
00227             xos << xml::Attr("idRef", "");
00228           }
00229           else {
00230             xos << xml::Attr("idRef", stmtid);
00231           }
00232           xos << xml::EndElem;
00233         }
00234         xos << xml::EndElem; 
00235       }
00236     }
00237     xos << xml::EndElem; 
00238     xos << std::endl;
00239     // -------------------------------------------------------
00240     // DOSetMap: The first two elements are the *same* for each procedure.
00241     // -------------------------------------------------------
00242     xos << xml::BegElem("xaif:DOSetMap");
00243     procIt.reset();
00244     for (int procCnt = 1; procIt.isValid(); ++procIt, ++procCnt) {
00245       PU_Info* pu = (PU_Info*)procIt.current().hval();
00246       fortTkSupport::IntraOAInfo* oaAnal = ourOAAnalMap.Find(pu);
00247       fortTkSupport::WNToWNIdMap* wnmap = ourWNToWNIdTableMap.Find(pu);
00248       OA::OA_ptr<OA::XAIF::ReachDefsOverwriteXAIF> rdo = oaAnal->getReachDefsOverwriteXAIF();
00249       OA::OA_ptr<OA::XAIF::ReachDefsOverwriteXAIF::ChainsIterator> chainsIter 
00250         = rdo->getChainsIterator();
00251       for ( ; chainsIter->isValid(); ++(*chainsIter)) {
00252         OA::OA_ptr<OA::XAIF::ChainsXAIF::ChainIterator> chainIter 
00253           = chainsIter->currentChainIterator();
00254         int chainid = chainsIter->currentId(); // 0-2 are same for each proc
00255         if ((0 <= chainid && chainid <= 2) && procCnt != 1) { continue; }
00256         xos << xml::BegElem("xaif:StmtIdSet") << xml::Attr("key", chainid);
00257         for ( ; chainIter->isValid(); (*chainIter)++ ) {
00258           OA::StmtHandle stmt = chainIter->current();
00259           WN* stmtWN = (WN*)(stmt.hval());
00260           fortTkSupport::WNId stmtid = wnmap->Find(stmtWN);
00261           xos << xml::BegElem("xaif:StatementId");
00262           if (stmtWN == NULL) {
00263             xos << xml::Attr("idRef", "");
00264           }
00265           else {
00266             xos << xml::Attr("idRef", stmtid);
00267           }
00268           xos << xml::EndElem;
00269         }
00270         xos << xml::EndElem; 
00271       }
00272     }
00273     xos << xml::EndElem; 
00274     xos << std::endl;
00275   }
00276 
00277   void Whirl2Xaif::translatePU(xml::ostream& xos, 
00278                                OA::OA_ptr<OA::CallGraph::Node> n, 
00279                                UINT32 vertexId, 
00280                                PUXlationContext& ctxt) {
00281     // FIXME: A more general test will be needed
00282     PU_Info* pu = (PU_Info*)n->getProc().hval();
00283     FORTTK_ASSERT(pu, fortTkSupport::Diagnostics::UnexpectedInput << "PU is NULL");
00284     translatePU(xos, pu, n->getId(), ctxt);
00285     xos << std::endl;
00286     xos.flush();
00287   }
00288 
00289   bool hasUnstructuredCF(WN* thePU_WN_p,
00290                          ST* puST_p) { 
00291     // quick test for offending nodes  
00292     WN_TREE_CONTAINER<PRE_ORDER> aWNPtree(thePU_WN_p);
00293     WN_TREE_CONTAINER<PRE_ORDER>::iterator aWNPtreeIterator=aWNPtree.begin();
00294     while (aWNPtreeIterator != aWNPtree.end()) { 
00295       WN* curWN_p = aWNPtreeIterator.Wn();
00296       OPERATOR opr = WN_operator(curWN_p);
00297       if (opr==OPR_RETURN) { 
00298         // does it have a tail of Return nodes...
00299         // see if this curWN_p is the last node
00300         WN* tailWN_p=WN_last(WN_kid(thePU_WN_p,WN_kid_count(thePU_WN_p)-1));
00301         while (tailWN_p) {
00302           if (tailWN_p==curWN_p)
00303             break;
00304           else {
00305             if (WN_operator(tailWN_p)!=OPR_RETURN) { 
00306               FORTTK_MSG(1,"hasUnstructuredCF: found early return in " << ST_name(puST_p));
00307               return true; 
00308             }
00309             tailWN_p=WN_prev(tailWN_p);
00310           }
00311         }
00312       }
00313       if (opr==OPR_GOTO || opr==OPR_AGOTO) {
00314         LABEL_IDX lb=WN_label_number(curWN_p);
00315         if (Label_Table[lb].kind==LKIND_LOOP_GEN) { 
00316           FORTTK_MSG(1,"hasUnstructuredCF: found unstructured loop control flow statements in "<< ST_name(puST_p));
00317           return true; 
00318         }
00319         if (Label_Table[lb].kind!=LKIND_SELECT_GEN) { 
00320           FORTTK_MSG(1,"hasUnstructuredCF: found goto statements in "<< ST_name(puST_p));
00321           return true; 
00322         }
00323       }
00324       if (opr==OPR_TRUEBR) { 
00325         LABEL_IDX lb=WN_label_number(curWN_p);
00326         if (Label_Table[lb].kind==LKIND_LOOP_GEN) { 
00327           FORTTK_MSG(1,"hasUnstructuredCF: found unstructured loop control flow statements in "<< ST_name(puST_p));
00328           return true; 
00329         }
00330       } 
00331       ++aWNPtreeIterator;
00332     } 
00333     return false; 
00334   }
00335 
00336   void Whirl2Xaif::translatePU(xml::ostream& xos, 
00337                                PU_Info *pu, 
00338                                UINT32 vertexId,
00339                                PUXlationContext& ctxt) {
00340     if (!pu) { return; }
00341     PU_SetGlobalState(pu);
00342     bool isCompilerGen = ((Language == LANG_F90) && 
00343                           (CURRENT_SYMTAB == GLOBAL_SYMTAB + 2) && 
00344                           Is_Set_PU_Info_flags(pu, PU_IS_COMPILER_GENERATED));
00345     Is_True(!isCompilerGen, ("Compiler generated PU!")); // FIXME
00346     // -------------------------------------------------------
00347     // translate the PU
00348     // -------------------------------------------------------
00349     // FIXME: how is PU_f90_lang() different from (Language == LANG_F90)?
00350     PU& real_pu = PU_Info_pu(pu); 
00351     ctxt.setF90(PU_f90_lang(real_pu) != 0); // FIXME: set F90 flag
00352     bool isProgram = PU_is_mainpu(real_pu);
00353     ST* st = ST_ptr(PU_Info_proc_sym(pu));
00354     WN *wn_pu = PU_Info_tree_ptr(pu);
00355     fortTkSupport::PUId puId = ctxt.findPUId(pu);
00356     ST_TAB* sttab = Scope_tab[ST_level(st)].st_tab;
00357    fortTkSupport::SymTabId scopeId = ctxt.findSymTabId(sttab);
00358    fortTkSupport::SymTabId puScopeId = ctxt.findSymTabId(Scope_tab[CURRENT_SYMTAB].st_tab);
00359     // Generate the CFG
00360     xos << xml::Comment(ourDividerComment.c_str());
00361     if (isProgram) { xos << xml::Comment("*** This is the PROGRAM routine ***"); }
00362     xos << xml::BegElem("xaif:ControlFlowGraph") 
00363         << xml::Attr("vertex_id", vertexId) << xml::Attr("scope_id", scopeId)
00364         << AttrSymId(st) << PUIdAnnot(puId)
00365         << xml::Attr("controlflowgraph_scope_id", puScopeId);
00366     if (hasUnstructuredCF(wn_pu,st)) { 
00367       FORTTK_WMSG("translatePU: found unstructured control flow in "<< ST_name(st) << " while simple loop annotations (-s) were requested");
00368       xos << xml::Attr("structured", false);
00369     }
00370     xos << xml::EndAttrs;
00371     if (IsActivePU(st)) {
00372       translateWNPU(xos, wn_pu, ctxt);
00373     }
00374     xos << xml::EndElem; // xaif:ControlFlowGraph
00375   }
00376 
00377   void Whirl2Xaif::translateWNPU(xml::ostream& xos, 
00378                                  WN *wn_pu, 
00379                                  PUXlationContext& ctxt) {
00380     const char* const caller_err_phase = Get_Error_Phase();
00381     Diag_Set_Phase("WHIRL to XAIF: translate PU");
00382     Is_True(WN_opcode(wn_pu) == OPC_FUNC_ENTRY, ("Invalid opcode"));
00383     // fdump_tree(stderr, wn_pu);
00384     TranslateWN(xos, wn_pu, ctxt);
00385     Stab_Free_Tmpvars();  // FIXME: it would be nice to eventually 
00386     Stab_Free_Namebufs(); // remove this stuff
00387     Diag_Set_Phase(caller_err_phase);
00388   }
00389 
00390   void Whirl2Xaif::dumpTranslationHeaderComment(xml::ostream& xos) {
00391     // 1. Get a string representation of the time
00392     char tmStr[30] = "unknown time\n";
00393     time_t tm = time(NULL);
00394     if (tm != (time_t)-1) { strcpy(tmStr, ctime(&tm)); }
00395     tmStr[strlen(tmStr)-1] = '\0'; // remove the trailing '\n'
00396     // 2. Generate header comment
00397     xos << xml::Comment(ourDividerComment.c_str())
00398         << xml::BegComment << "XAIF file translated from WHIRL at " << tmStr 
00399         << xml::EndComment
00400         << xml::Comment(ourDividerComment.c_str()) << std::endl;
00401   }
00402 
00403 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines