|
OpenADFortTk (basic)
|
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 }