|
OpenADFortTk (basic)
|
00001 #include <set> 00002 #include "CleanUpWhirl.h" 00003 #include "IFDiagnostics.h" 00004 #include "WhirlGlobalStateUtils.h" 00005 00006 PU_Info* CleanUpWhirl::findModulePU(PU_Info* aPUInfoForest_p, 00007 ST* moduleName_ST_p) { 00008 PU_Info* aPUInfoTree_p; 00009 for (aPUInfoTree_p=aPUInfoForest_p; aPUInfoTree_p!= NULL; aPUInfoTree_p=PU_Info_next(aPUInfoTree_p)) { 00010 if (aPUInfoTree_p->proc_sym==ST_st_idx(*moduleName_ST_p)) 00011 return aPUInfoTree_p; 00012 } 00013 DIE("findModulePU: no module %s\n",ST_name(moduleName_ST_p)); 00014 } 00015 00016 00017 void CleanUpWhirl::forPUInfoForest(PU_Info* aPUInfoForest_p) { 00018 if (!aPUInfoForest_p) { return; } 00019 /* Loop through all the PU_Infos */ 00020 PU_Info* aPUInfoTree_p; 00021 for (aPUInfoTree_p=aPUInfoForest_p; aPUInfoTree_p!= NULL; aPUInfoTree_p=PU_Info_next(aPUInfoTree_p)) { 00022 forPUInfoTree(aPUInfoTree_p, 00023 aPUInfoForest_p); 00024 } 00025 } 00026 00027 void CleanUpWhirl::forPUInfoTree(PU_Info* aPUInfoTree_p, 00028 PU_Info* aTopPUInfo_p) { 00029 if (!aPUInfoTree_p) { return; } 00030 forPUInfo(aPUInfoTree_p, 00031 aTopPUInfo_p); 00032 for (PU_Info *aPUInfosubtree_p = PU_Info_child(aPUInfoTree_p); 00033 aPUInfosubtree_p != NULL; 00034 aPUInfosubtree_p = PU_Info_next(aPUInfosubtree_p)) { 00035 forPUInfoTree(aPUInfosubtree_p, 00036 aTopPUInfo_p); 00037 } 00038 } 00039 00040 ST* CleanUpWhirl::findModuleSymbol(ST* moduleName_ST_p, 00041 ST* dummyLocal_ST_p, 00042 PU_Info* aTopPUInfo_p) { 00043 INT level=ST_level(moduleName_ST_p); 00044 // level should be the same as the module name symbol, i.e. 1 00045 for (INT i = 1; 00046 i < ST_Table_Size(level) ; 00047 ++i) { 00048 // get the symbol from the table 00049 ST* an_ST_p=&(St_Table(level,i)); 00050 if ((ST_sclass(an_ST_p)==SCLASS_MODULE) // must be module storage class 00051 && 00052 (moduleName_ST_p== ST_base(an_ST_p)) // must be the same module symbol 00053 && 00054 (strcmp(ST_name(an_ST_p),ST_name(dummyLocal_ST_p))==0)) // must match the name 00055 return an_ST_p; 00056 } 00057 // haven't found it yet. This can be the case if the module variable is actually 00058 // a fortran "PARAMETER" i.e. a constant for which the name won't match 00059 // because its name in the global symbol table is the constant value. 00060 // we can't do anything here because the symbol table entry in the 00061 // actual module isn't visible in this context (because whirl 00062 // only distinguishes things by symbol table level (both would be level 2) 00063 // and within that given level by "index" 00064 // so we don't do anything here under the assumption that the 00065 // parameter in all references is being replaced by the actual value anyway 00066 PU_Info* theModulePU=findModulePU(aTopPUInfo_p,moduleName_ST_p); 00067 const char* dummyLocalName=ST_name(dummyLocal_ST_p); 00068 DBGMSG(2,"findModuleSymbol: not replacing presumed parameter with local name %s",dummyLocalName); 00069 return dummyLocal_ST_p; 00070 } 00071 00072 // in use statements the front-end generates 00073 // references to bogus local symbol table 00074 // entries instead of the proper entries in the 00075 // global symbol table. We replace these references. 00076 void CleanUpWhirl::forPUInfo(PU_Info* aPUInfo_p, 00077 PU_Info* aTopPUInfo_p) { 00078 PU_SetGlobalState(aPUInfo_p); 00079 WN *pragmaWN_p=0, *parentBlockWN_p=0; 00080 WN* thePU_WN_p = PU_Info_tree_ptr(aPUInfo_p); 00081 WN_TREE_CONTAINER<PRE_ORDER> aWNPtree(thePU_WN_p); 00082 WN_TREE_CONTAINER<PRE_ORDER>::iterator aWNPtreeIterator=aWNPtree.begin(); 00083 typedef std::pair<WN*, WN*> NodeBlockWNPPair; 00084 typedef std::set<NodeBlockWNPPair> NodeBlockWNPPairSet; 00085 NodeBlockWNPPairSet interfaceTreesToBeDeleted; 00086 std::set<WN*> useVarsToBeDeleted; 00087 bool skipKids=false; 00088 while (aWNPtreeIterator != aWNPtree.end()) { 00089 WN* curWN_p = aWNPtreeIterator.Wn(); 00090 OPERATOR opr = WN_operator(curWN_p); 00091 if (opr==OPR_USE) { // use statements 00092 skipKids=true; 00093 ST* moduleName_ST_p=WN_st(curWN_p); 00094 for (INT kidIdx = 0; kidIdx < WN_kid_count(curWN_p); kidIdx+=2) { 00095 // for each symbol listed in the code after the use 00096 // the symbol is repeated identical if it is not renamed 00097 // or else the first in the pair is the new name 00098 // with which we reference the module name listed as the second one. 00099 const char* renameName=ST_name(WN_st(WN_kid(curWN_p,kidIdx))); 00100 const char* moduleName=ST_name(WN_st(WN_kid(curWN_p,kidIdx+1))); 00101 if (!strcmp(renameName,moduleName)) { 00102 // is not a rename, fix up the first kid as well to be consistent 00103 WN* useOldKid_WN_p = WN_kid(curWN_p, kidIdx); 00104 ST* dummyLocal_ST_p=WN_st(useOldKid_WN_p); 00105 ST* properModule_ST_p=findModuleSymbol(moduleName_ST_p, 00106 dummyLocal_ST_p, 00107 aTopPUInfo_p); 00108 if (properModule_ST_p && properModule_ST_p!=dummyLocal_ST_p) { 00109 WN_kid(curWN_p,kidIdx)=WN_CreateIdname(WN_idname_offset(useOldKid_WN_p),properModule_ST_p); 00110 useVarsToBeDeleted.insert(useOldKid_WN_p); 00111 } 00112 } 00113 // always fix up the second kid 00114 WN* useOldKid_WN_p = WN_kid(curWN_p, kidIdx+1); 00115 ST* dummyLocal_ST_p=WN_st(useOldKid_WN_p); 00116 ST* properModule_ST_p=findModuleSymbol(moduleName_ST_p, 00117 dummyLocal_ST_p, 00118 aTopPUInfo_p); 00119 if (properModule_ST_p && properModule_ST_p!=dummyLocal_ST_p) { 00120 WN_kid(curWN_p,kidIdx+1)=WN_CreateIdname(WN_idname_offset(useOldKid_WN_p),properModule_ST_p); 00121 useVarsToBeDeleted.insert(useOldKid_WN_p); 00122 } 00123 } 00124 } 00125 else if ( opr == OPR_INTERFACE ) { 00126 if (parentBlockWN_p==0 || pragmaWN_p==0) { 00127 DIE("forPUInfo: need parentBlockWN_p(%h)!=0 and pragmaWN_p(%h)!=0\n",parentBlockWN_p,pragmaWN_p); 00128 } 00129 skipKids=true; 00130 if (parentBlockWN_p!=pragmaWN_p) { // don't repeat things if we already cleaned up once ... 00131 // make a copy of curWN_p 00132 // attach it to pragma_WN_p 00133 WN* newInterfaceWN_p=WN_COPY_Tree(curWN_p); 00134 WN_INSERT_BlockLast(pragmaWN_p,newInterfaceWN_p); 00135 interfaceTreesToBeDeleted.insert(NodeBlockWNPPair(curWN_p,parentBlockWN_p)); 00136 } 00137 } 00138 else if ( opr == OPR_BLOCK ) { 00139 parentBlockWN_p=curWN_p; 00140 } 00141 else if ( opr == OPR_FUNC_ENTRY ) { 00142 pragmaWN_p=WN_kid(curWN_p,WN_kid_count(curWN_p)-3); 00143 } 00144 // advance the iterator 00145 if (skipKids){ 00146 aWNPtreeIterator.WN_TREE_next_skip(); 00147 skipKids=false; 00148 } 00149 else 00150 ++aWNPtreeIterator; 00151 } 00152 // postpone the deletion to avoid possibly upsetting the iterator 00153 for (std::set<WN*>::iterator i = useVarsToBeDeleted.begin(); 00154 i!=useVarsToBeDeleted.end(); 00155 ++i) 00156 WN_Delete(*i); 00157 for (NodeBlockWNPPairSet::iterator i = interfaceTreesToBeDeleted.begin(); 00158 i!=interfaceTreesToBeDeleted.end(); 00159 ++i) { 00160 WN_DELETE_FromBlock((*i).second,(*i).first); 00161 } 00162 } 00163