#include "leak_detector.h" #include #include #include #include #include #include #include #include #include "dvm.h" #include "../GraphCall/graph_calls_func.h" #include "../Utils/SgUtils.h" #include "../Utils/CommonBlock.h" #include "../Utils/DefUseList.h" #include "expr_transform.h" #include "../VerificationCode/verifications.h" #include "../DvmhRegions/DvmhRegionInserter.h" #include "function_purifying.h" using std::vector; using std::map; using std::set; using std::pair; using std::tuple; using std::string; using std::wstring; using std::make_pair; using std::to_string; static bool isIntrincis(const string& name); void insertIntrinsicStat(const vector& allFuncInfo) { for (auto& func : allFuncInfo) { auto start = func->funcPointer->GetOriginal(); auto end = start->lastNodeOfStmt(); SgStatement* st = start; SgStatement* intr = NULL; //find last decl place for ( ; st != end; st = st->lexNext()) { if (isSgExecutableStatement(st)) break; if (st->variant() == CONTAINS_STMT) break; if (st->variant() == INTRIN_STAT) intr = st; } map intrincis; for (auto& call : func->callsFromDetailed) { auto name = call.detailCallsFrom.first; if (intrincis.find(name) != intrincis.end()) continue; if (!isIntrincis(name)) continue; void* ptr = call.pointerDetailCallsFrom.first; int var = call.pointerDetailCallsFrom.second; SgSymbol* s = NULL; if (var == PROC_STAT) s = ((SgStatement*)ptr)->symbol(); else if (var == FUNC_CALL) s = ((SgExpression*)ptr)->symbol(); else continue; if ((s->attributes() & INTRINSIC_BIT) != 0) continue; intrincis[name] = s; } if (!intrincis.size()) continue; if (intr == NULL) { vector list; for (auto& elem : intrincis) list.push_back(new SgVarRefExp(elem.second)); SgStatement* intr = new SgStatement(INTRIN_STAT); intr->setExpression(0, makeExprList(list)); auto prev = (st->variant() == FOR_NODE) ? st->lexPrev() : st; int line = prev->lineNumber(); while (line <= 0 && !isSgProgHedrStmt(prev)) { prev = prev->lexPrev(); line = prev->lineNumber(); } if (line <= 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); intr->setlineNumber(line); st->insertStmtBefore(*intr, *func->funcPointer); } else { SgExprListExp* list = isSgExprListExp(intr->expr(0)); checkNull(list, convertFileName(__FILE__).c_str(), __LINE__); for (auto& elem : intrincis) list->append(*new SgVarRefExp(elem.second)); } } } bool checkOutCalls(const set& outCalls) { for (auto& elem : outCalls) if (isIntrinsicFunctionName(elem.c_str()) == 0) return true; return false; } void createInterfacesForOutCalls(FuncInfo* func) { if (func->isPure && !func->isMain) { bool hasOutCalls = checkOutCalls(func->callsFrom); if (hasOutCalls) DvmhRegionInserter::createInterfaceBlockForOutCalls(func); } } static bool changeIfHasStarRange(SgExpression* arrayDecl, bool doReplace = false) { SgExpression* list = arrayDecl->lhs(); bool has = doReplace; while (list) { const int var = list->lhs()->variant(); if (var == STAR_RANGE) has = true; list = list->rhs(); } if (has) { list = arrayDecl->lhs(); while (list) { list->setLhs(new SgExpression(DDOT)); list = list->rhs(); } } return has; } static void removeExternalStat(SgStatement* func, const set& addedInterfaceFor) { vector toRem; for (auto st = func; st != func->lastNodeOfStmt(); st = st->lexNext()) { if (isSgExecutableStatement(st)) break; if (st->variant() == CONTAINS_STMT) break; if (st->variant() == EXTERN_STAT) { vector list; SgExpression* ex = st->expr(0); int count = 0; while (ex) { if (addedInterfaceFor.find(ex->lhs()->symbol()->identifier()) == addedInterfaceFor.end()) list.push_back(ex->lhs()); count++; ex = ex->rhs(); } if (count == list.size()) continue; if (list.size() == 0) toRem.push_back(st); else st->setExpression(0, makeExprList(list, false)); } } for (auto& rem : toRem) rem->deleteStmt(); } template static vector sortByName(const T &funcs) { vector funcList; for (auto& elem : funcs) funcList.push_back(elem); std::sort(funcList.begin(), funcList.end(), [](FuncInfo* a, FuncInfo* b) { return a->funcName > b->funcName; }); return funcList; } void createInterfacesForAssumedSize(const map>& allFuncInfo) { set hasAssumedSizeArrays; for (auto& funcByFile : allFuncInfo) { if (SgFile::switchToFile(funcByFile.first) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& func : funcByFile.second) { SgProgHedrStmt* prog = isSgProgHedrStmt(func->funcPointer->GetOriginal()); if (prog == NULL) continue; vector arrayRefs; bool hasRefs = false; for (int z = 0; z < func->funcParams.countOfPars; ++z) { if (func->funcParams.parametersT[z] == ARRAY_T) { auto s = prog->parameter(z); const string name = s->identifier(); vector allDecls; declaratedInStmt(s, &allDecls); for (auto& decl : allDecls) { SgExpression* list = decl->expr(0); while (list) { if (list->lhs() && list->lhs()->symbol()->identifier() == name) { if (changeIfHasStarRange(list->lhs())) { hasRefs = true; hasAssumedSizeArrays.insert(func); } else arrayRefs.push_back(list->lhs()); break; } list = list->rhs(); } } } } if (hasRefs) for (auto& ref : arrayRefs) changeIfHasStarRange(ref, true); } } if (hasAssumedSizeArrays.size() == 0) return; for (auto& funcByFile : allFuncInfo) { if (SgFile::switchToFile(funcByFile.first) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& func : sortByName(funcByFile.second)) { SgProgHedrStmt* prog = isSgProgHedrStmt(func->funcPointer->GetOriginal()); if (prog == NULL) continue; set addedInterfaceFor; for (auto& elem : sortByName(func->callsFromV)) { auto it = hasAssumedSizeArrays.find(elem); if (it != hasAssumedSizeArrays.end()) { auto callFrom = *it; DvmhRegionInserter::createInterfaceBlockForOutCall(func, callFrom); addedInterfaceFor.insert(callFrom->funcName); } } if (addedInterfaceFor.size()) removeExternalStat(prog, addedInterfaceFor); } } } static void setPureStatus(FuncInfo* func) { if (func->isPure && !func->isMain) { SgStatement* header = func->funcPointer->GetOriginal(); if (header->switchToFile() == false) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); bool isFunc = (header->variant() == FUNC_HEDR); bool hasOut = false; for (int z = 0; z < func->funcParams.countOfPars; ++z) hasOut |= func->funcParams.isArgOut(z); bool hasPure = (header->expr(2) != NULL) || ((header->symbol()->attributes() & PURE_BIT) != 0); bool hasIO = func->linesOfIO.size() || func->linesOfStop.size(); if (!hasPure && !hasIO && ((isFunc == false) || (isFunc && hasOut == false))) { header->setExpression(2, new SgExpression(PURE_OP)); header->symbol()->setAttribute(header->symbol()->attributes() | PURE_BIT); } } } void setPureStatus(const set& funcInfo) { for (auto& func : funcInfo) setPureStatus(func); } void setPureStatus(const map>& allFuncInfo) { for (auto& funcByFile : allFuncInfo) for (auto& func : funcByFile.second) setPureStatus(func); for (auto& funcByFile : allFuncInfo) for (auto& func : funcByFile.second) createInterfacesForOutCalls(func); } map> fillFromIntent(SgStatement* header) { map> intentS; if (header->variant() == ENTRY_STAT) while (isSgProgHedrStmt(header) == NULL) header = header->controlParent(); SgStatement* last = header->lastNodeOfStmt(); for (auto stmt = header->lexNext(); stmt && stmt != last; stmt = stmt->lexNext()) { if (stmt->variant() == CONTAINS_STMT) break; if (isSgExecutableStatement(stmt)) break; if (stmt->variant() == INTENT_STMT) { SgIntentStmt* s = (SgIntentStmt*)stmt; for (int i = 0; i < s->numberOfVars(); i++) intentS[s].insert(s->var(i)->symbol()->identifier()); } else { //check intent in decl SgExpression* ex = stmt->expr(2); bool containsIntent = false; while (ex) { if (ex->lhs()) { int var = ex->lhs()->variant(); if (var == IN_OP || var == INOUT_OP || var == OUT_OP) containsIntent = true; } ex = ex->rhs(); } if (containsIntent) { SgExpression* ex = stmt->expr(0); while (ex) { if (ex->lhs() && ex->lhs()->symbol()) intentS[stmt].insert(ex->lhs()->symbol()->identifier()); ex = ex->rhs(); } } } } return intentS; } static void insertIntents(set& identificators, SgStatement* header, const map& parSym, int intentVariant, int intentBit) { if (identificators.size() == 0) return; if (header->variant() == ENTRY_STAT) while (isSgProgHedrStmt(header) == NULL) header = header->controlParent(); SgStatement* last = header->lastNodeOfStmt(); SgStatement* lastDecl = header; for (auto stmt = header->lexNext(); stmt && stmt != last; stmt = stmt->lexNext()) { if (stmt->variant() == CONTAINS_STMT) break; if (isSgExecutableStatement(stmt)) break; if (stmt->variant() != ENTRY_STAT) lastDecl = stmt; if (stmt->variant() == VAR_DECL_90) { SgVarDeclStmt* s = (SgVarDeclStmt*)stmt; for (int i = 0; i < s->numberOfAttributes(); i++) { if (s->attribute(i)->variant() == intentVariant) { for (int i = 0; i < s->numberOfVars(); i++) { auto sname = s->var(i)->symbol()->identifier(); if (identificators.count(sname)) identificators.erase(sname); } } } } else if (stmt->variant() == INTENT_STMT) { SgIntentStmt* s = (SgIntentStmt*)stmt; if (s->attribute()->variant() == intentVariant) { for (int i = 0; i < s->numberOfVars(); i++) { auto sname = s->var(i)->symbol()->identifier(); if (identificators.count(sname)) identificators.erase(sname); } } } } SgExpression* attr = new SgExpression(intentVariant); vector args; for (auto& par : identificators) { if (parSym.count(par) == 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); auto s = parSym.at(par); args.push_back(new SgVarRefExp(s)); s->setAttribute(s->attributes() | intentBit); } if (args.size()) { SgIntentStmt* intent = new SgIntentStmt(*makeExprList(args), *attr); intent->setlineNumber(lastDecl->lineNumber()); lastDecl->insertStmtAfter(*intent, (header == lastDecl) ? *header : *lastDecl->controlParent()); } } static SgSymbol* getParameter(SgStatement* stat, int n) { SgSymbol* retVal = NULL; auto funcStat = isSgProgHedrStmt(stat); if (funcStat) retVal = funcStat->parameter(n); else if (stat->variant() == ENTRY_STAT) { SgExpression* list = stat->expr(0); while (n != 0) { --n; list = list->rhs(); } retVal = list->lhs()->symbol(); } checkNull(retVal, convertFileName(__FILE__).c_str(), __LINE__); return retVal; } static void intentInsert(const FuncInfo* func, SgStatement* headerSt) { if (func == NULL) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (func->funcPointer->variant() == ENTRY_STAT) return; set InIdentificators; set OutIdentificators; set InOutIdentificators; map parSym; set intentS; auto intentsByStat = fillFromIntent(headerSt); for (auto& elem : intentsByStat) intentS.insert(elem.second.begin(), elem.second.end()); intentS.insert(func->callsFrom.begin(), func->callsFrom.end()); for (int i = 0; i < func->funcParams.countOfPars; i++) { SgSymbol* parS = getParameter(headerSt, i); const string ident = parS->identifier(); if (ident == "*" || parS->attributes() & EXTERNAL_BIT) continue; parSym[ident] = parS; if (intentS.find(ident) != intentS.end()) continue; if (func->funcParams.isArgInOut(i)) InOutIdentificators.insert(ident); else if (func->funcParams.isArgIn(i)) InIdentificators.insert(ident); else if (func->funcParams.isArgOut(i)) OutIdentificators.insert(ident); } //remove conflicted intents for (auto& entry : func->entry) { for (int i = 0; i < entry->funcParams.countOfPars; i++) { const auto& ident = entry->funcParams.identificators[i]; if (entry->funcParams.isArgInOut(i)) { if (InIdentificators.count(ident)) InIdentificators.erase(ident); if (OutIdentificators.count(ident)) OutIdentificators.erase(ident); } else if (entry->funcParams.isArgIn(i)) { if (InOutIdentificators.count(ident)) InOutIdentificators.erase(ident); if (OutIdentificators.count(ident)) OutIdentificators.erase(ident); } else if (entry->funcParams.isArgOut(i)) { if (InIdentificators.count(ident)) InIdentificators.erase(ident); if (InOutIdentificators.count(ident)) InOutIdentificators.erase(ident); } } } insertIntents(InOutIdentificators, headerSt, parSym, INOUT_OP, INOUT_BIT); insertIntents(InIdentificators, headerSt, parSym, IN_OP, IN_BIT); insertIntents(OutIdentificators, headerSt, parSym, OUT_OP, OUT_BIT); } void intentInsert(const vector& allFuncInfo) { for (auto& func : allFuncInfo) { if (func->isMain) continue; intentInsert(func, func->funcPointer->GetOriginal()); } } void intentInsertToInterfaces(const map>& allFuncInfo) { for (auto& funcByFile : allFuncInfo) { if (SgFile::switchToFile(funcByFile.first) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& func : funcByFile.second) { if (func->interfaceBlocks.size() == 0) continue; auto start = func->funcPointer->GetOriginal(); auto end = start->lastNodeOfStmt(); for (auto st = start; st != end; st = st->lexNext()) { if (isSgExecutableStatement(st)) break; if (st->variant() == CONTAINS_STMT) break; if (st->controlParent()->variant() == INTERFACE_STMT) { if (st->variant() == PROC_HEDR || st->variant() == FUNC_HEDR) { auto it = func->interfaceBlocks.find(st->symbol()->identifier()); if (it == func->interfaceBlocks.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); intentInsert(it->second, st); } } } } } } //DEBUG /*static void printcvu(map>& commonVarsUsed) { for (auto& common : commonVarsUsed) { printf(">%s\n", common.first.c_str()); for (int posVar : common.second) printf("\t%d\n", posVar); } }*/ static void collectForChange(set& allForChange, FuncInfo* start) { allForChange.insert(start); bool chagned = true; while (chagned) { set newAdd; for (auto& elem : allForChange) for (auto& call : elem->callsFromV) if (allForChange.find(call) == allForChange.end()) newAdd.insert(call); chagned = newAdd.size() != 0; allForChange.insert(newAdd.begin(), newAdd.end()); } } template static void transferVarToArg(const map>& commonVarsUsed, const map& commonBlocks, const FuncInfo* curFunc, CallExp* callExp) { for (auto& common : commonVarsUsed) { for (auto& posVar : common.second) { const Variable* var = commonBlocks.find(common.first)->second->getGroupedVars().find(posVar)->second[0]; string name = ""; if (curFunc->isMain && curFunc->commonBlocks.count(common.first) > 0) { for (auto& v : commonBlocks.find(common.first)->second->getVariables(curFunc->fileName, curFunc->funcName)) { if (v->getPosition() == posVar) { name = v->getName(); break; } } } else if ((int)(string(var->getName()).find("c_" + common.first + "_")) < 0) name = "c_" + common.first + "_" + var->getName(); else name = var->getName(); SgSymbol* s = new SgSymbol(var->getSymbol()->variant(), name.c_str()); callExp->addArg(*new SgVarRefExp(*s)); } } } static void findInterfaces(FuncInfo* func, vector& ifaces) { for (auto& callFunc : func->callsTo) { SgStatement* iface = NULL; if (callFunc->interfaceBlocks.find(func->funcName) != callFunc->interfaceBlocks.end()) { SgStatement* hedr = callFunc->funcPointer->GetOriginal(); for (SgStatement* start = hedr->lexNext(), *end = hedr->lastNodeOfStmt(); start != end; start = start->lexNext()) { if (start->variant() == INTERFACE_STMT) { for (int i = 0; i < start->numberOfChildrenList1(); i++) { if ((isSgProgHedrStmt(start->childList1(i))) && start->childList1(i)->symbol()->identifier() == func->funcName) { iface = start->childList1(i); break; } } } if (iface) { ifaces.push_back(iface); break; } } } } } static void transferCommons(set& allForChange, map >>& funcCommons, map>& commonVarsUsed, FuncInfo* curFunc, FuncInfo* precFunc, const map& commonBlocks, map>& funcCommonDeclared) { if (commonVarsUsed.empty()) return; if (funcCommons.count(curFunc) == 0) funcCommons[curFunc] = map>(); //add params to calls if (curFunc != precFunc) { if (SgFile::switchToFile(curFunc->fileName) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& callInfo : curFunc->callsFromDetailed) { auto& call = callInfo.pointerDetailCallsFrom; if (isSgFuncHedrStmt(precFunc->funcPointer->GetOriginal()) && call.second == FUNC_CALL) { SgFunctionCallExp* callExp = (SgFunctionCallExp*)call.first; if (callExp->funName()->identifier() == precFunc->funcName) transferVarToArg(commonVarsUsed, commonBlocks, curFunc, callExp); } else if (isSgProcHedrStmt(precFunc->funcPointer->GetOriginal()) && call.second == PROC_STAT) { SgCallStmt* callSt = (SgCallStmt*)call.first; if (callSt->name()->identifier() == precFunc->funcName) transferVarToArg(commonVarsUsed, commonBlocks, curFunc, callSt); } } } map> nextCommonVarsUsed; //find the things we have already done for (auto& common : commonVarsUsed) { if (funcCommons[curFunc].count(common.first) == 0) funcCommons[curFunc][common.first] = vector(); for (auto& var : common.second) { bool done = false; for (auto& v : funcCommons[curFunc][common.first]) if (v == var) done = true; if (!done) { funcCommons[curFunc][common.first].push_back(var); if (nextCommonVarsUsed.count(common.first) == 0) nextCommonVarsUsed[common.first] = vector(); nextCommonVarsUsed[common.first].push_back(var); } } } vector ifaces; ifaces.push_back(curFunc->funcPointer->GetOriginal()); findInterfaces(curFunc, ifaces); for (auto& common : nextCommonVarsUsed) { bool uses = false; auto groupedVars = commonBlocks.find(common.first)->second->getGroupedVars(); if (curFunc->commonBlocks.count(common.first) > 0) //rename common vars in funcs { uses = true; const vector& vars = commonBlocks.find(common.first)->second->getVariables(curFunc->fileName, curFunc->funcName); if (allForChange.count(curFunc)) { for (auto& var : vars) { bool contains = false; for (auto& v : common.second) if (v == var->getPosition()) contains = true; if (contains) { for (auto& varUse : var->getAllUse()) { if (varUse.getFileName() == curFunc->fileName && varUse.getFunctionName() == curFunc->funcName) { string name; if ((int)(string(groupedVars[var->getPosition()][0]->getName()).find("c_" + common.first + "_")) < 0) name = "c_" + common.first + "_" + groupedVars[var->getPosition()][0]->getName(); else name = groupedVars[var->getPosition()][0]->getName(); varUse.getUseS()->changeName(name.c_str()); break; } } } } } } else if (!allForChange.count(curFunc)) //add of commons to main { SgExprListExp* res = NULL; vector varsToDeclare = vector (); for (auto it = groupedVars.rbegin(); it != groupedVars.rend(); it++) { string name; if ((int)(string(it->second[0]->getName()).find("c_" + common.first + "_")) < 0) name = "c_" + common.first + "_" + it->second[0]->getName(); else name = it->second[0]->getName(); SgSymbol* symb = it->second[0]->getSymbol(); SgType* type = symb->type(); SgSymbol* s = new SgSymbol(symb->variant(), name.c_str(), type, curFunc->funcPointer); SgVarRefExp* vr = new SgVarRefExp(s); SgExprListExp* el = new SgExprListExp(); el->setLhs(vr); el->setRhs(res); res = el; varsToDeclare.push_back(s); } SgSymbol* commSymb = new SgSymbol(VARIABLE_NAME, common.first.c_str()); SgExprListExp* commList = new SgExprListExp(COMM_LIST); SgStatement* commStat = new SgStatement(COMM_STAT); commStat->setExpression(0, *commList); commList->setSymbol(commSymb); commList->setLhs(res); SgStatement* firstExDec, * hedr = curFunc->funcPointer->GetOriginal(); for (SgStatement* start = hedr->lexNext(), *end = hedr->lastNodeOfStmt(); start != end; start = start->lexNext()) { if ((isSgExecutableStatement(start) || isSgDeclarationStatement(start)) && !strcmp(hedr->fileName(), start->fileName())) { firstExDec = start; break; } } commStat->setlineNumber(firstExDec->lineNumber()); firstExDec->insertStmtBefore(*commStat, *(hedr)); for (auto& var : varsToDeclare) { vector varVec = vector(); varVec.push_back(var); SgStatement* decl = makeDeclaration(NULL, varVec); for (int i = 0; i < 3; i++) { SgExpression* e; if (e = decl->expr(i)) decl->setExpression(i, CalculateInteger(ReplaceConstant(e))); } decl->setlineNumber(firstExDec->lineNumber()); decl->setFileName(hedr->fileName()); commStat->insertStmtAfter(*decl, *(hedr)); } } //parametrs add if (allForChange.count(curFunc)) { for (int i = 0; i < ifaces.size(); i++) { for (auto& posVar : common.second) { const Variable* var = commonBlocks.find(common.first)->second->getGroupedVars().find(posVar)->second[0]; SgSymbol* symb = var->getSymbol(); string name; if ((int)(string(symb->identifier()).find("c_" + common.first + "_")) < 0) name = "c_" + common.first + "_" + var->getSymbol()->identifier(); else name = symb->identifier(); SgSymbol* s = new SgSymbol(symb->variant(), name.c_str(), symb->type(), ifaces[i]); SgStatement* hedr = ifaces[i]; SgExpression* result = hedr->expr(0) == NULL ? NULL : hedr->expr(0)->copyPtr(); if (isSgFuncHedrStmt(hedr)) isSgFuncHedrStmt(hedr)->AddArg(*new SgVarRefExp(s)); else if (isSgProcHedrStmt(hedr)) isSgProcHedrStmt(hedr)->AddArg(*new SgVarRefExp(s)); else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); if (result == NULL) { if (hedr->expr(0) != NULL) hedr->setExpression(0, NULL); } else { if (hedr->expr(0) != NULL) hedr->setExpression(0, result); else if (string(hedr->expr(0)->unparse()) != result->unparse()) hedr->setExpression(0, result); } curFunc->funcPointer->GetOriginal()->lexNext()->deleteStmt(); if (!funcCommonDeclared[curFunc].count(common.first) || i!=0) { vector varVec = vector(); varVec.push_back(s); SgStatement* decl = makeDeclaration(NULL, varVec); for (int i = 0; i < 3; i++) { SgExpression* e; if (e = decl->expr(i)) decl->setExpression(i, CalculateInteger(ReplaceConstant(e))); } SgStatement* firstExDec; for (SgStatement* start = hedr->lexNext(), *end = hedr->lastNodeOfStmt(); start != end; start = start->lexNext()) { if ((isSgExecutableStatement(start) || isSgDeclarationStatement(start)) && !strcmp(hedr->fileName(), start->fileName())) { firstExDec = start; break; } } decl->setlineNumber(firstExDec->lineNumber()); decl->setFileName(hedr->fileName()); firstExDec->insertStmtBefore(*decl, *(hedr)); } } } } } for (auto& callFunc : curFunc->callsTo) transferCommons(allForChange, funcCommons, nextCommonVarsUsed, callFunc, curFunc, commonBlocks, funcCommonDeclared); } static void fillUsedVars(set& usedVars, SgExpression* exp) { if (exp) { if (exp->variant() == VAR_REF || exp->variant() == ARRAY_REF) usedVars.insert(exp->symbol()->identifier()); fillUsedVars(usedVars, exp->lhs()); fillUsedVars(usedVars, exp->rhs()); } } void commonTransfer(const map>& allFuncInfo, const map& commonBlocks) { map >> funcCommons; map > funcCommonDeclared; FuncInfo* start = NULL; set allForChange; for (auto& byfile : allFuncInfo) { if (SgFile::switchToFile(byfile.first) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& func : byfile.second) { SgStatement* st = func->funcPointer->GetOriginal(); if (st->variant() < 0 || func->isInterface) continue; if (func->commonBlocks.size() > 0 && st->variant() != PROG_HEDR) { for (SgStatement* start = st, *end = st->lastNodeOfStmt(); start != end;) { if (start->variant() == CONTAINS_STMT) break; SgStatement* next = start->lexNext(); if (start->variant() == COMM_STAT && string(start->fileName()) == func->fileName) { if (funcCommonDeclared.count(func) == 0) funcCommonDeclared[func] = set(); for (SgExpression* e = start->expr(0); e; e = e->rhs()) funcCommonDeclared[func].insert(e->symbol() ? e->symbol()->identifier() : "spf_unnamed"); start->deleteStmt(); } start = next; } } if (func->isMain) start = func; } } checkNull(start, convertFileName(__FILE__).c_str(), __LINE__); collectForChange(allForChange, start); allForChange.erase(start); for (auto& func : allForChange) { if (SgFile::switchToFile(func->fileName) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgStatement* st = func->funcPointer->GetOriginal(); if (st->variant() < 0 || st->variant() == PROG_HEDR || func->isInterface) continue; if (func->commonBlocks.size() > 0) { map> commonVarsUsed; set usedVars; for (SgStatement* start = st->lastDeclaration()->lexNext(), *end = st->lastNodeOfStmt(); start != end; start = start->lexNext()) { if (start->variant() == CONTAINS_STMT) break; if (isSgExecutableStatement(start)) for (int i = 0; i < 3; i++) fillUsedVars(usedVars, start->expr(i)); } for (auto& var : usedVars) { for (auto& common : func->commonBlocks) { const string name = common.first; if (common.second.count(var) > 0) { if (commonVarsUsed.count(common.first) == 0) commonVarsUsed[name] = vector(); for (auto& cvar : commonBlocks.find(name)->second->getVariables(func->fileName, func->funcName)) if (cvar->getName() == var) commonVarsUsed[name].push_back(cvar->getPosition()); } } } transferCommons(allForChange, funcCommons, commonVarsUsed, func, func, commonBlocks, funcCommonDeclared); } } } static string changeData(const string& data, const map& constSymVars, const map& locVars) { int curChar = 0; string ident = ""; string res = ""; while (curChar < data.length()) { switch (data[curChar]) { case ' ': case ',': case ')': case '(': case '=': case '*': case '/': case '\n': case '\t': if (ident.size() > 0) { if (constSymVars.count(ident) > 0) res += constSymVars.at(ident); else if (locVars.count(ident) > 0) res += locVars.at(ident); else res += ident; ident = ""; } res += tolower(data[curChar]); curChar++; break; default: ident += tolower(data[curChar]); curChar++; break; } } return res; } static void transferSave(map>& funcAddedVarsFuncs, vector & varsToTransfer, vector & dataToTransfer, FuncInfo* curFunc, FuncInfo* precFunc, FuncInfo* startFunc) { if (curFunc != precFunc) { if (SgFile::switchToFile(curFunc->fileName) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); for (auto& callInfo : curFunc->callsFromDetailed) { auto& call = callInfo.pointerDetailCallsFrom; if (isSgFuncHedrStmt(precFunc->funcPointer->GetOriginal()) && call.second == FUNC_CALL) { SgFunctionCallExp* callExp = (SgFunctionCallExp*)call.first; if (callExp->funName()->identifier() == precFunc->funcName) for (auto& var : varsToTransfer) callExp->addArg(*new SgVarRefExp(*var)); } else if (isSgProcHedrStmt(precFunc->funcPointer->GetOriginal()) && call.second == PROC_STAT) { SgCallStmt* callSt = (SgCallStmt*)call.first; if (callSt->name()->identifier() == precFunc->funcName) for (auto& var : varsToTransfer) callSt->addArg(*new SgVarRefExp(*var)); } } } if (!funcAddedVarsFuncs.count(curFunc)) funcAddedVarsFuncs[curFunc] = set(); else if (funcAddedVarsFuncs[curFunc].count(startFunc)) return; vector ifaces; ifaces.push_back(curFunc->funcPointer->GetOriginal()); findInterfaces(curFunc, ifaces); funcAddedVarsFuncs[curFunc].insert(startFunc); if (!curFunc->isMain) { for (int i = 0; i < ifaces.size(); i++) { SgStatement* hedr = ifaces[i]; for (auto& var : varsToTransfer) { ((SgProcHedrStmt*)(hedr))->AddArg(*new SgVarRefExp(var->copy())); hedr->lexNext()->deleteStmt(); if (curFunc != startFunc || i!=0) { vector varVec = vector(); varVec.push_back(var); SgStatement* decl = makeDeclaration(NULL, varVec); for (int i = 0; i < 3; i++) { SgExpression* e; if (e = decl->expr(i)) decl->setExpression(i, CalculateInteger(ReplaceConstant(e))); } SgStatement* firstExDec = NULL; for (SgStatement* start = hedr->lexNext(), *end = hedr->lastNodeOfStmt(); start != end; start = start->lexNext()) { if ((isSgExecutableStatement(start) || isSgDeclarationStatement(start)) && !strcmp(hedr->fileName(), start->fileName())) { firstExDec = start; break; } } checkNull(firstExDec, convertFileName(__FILE__).c_str(), __LINE__); decl->setlineNumber(firstExDec->lineNumber()); decl->setFileName(hedr->fileName()); firstExDec->insertStmtBefore(*decl, *(hedr)); } } } for (auto& callFunc : curFunc->callsTo) transferSave(funcAddedVarsFuncs, varsToTransfer, dataToTransfer, callFunc, curFunc, startFunc); } else { SgStatement* firstExDec = NULL; auto hedr = curFunc->funcPointer->GetOriginal(); for (SgStatement* start = hedr->lexNext(), *end = hedr->lastNodeOfStmt(); start != end; start = start->lexNext()) { if ((isSgExecutableStatement(start) || isSgDeclarationStatement(start)) && !strcmp(hedr->fileName(), start->fileName())) { firstExDec = start; break; } } checkNull(firstExDec, convertFileName(__FILE__).c_str(), __LINE__); for (auto& var : varsToTransfer) { vector varVec = vector(); varVec.push_back(var); SgStatement* decl = makeDeclaration(NULL, varVec); for (int i = 0; i < 3; i++) { SgExpression* e; if (e = decl->expr(i)) decl->setExpression(i, CalculateInteger(ReplaceConstant(e))); } decl->setlineNumber(firstExDec->lineNumber()); decl->setFileName(hedr->fileName()); firstExDec->insertStmtBefore(*decl, *(hedr)); } for (auto& data : dataToTransfer) firstExDec->addComment(data.c_str()); } } void saveTransfer(const map>& allFuncInfo) { FuncInfo* start = NULL; set allForChange; map> funcAddedVarsFuncs; for (auto& byfile : allFuncInfo) for (auto& func : byfile.second) if (func->isMain) start = func; collectForChange(allForChange, start); allForChange.erase(start); for (auto& func : allForChange) { if (SgFile::switchToFile(func->fileName) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgStatement* st = func->funcPointer->GetOriginal(); vector varsToTransfer; vector dataToTransfer; map varInit; map constSymVars; map locVars; set params; bool hasComplType = false; SgStatement* lst = st->lastNodeOfStmt(); SgSymbol* s, * sl; bool allSave = false; for (SgStatement* start = st, *end = lst; start != end; start = start->lexNext()) { if (start->variant() == CONTAINS_STMT) break; if (start->variant() == SAVE_DECL && !start->expr(0)) allSave = true; } for (auto& s : func->funcParams.identificators) params.insert(s); sl = lst->lexNext() ? lst->lexNext()->symbol() : NULL; for (s = st->symbol(); s != sl && s != NULL; s = s->next()) { SgConstantSymb* sc = isSgConstantSymb(s); if (sc && sc->constantValue()) constSymVars[string(s->identifier())] = string(sc->constantValue()->unparse()); if (s->scope() == st) { if ( (s->attributes() & SAVE_BIT) || (s->attributes() & DATA_BIT) || allSave && s->variant() == VARIABLE_NAME && !params.count(s->identifier())) { if ((s->type() ? s->type()->variant() : (T_COMPLEX + 1)) > T_COMPLEX) { hasComplType = true; break; } string newName = "s_" + func->funcName + "_" + s->identifier(); locVars[s->identifier()] = newName; s->changeName(newName.c_str()); varsToTransfer.push_back(s); } } } if (hasComplType) continue; for (SgStatement* start = st, *end = lst; start != end;) { SgStatement* next = start->lexNext(); if (strcmp(start->fileName(), st->fileName())) { start = next; continue; } if (start->variant() == DATA_DECL) { dataToTransfer.push_back(changeData(start->sunparse(), constSymVars, locVars)); start->deleteStmt(); } else if (start->variant() == SAVE_DECL) start->deleteStmt(); else if (start->variant() == VAR_DECL || start->variant() == VAR_DECL_90) { SgVarDeclStmt* vst = (SgVarDeclStmt*)start; for (int i = 0; i < vst->numberOfVars(); i++) { if (vst->initialValue(i)) { string data = " data " + vst->var(i)->lhs()->sunparse() + " / " + vst->initialValue(i)->sunparse() + " / \n"; dataToTransfer.push_back(changeData(data, constSymVars, locVars)); vst->clearInitialValue(i); } } SgExprListExp* attrsNoSave = new SgExprListExp(); bool needChange = false; for (int i = 0; i < vst->numberOfAttributes(); i++) { if (vst->attribute(i)->variant() != SAVE_OP) { attrsNoSave->append(vst->attribute(i)->copy()); } else needChange = true; } if (needChange) { SgVarDeclStmt* newVst; if (!attrsNoSave->length()) newVst = new SgVarDeclStmt(vst->varList()->copy(), *attrsNoSave, vst->type()->copy()); else newVst = new SgVarDeclStmt(vst->varList()->copy(), vst->type()->copy()); newVst->setlineNumber(vst->lineNumber()); newVst->setComments(vst->comments()); vst->replaceWithStmt(*newVst); } } start = next; } if (varsToTransfer.size()) transferSave(funcAddedVarsFuncs, varsToTransfer, dataToTransfer, func, func, func); } } //DEBUG /*static void printmbu(map>> modByUse) { for (auto& mod : modByUse) { printf("|%s| \n", mod.first.c_str()); for (auto& var : mod.second) printf("\t%s => %s\n", var.first->identifier(), var.second->identifier()); } }*/ static string makeName(SgSymbol* var, map>& modVarsToAdd, const set& useMod, const map>>& modByUse, const map>>& modByUseOnly) { string name = "", modName = OriginalSymbol(var)->scope()->symbol()->identifier(); SgSymbol* modS = OriginalSymbol(var)->scope()->symbol(); string varOrName = OriginalSymbol(var)->identifier(); size_t um = useMod.count(modName), mbu = modByUse.count(modName), mbuo = modByUseOnly.count(modName); if (um && !mbu && !mbuo) name = varOrName; else if (mbu) { for (auto& elem : modByUse.at(modName)) { if ((elem.second ? elem.second : elem.first)->identifier() == varOrName) { name = elem.first->identifier(); break; } } if (!name.length()) name = varOrName; } else if (mbuo) { for (auto& elem : modByUseOnly.at(modName)) { if ((elem.second ? elem.second : elem.first)->identifier() == varOrName) { name = elem.first->identifier(); break; } } if (!name.length()) { name = "m_" + modName + "_" + varOrName; if (!modVarsToAdd.count(modS)) modVarsToAdd[modS] = set(); modVarsToAdd[modS].insert(OriginalSymbol(var)); } } else { name = "m_" + modName + "_" + varOrName; if (!modVarsToAdd.count(modS)) modVarsToAdd[modS] = set(); modVarsToAdd[modS].insert(OriginalSymbol(var)); } return name; } static string getInterfaceBlock(SgStatement* func, const FuncParam& pars) { string oldFile = current_file->filename(); if (!func->switchToFile()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); auto copy = duplicateProcedure(func, NULL, false, false, false, true); const set ident(pars.identificators.begin(), pars.identificators.end()); //remove all exec SgStatement* st = copy->lexNext(); SgStatement* last = copy->lastNodeOfStmt(); vector toExtract; while (st != last) { if (isDVM_stat(st) || isSPF_stat(st)) { if (st->variant() != ACC_ROUTINE_DIR) { SgStatement* next = st->lexNext(); st->extractStmt(); st = next; } else st = st->lexNext(); } else if (isSgExecutableStatement(st)) { SgStatement* next = st->lastNodeOfStmt(); if (next != last) next = next->lexNext(); toExtract.push_back(st); st = next; } else st = st->lexNext(); } //remove unused declarations st = copy->lexNext(); while (st != last) { if (st->variant() == VAR_DECL || st->variant() == VAR_DECL_90 || st->variant() == DIM_STAT || st->variant() == INTENT_STMT) { SgExpression* list = st->expr(0); vector newList; while (list) { if (ident.find(list->lhs()->symbol()->identifier()) != ident.end()) newList.push_back(list->lhs()); list = list->rhs(); } if (newList.size() == 0) { SgStatement* next = st->lexNext(); toExtract.push_back(st); st = next; continue; } else st->setExpression(0, makeExprList(newList)); } else toExtract.push_back(st); if (st->variant() == CONTAINS_STMT) break; st = st->lexNext(); } for (auto& elem : toExtract) elem->extractStmt(); string retVal = copy->unparse(); if (SgFile::switchToFile(oldFile) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); return retVal; } static void insertInterface(SgStatement* func, const string& iface) { string oldFile = current_file->filename(); if (!func->switchToFile()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgStatement* st = func->lexNext(); SgStatement* last = func->lastNodeOfStmt(); while (st != last) { if (isSgExecutableStatement(st)) break; st = st->lexNext(); } SgStatement* ifaceBlock = new SgStatement(INTERFACE_STMT); addControlEndToStmt(ifaceBlock->thebif); ifaceBlock->setlineNumber(st->lineNumber()); ifaceBlock->setFileName(st->fileName()); st->insertStmtBefore(*ifaceBlock, *st->controlParent()); ifaceBlock->lastNodeOfStmt()->addComment(iface.c_str()); if (SgFile::switchToFile(oldFile) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } static void createInterfaceBlockForToCalls(FuncInfo* func) { for (auto& callTo : func->callsTo) { if (callTo->interfaceBlocks.find(func->funcName) == callTo->interfaceBlocks.end()) { callTo->interfaceBlocks[func->funcName] = func; insertInterface(callTo->funcPointer, getInterfaceBlock(func->funcPointer->GetOriginal(), func->funcParams)); } } } static void transferModule(map>& funcAddedVarsMods, set& allForChange, vector& varsToTransfer, FuncInfo* curFunc, FuncInfo* precFunc, set& funcForInterfaceAdd) { SgStatement* st = curFunc->funcPointer->GetOriginal(); map> modVarsToAdd; if (curFunc != precFunc) { if (SgFile::switchToFile(curFunc->fileName) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); set useMod; map>> modByUse; map>> modByUseOnly; if (!allForChange.count(curFunc)) { for (SgStatement* start = st; start != st->lastNodeOfStmt(); start = start->lexNext()) { if (isSgExecutableStatement(start)) break; if (start->variant() == CONTAINS_STMT) break; if (start != st && (start->variant() == PROC_HEDR || start->variant() == FUNC_HEDR)) break; fillUseStatement(start, useMod, modByUse, modByUseOnly); } } for (auto& callInfo : curFunc->callsFromDetailed) { auto& call = callInfo.pointerDetailCallsFrom; if (isSgFuncHedrStmt(precFunc->funcPointer->GetOriginal()) && call.second == FUNC_CALL) { SgFunctionCallExp* callExp = (SgFunctionCallExp*)call.first; if (callExp->funName()->identifier() == precFunc->funcName) { for (auto& var : varsToTransfer) { if (allForChange.count(curFunc)) callExp->addArg(*new SgVarRefExp(*var)); else { string name = makeName(var, modVarsToAdd, useMod, modByUse, modByUseOnly); SgSymbol* s = new SgSymbol(VARIABLE_NAME, name.c_str()); callExp->addArg(*new SgVarRefExp(*s)); } } } } else if (isSgProcHedrStmt(precFunc->funcPointer->GetOriginal()) && call.second == PROC_STAT) { SgCallStmt* callSt = (SgCallStmt*)call.first; if (callSt->name()->identifier() == precFunc->funcName) { for (auto& var : varsToTransfer) { if (allForChange.count(curFunc)) callSt->addArg(*new SgVarRefExp(*var)); else { string name = makeName(var, modVarsToAdd, useMod, modByUse, modByUseOnly); SgSymbol* s = new SgSymbol(VARIABLE_NAME, name.c_str()); callSt->addArg(*new SgVarRefExp(*s)); } } } } } } map> modVarsNeedToAdd; vector nextVarsToTransfer; if (!funcAddedVarsMods.count(curFunc)) funcAddedVarsMods[curFunc] = set(); for (auto& var : varsToTransfer) { if (!funcAddedVarsMods[curFunc].count(OriginalSymbol(var))) { SgSymbol* modS = OriginalSymbol(var)->scope()->symbol(); if (modVarsToAdd.count(modS) && modVarsToAdd[modS].count(OriginalSymbol(var))) { if (!modVarsNeedToAdd.count(modS)) modVarsNeedToAdd[modS] = set< SgSymbol*>(); modVarsNeedToAdd[modS].insert(OriginalSymbol(var)); } nextVarsToTransfer.push_back(var); funcAddedVarsMods[curFunc].insert(OriginalSymbol(var)); } } vector ifaces; ifaces.push_back(curFunc->funcPointer->GetOriginal()); findInterfaces(curFunc, ifaces); if (allForChange.count(curFunc)) { for (int i = 0; i < ifaces.size(); i++) { SgStatement* hedr = ifaces[i]; for (auto& var : nextVarsToTransfer) { if (i == 0) curFunc->funcParams.identificators.push_back(var->identifier()); ((SgProcHedrStmt*)(hedr))->AddArg(*new SgVarRefExp(var->copy())); hedr->lexNext()->deleteStmt(); vector varVec = vector(); varVec.push_back(var); SgStatement* decl = makeDeclaration(NULL, varVec); /*TODO:: add some other*/ if (var->attributes() && ALLOCATABLE_BIT) { bool isAuto = false; if (decl->expr(0)->lhs()->variant() == ARRAY_REF && decl->expr(0)->lhs()->lhs()) { for (SgExpression* e = decl->expr(0)->lhs()->lhs(); e; e = e->rhs()) { if (e->lhs()->variant() == DDOT && (e->lhs()->rhs() || e->lhs()->lhs()) || e->lhs()->variant() != DDOT) { isAuto = true; break; } } } if (!isAuto) { funcForInterfaceAdd.insert(curFunc); SgAttributeExp* a = new SgAttributeExp(ALLOCATABLE_OP); SgExprListExp* l = new SgExprListExp(); l->setLhs(a); ((SgVarDeclStmt*)decl)->addAttributeExpression(a); } } for (int i = 0; i < 3; i++) { SgExpression* e; if (e = decl->expr(i)) decl->setExpression(i, CalculateInteger(ReplaceConstant(e))); } SgStatement* firstExDec = NULL; for (SgStatement* start = hedr->lexNext(), *end = hedr->lastNodeOfStmt(); start != end; start = start->lexNext()) { if ((isSgExecutableStatement(start) || isSgDeclarationStatement(start)) && !strcmp(hedr->fileName(), start->fileName())) { firstExDec = start; break; } } checkNull(firstExDec, convertFileName(__FILE__).c_str(), __LINE__); decl->setlineNumber(firstExDec->lineNumber()); decl->setFileName(hedr->fileName()); firstExDec->insertStmtBefore(*decl, *(hedr)); } } for (auto& callFunc : curFunc->callsTo) transferModule(funcAddedVarsMods, allForChange, nextVarsToTransfer, callFunc, curFunc, funcForInterfaceAdd); } else { for (auto& mod : modVarsNeedToAdd) { SgSymbol modS = mod.first->copy(); SgExpression* onlyE = new SgExpression(ONLY_NODE); SgExprListExp* renameL = NULL; for (auto& var : mod.second) { string name = "m_" + string(modS.identifier()) + "_" + var->identifier(); SgSymbol varS = SgSymbol(VARIABLE_NAME, name.c_str()); SgExprListExp* el = new SgExprListExp(); SgVarRefExp* nvr = new SgVarRefExp(varS), * vr = new SgVarRefExp(var); SgExpression* renameE = new SgExpression(RENAME_NODE, nvr, vr); el->setLhs(renameE); el->setRhs(renameL); renameL = el; } onlyE->setLhs(renameL); SgStatement* useSt = new SgStatement(USE_STMT); useSt->setSymbol(modS); useSt->setExpression(0, onlyE); st->insertStmtAfter(*useSt, *st); } } } static void fillUsedVars(set& usedVars, SgExpression* exp) { if (exp) { if (exp->variant() == VAR_REF || exp->variant() == ARRAY_REF) usedVars.insert(exp->symbol()); fillUsedVars(usedVars, exp->lhs()); fillUsedVars(usedVars, exp->rhs()); } } void moduleTransfer(const map>& allFuncInfo) { FuncInfo* start = NULL; set allForChange; map> funcAddedVarsMods; set funcForInterfaceAdd; for (auto& byfile : allFuncInfo) { for (auto& func : byfile.second) if (func->isMain) start = func; } collectForChange(allForChange, start); allForChange.erase(start); for (auto& func : allForChange) { if (SgFile::switchToFile(func->fileName) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); SgStatement* st = func->funcPointer->GetOriginal(); vector varsToTransfer; map locVars; SgStatement* lst = st->lastNodeOfStmt(); SgSymbol* s, * sl; bool allSave = false; set< SgSymbol*> usedVars; for (SgStatement* start = st->lexNext(), *end = st->lastNodeOfStmt(); start != end;) { if (start->variant() == CONTAINS_STMT) break; SgStatement* next = start->lexNext(); if (start->variant() == USE_STMT) { SgExpression* onlyE = start->expr(0); if (onlyE) { SgExprListExp* renameL = NULL; for (SgExpression* ex = onlyE->lhs(); ex; ex = ex->rhs()) { if (ex->lhs()->variant() == RENAME_NODE) { SgSymbol* left = NULL, *right = NULL; if (ex->lhs()->lhs()->symbol()) left = ex->lhs()->lhs()->symbol(); if (ex->lhs()->rhs() && ex->lhs()->rhs()->symbol()) right = ex->lhs()->rhs()->symbol(); if (!(right && (right->variant() == VARIABLE_NAME) || left && (left->variant() == VARIABLE_NAME))) { SgExprListExp* el = new SgExprListExp(); el->setLhs(ex->lhs()); el->setRhs(renameL); renameL = el; } } } if (renameL) onlyE->setLhs(renameL); else start->deleteStmt(); } } if (isSgExecutableStatement(start)|| isSgDeclarationStatement(start)) for (int i = 0; i < 3; i++) fillUsedVars(usedVars, start->expr(i)); // if (start->variant() == IMPL_DECL) // start->deleteStmt(); start = next; } sl = lst->lexNext() ? lst->lexNext()->symbol() : NULL; for (s = st->symbol(); s != sl && s != NULL; s = s->next()) { if (OriginalSymbol(s)->scope()->variant() == MODULE_STMT && (s->variant() == VARIABLE_NAME) && usedVars.count(s)) { string newName = "m_" + string(OriginalSymbol(s)->scope()->symbol()->identifier()) + "_" + OriginalSymbol(s)->identifier(); locVars[s->identifier()] = newName; s->changeName(newName.c_str()); varsToTransfer.push_back(s); } } transferModule(funcAddedVarsMods, allForChange, varsToTransfer, func, func, funcForInterfaceAdd); } for (auto& func : funcForInterfaceAdd) createInterfaceBlockForToCalls(func); } static bool isIntrincis(const string& name) { static set intrinsicF; if (intrinsicF.size() == 0) { intrinsicF.insert(string("abs")); intrinsicF.insert(string("adjustl")); intrinsicF.insert(string("and")); intrinsicF.insert(string("any")); intrinsicF.insert(string("associated")); intrinsicF.insert(string("allocated")); intrinsicF.insert(string("amod")); intrinsicF.insert(string("aimax0")); intrinsicF.insert(string("ajmax0")); intrinsicF.insert(string("akmax0")); intrinsicF.insert(string("aimin0")); intrinsicF.insert(string("ajmin0")); intrinsicF.insert(string("akmin0")); intrinsicF.insert(string("amax1")); intrinsicF.insert(string("amax0")); intrinsicF.insert(string("amin1")); intrinsicF.insert(string("amin0")); intrinsicF.insert(string("aimag")); intrinsicF.insert(string("alog")); intrinsicF.insert(string("alog10")); intrinsicF.insert(string("asin")); intrinsicF.insert(string("asind")); intrinsicF.insert(string("asinh")); intrinsicF.insert(string("acos")); intrinsicF.insert(string("acosd")); intrinsicF.insert(string("acosh")); intrinsicF.insert(string("atan")); intrinsicF.insert(string("atand")); intrinsicF.insert(string("atanh")); intrinsicF.insert(string("atan2")); intrinsicF.insert(string("atan2d")); intrinsicF.insert(string("aint")); intrinsicF.insert(string("anint")); intrinsicF.insert(string("achar")); intrinsicF.insert(string("babs")); intrinsicF.insert(string("bbits")); intrinsicF.insert(string("bbset")); intrinsicF.insert(string("bdim")); intrinsicF.insert(string("biand")); intrinsicF.insert(string("bieor")); intrinsicF.insert(string("bior")); intrinsicF.insert(string("bixor")); intrinsicF.insert(string("btest")); intrinsicF.insert(string("bbtest")); intrinsicF.insert(string("bbclr")); intrinsicF.insert(string("bitest")); intrinsicF.insert(string("bjtest")); intrinsicF.insert(string("bktest")); intrinsicF.insert(string("bessel_j0")); intrinsicF.insert(string("bessel_j1")); intrinsicF.insert(string("bessel_jn")); intrinsicF.insert(string("bessel_y0")); intrinsicF.insert(string("bessel_y1")); intrinsicF.insert(string("bessel_yn")); intrinsicF.insert(string("bmod")); intrinsicF.insert(string("bnot")); intrinsicF.insert(string("bshft")); intrinsicF.insert(string("bshftc")); intrinsicF.insert(string("bsign")); intrinsicF.insert(string("cos")); intrinsicF.insert(string("ccos")); intrinsicF.insert(string("cdcos")); intrinsicF.insert(string("cosd")); intrinsicF.insert(string("cosh")); intrinsicF.insert(string("cotan")); intrinsicF.insert(string("cotand")); intrinsicF.insert(string("ceiling")); intrinsicF.insert(string("cexp")); intrinsicF.insert(string("conjg")); intrinsicF.insert(string("csqrt")); intrinsicF.insert(string("clog")); intrinsicF.insert(string("clog10")); intrinsicF.insert(string("cdlog")); intrinsicF.insert(string("cdlog10")); intrinsicF.insert(string("csin")); intrinsicF.insert(string("cabs")); intrinsicF.insert(string("cdabs")); intrinsicF.insert(string("cdexp")); intrinsicF.insert(string("cdsin")); intrinsicF.insert(string("cdsqrt")); intrinsicF.insert(string("cdtan")); intrinsicF.insert(string("cmplx")); intrinsicF.insert(string("char")); intrinsicF.insert(string("ctan")); intrinsicF.insert(string("cpu_time")); intrinsicF.insert(string("dim")); intrinsicF.insert(string("ddim")); intrinsicF.insert(string("dble")); intrinsicF.insert(string("dfloat")); intrinsicF.insert(string("dfloti")); intrinsicF.insert(string("dflotj")); intrinsicF.insert(string("dflotk")); intrinsicF.insert(string("dint")); intrinsicF.insert(string("dmax1")); intrinsicF.insert(string("dmin1")); intrinsicF.insert(string("dmod")); intrinsicF.insert(string("dprod")); intrinsicF.insert(string("dreal")); intrinsicF.insert(string("dsign")); intrinsicF.insert(string("dshiftl")); intrinsicF.insert(string("dshiftr")); intrinsicF.insert(string("dabs")); intrinsicF.insert(string("dsqrt")); intrinsicF.insert(string("dexp")); intrinsicF.insert(string("dlog")); intrinsicF.insert(string("dlog10")); intrinsicF.insert(string("dsin")); intrinsicF.insert(string("dcos")); intrinsicF.insert(string("dcosd")); intrinsicF.insert(string("dtan")); intrinsicF.insert(string("dtand")); intrinsicF.insert(string("dasin")); intrinsicF.insert(string("dasind")); intrinsicF.insert(string("dasinh")); intrinsicF.insert(string("dacos")); intrinsicF.insert(string("dacosd")); intrinsicF.insert(string("dacosh")); intrinsicF.insert(string("datan")); intrinsicF.insert(string("datand")); intrinsicF.insert(string("datanh")); intrinsicF.insert(string("datan2")); intrinsicF.insert(string("datan2d")); intrinsicF.insert(string("derf")); intrinsicF.insert(string("derfc")); intrinsicF.insert(string("dsind")); intrinsicF.insert(string("dsinh")); intrinsicF.insert(string("dcosh")); intrinsicF.insert(string("dcotan")); intrinsicF.insert(string("dcotand")); intrinsicF.insert(string("dtanh")); intrinsicF.insert(string("dnint")); intrinsicF.insert(string("dcmplx")); intrinsicF.insert(string("dconjg")); intrinsicF.insert(string("dimag")); intrinsicF.insert(string("exp")); intrinsicF.insert(string("erf")); intrinsicF.insert(string("erfc")); intrinsicF.insert(string("erfc_scaled")); intrinsicF.insert(string("etime")); intrinsicF.insert(string("float")); intrinsicF.insert(string("floati")); intrinsicF.insert(string("floatj")); intrinsicF.insert(string("floatk")); intrinsicF.insert(string("floor")); intrinsicF.insert(string("flush")); intrinsicF.insert(string("gamma")); intrinsicF.insert(string("habs")); intrinsicF.insert(string("hbclr")); intrinsicF.insert(string("hbits")); intrinsicF.insert(string("hbset")); intrinsicF.insert(string("hdim")); intrinsicF.insert(string("hiand")); intrinsicF.insert(string("hieor")); intrinsicF.insert(string("hior")); intrinsicF.insert(string("hixor")); intrinsicF.insert(string("hmod")); intrinsicF.insert(string("hnot")); intrinsicF.insert(string("hshft")); intrinsicF.insert(string("hshftc")); intrinsicF.insert(string("hsign")); intrinsicF.insert(string("htest")); intrinsicF.insert(string("huge")); intrinsicF.insert(string("hypot")); intrinsicF.insert(string("iiabs")); intrinsicF.insert(string("iargc")); intrinsicF.insert(string("iiand")); intrinsicF.insert(string("iibclr")); intrinsicF.insert(string("iibits")); intrinsicF.insert(string("iibset")); intrinsicF.insert(string("iidim")); intrinsicF.insert(string("iieor")); intrinsicF.insert(string("iior")); intrinsicF.insert(string("iishft")); intrinsicF.insert(string("iishftc")); intrinsicF.insert(string("iisign")); intrinsicF.insert(string("iixor")); intrinsicF.insert(string("int")); intrinsicF.insert(string("idint")); intrinsicF.insert(string("ifix")); intrinsicF.insert(string("idim")); intrinsicF.insert(string("isign")); intrinsicF.insert(string("index")); intrinsicF.insert(string("iabs")); intrinsicF.insert(string("ibits")); intrinsicF.insert(string("idnint")); intrinsicF.insert(string("ichar")); intrinsicF.insert(string("iachar")); intrinsicF.insert(string("isnan")); intrinsicF.insert(string("iand")); intrinsicF.insert(string("ior")); intrinsicF.insert(string("ibset")); intrinsicF.insert(string("ibclr")); intrinsicF.insert(string("ibchng")); intrinsicF.insert(string("ieor")); intrinsicF.insert(string("ilen")); intrinsicF.insert(string("imag")); intrinsicF.insert(string("imax0")); intrinsicF.insert(string("imax1")); intrinsicF.insert(string("imin0")); intrinsicF.insert(string("imin1")); intrinsicF.insert(string("imod")); intrinsicF.insert(string("inot")); intrinsicF.insert(string("isha")); intrinsicF.insert(string("ishc")); intrinsicF.insert(string("ishft")); intrinsicF.insert(string("ishftc")); intrinsicF.insert(string("ishl")); intrinsicF.insert(string("ixor")); intrinsicF.insert(string("jiabs")); intrinsicF.insert(string("jiand")); intrinsicF.insert(string("jibclr")); intrinsicF.insert(string("jibits")); intrinsicF.insert(string("jibset")); intrinsicF.insert(string("jidim")); intrinsicF.insert(string("jieor")); intrinsicF.insert(string("jior")); intrinsicF.insert(string("jishft")); intrinsicF.insert(string("jishftc")); intrinsicF.insert(string("jisign")); intrinsicF.insert(string("jixor")); intrinsicF.insert(string("jmax0")); intrinsicF.insert(string("jmax1")); intrinsicF.insert(string("jmin0")); intrinsicF.insert(string("jmin1")); intrinsicF.insert(string("jmod")); intrinsicF.insert(string("jnot")); intrinsicF.insert(string("kiabs")); intrinsicF.insert(string("kiand")); intrinsicF.insert(string("kibclr")); intrinsicF.insert(string("kibits")); intrinsicF.insert(string("kibset")); intrinsicF.insert(string("kidim")); intrinsicF.insert(string("kieor")); intrinsicF.insert(string("kior")); intrinsicF.insert(string("kishft")); intrinsicF.insert(string("kishftc")); intrinsicF.insert(string("kisign")); intrinsicF.insert(string("kmax0")); intrinsicF.insert(string("kmax1")); intrinsicF.insert(string("kmin0")); intrinsicF.insert(string("kmin1")); intrinsicF.insert(string("kmod")); intrinsicF.insert(string("knot")); intrinsicF.insert(string("len")); intrinsicF.insert(string("len_trim")); intrinsicF.insert(string("lge")); intrinsicF.insert(string("lgt")); intrinsicF.insert(string("lle")); intrinsicF.insert(string("llt")); intrinsicF.insert(string("log_gamma")); intrinsicF.insert(string("log")); intrinsicF.insert(string("log10")); intrinsicF.insert(string("lshft")); intrinsicF.insert(string("lshift")); intrinsicF.insert(string("max")); intrinsicF.insert(string("max0")); intrinsicF.insert(string("max1")); intrinsicF.insert(string("merge_bits")); intrinsicF.insert(string("min")); intrinsicF.insert(string("minval")); intrinsicF.insert(string("maxval")); intrinsicF.insert(string("min0")); intrinsicF.insert(string("min1")); intrinsicF.insert(string("mod")); intrinsicF.insert(string("modulo")); intrinsicF.insert(string("not")); intrinsicF.insert(string("nint")); intrinsicF.insert(string("null")); intrinsicF.insert(string("or")); intrinsicF.insert(string("popcnt")); intrinsicF.insert(string("poppar")); intrinsicF.insert(string("random_number")); intrinsicF.insert(string("real")); intrinsicF.insert(string("reshape")); intrinsicF.insert(string("present")); intrinsicF.insert(string("repeat")); intrinsicF.insert(string("rshft")); intrinsicF.insert(string("rshift")); intrinsicF.insert(string("sign")); intrinsicF.insert(string("size")); intrinsicF.insert(string("scan")); intrinsicF.insert(string("sizeof")); intrinsicF.insert(string("sngl")); intrinsicF.insert(string("sqrt")); intrinsicF.insert(string("sin")); intrinsicF.insert(string("sind")); intrinsicF.insert(string("sinh")); intrinsicF.insert(string("shifta")); intrinsicF.insert(string("shiftl")); intrinsicF.insert(string("shiftr")); intrinsicF.insert(string("sum")); intrinsicF.insert(string("tan")); intrinsicF.insert(string("tand")); intrinsicF.insert(string("tanh")); intrinsicF.insert(string("tiny")); intrinsicF.insert(string("trailz")); intrinsicF.insert(string("trim")); intrinsicF.insert(string("xor")); intrinsicF.insert(string("zabs")); intrinsicF.insert(string("zcos")); intrinsicF.insert(string("zexp")); intrinsicF.insert(string("zlog")); intrinsicF.insert(string("zsin")); intrinsicF.insert(string("zsqrt")); intrinsicF.insert(string("ztan")); } if (intrinsicF.find(name) != intrinsicF.end()) return true; return false; }