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