void BasicProgmemTransform::transformFunction(SgFunctionDeclaration *func) { setupCharBufferForFunction(func); Rose_STL_Container<SgNode *> funcCalls = NodeQuery::querySubTree(func, V_SgFunctionCallExp); for(auto &funcCall: funcCalls) { int startPos = 0; SgFunctionCallExp *fcall = isSgFunctionCallExp(funcCall); Function callee(fcall); std::string orig = callee.get_name().getString(); std::string replacement = getReplacementName(orig); bool arduinoP = isArduinoProgmemSafeFunction(callee); SgExpressionPtrList params = fcall->get_args()->get_expressions(); param_pos_list progmemPositions = getPositionsToIgnore(orig); //TODO: figure out how to wrap with macro // for(auto &expr: params) { for(int index = 0; index < params.size(); index++){ SgExpression *expr = params[index]; SgVarRefExp* var = isSgVarRefExp(expr); if(var == NULL) { continue;} if(isVarDeclToRemove(var)) { if(arduinoP) { castProgmemParams(var); } else if(progmemPositions.find(index) == progmemPositions.end()) { loadProgmemStringsIntoBuffer(fcall, var, startPos); } } } if(replacement != "") { loadReplacewithProgmemFunction(fcall, replacement); } } }
int BasicProgmemTransform::getBuffersizeNeededForFunction(SgFunctionDeclaration *func) { int maxSize = 0; Rose_STL_Container<SgNode *> funcCalls = NodeQuery::querySubTree(func, V_SgFunctionCallExp); for(auto &funcCall: funcCalls) { SgFunctionCallExp *fcall = isSgFunctionCallExp(funcCall); Function callee(fcall); // printf("function called: %s\n", callee.get_name().str()); if(isArduinoProgmemSafeFunction(callee)) { continue; } param_pos_list ignoredPositions = getPositionsToIgnore(callee.get_name().getString()); SgExpressionPtrList params = fcall->get_args()->get_expressions(); int size = 0; for(int pos = 0; pos < params.size(); pos++) { if(ignoredPositions.find(pos) != ignoredPositions.end()) { continue; } SgVarRefExp* var = isSgVarRefExp(params[pos]); if(var) { SgInitializedName *initName = var->get_symbol()->get_declaration(); if(isVarDeclToRemove(initName)) { SgExpression *rhs = getRHSOfVarDecl(initName); if(rhs && isSgStringVal(rhs)) { size += isSgStringVal(rhs)->get_value().size() + 1; } } } } if(size > maxSize) { maxSize = size; } } return maxSize; }
// given a function call, sets argParamMap to map all simple arguments to this function to their // corresponding parameters void FunctionState::setArgParamMap(SgFunctionCallExp* call, map<varID, varID>& argParamMap) { Function func(call); SgExpressionPtrList args = call->get_args()->get_expressions(); //SgInitializedNamePtrList params = funcArgToParamByRef(call); SgInitializedNamePtrList params = func.get_params(); ROSE_ASSERT(args.size() == params.size()); //cout << "setArgParamMap() #args="<<args.size()<<" #params="<<params.size()<<"\n"; // the state of the callee's variables at the call site SgExpressionPtrList::iterator itA; SgInitializedNamePtrList::iterator itP; for(itA = args.begin(), itP = params.begin(); itA!=args.end() && itP!=params.end(); itA++, itP++) { //cout << " itA="<<(*itA)->unparseToString()<<" itP="<<(*itP)->unparseToString()<<" isValid="<<varID::isValidVarExp(*itA)<<"\n"; /*if(varID::isValidVarExp(*itA)) { varID arg(*itA); varID param(*itP); argParamMap[arg] = param; }*/ varID arg = SgExpr2Var(*itA); varID param(*itP); argParamMap[arg] = param; } }
//Generates SSA form numbers for the variables contained in *ex and attaches them as AstValueAttributes to the related SgNodes //Assumption: *ex is located in in the inTrueBranch branch of the if node labeled *condLabel (These two arguments are required to generate the SSA form numbers) void SSAGenerator::processSgExpression(SgExpression* ex, Label* condLabel, bool inTrueBranch) { SgIntVal* intVal = dynamic_cast<SgIntVal*>(ex); SgMinusOp* minusOp = dynamic_cast<SgMinusOp*>(ex); SgVarRefExp* varRef = dynamic_cast<SgVarRefExp*>(ex); SgBinaryOp* binOp = dynamic_cast<SgBinaryOp*>(ex); SgFunctionCallExp* funcCall = dynamic_cast<SgFunctionCallExp*>(ex); if(intVal) //Int value { //Nothing needs to be done; Case is listed here to have a collection of all expected cases } else if(minusOp) { processSgExpression(minusOp->get_operand(), condLabel, inTrueBranch); } else if(varRef) //Reference to variable that is NOT on the left hand side of an assignment { //Assign number to variable string varName = varRef->get_symbol()->get_name().getString(); int varNumber = currentNumber(varName, condLabel, inTrueBranch); logger[Sawyer::Message::DEBUG] << "Current number for variable " << varName << ": " << varNumber << endl; AstValueAttribute<int>* varNumberAtt = new AstValueAttribute<int>(varNumber); varRef->setAttribute("SSA_NUMBER", varNumberAtt); } else if(binOp) //Binary operation { SgExpression* lhs = binOp->get_lhs_operand(); SgExpression* rhs = binOp->get_rhs_operand(); //Process right hand side first processSgExpression(rhs, condLabel, inTrueBranch); //Process left hand side second SgAssignOp* assignOp = dynamic_cast<SgAssignOp*>(binOp); if(assignOp) //Assignment to a variable { //Assign new number to that variable SgVarRefExp* lhsVarRef = dynamic_cast<SgVarRefExp*>(lhs); assert(lhsVarRef != NULL); processAssignmentTo(lhsVarRef, condLabel, inTrueBranch); } else //Arithmetic operation or boolean operation (or something unexpected) { processSgExpression(lhs, condLabel, inTrueBranch); } } else if(funcCall) //Call to a function //RERS specific; Only two function call types are supported: //(1) scanf("%d",&...); //(2) __VERIFIER_error(RERSVerifierErrorNumber); The artificial bool variable RERSErrorOccured has to be updated { string funcName = funcCall->getAssociatedFunctionSymbol()->get_name().getString(); logger[Sawyer::Message::DEBUG] << "Call to function: " << funcName << endl; if(funcName == "scanf") //(1) { SgExprListExp* funcArgs = funcCall->get_args(); SgExpressionPtrList funcArgsPtrs = funcArgs->get_expressions(); SgExpressionPtrList::iterator i = funcArgsPtrs.begin(); while(i != funcArgsPtrs.end()) { SgAddressOfOp* addrOp = dynamic_cast<SgAddressOfOp*>(*i); if(addrOp) { SgVarRefExp* varRef = dynamic_cast<SgVarRefExp*>(addrOp->get_operand()); if(varRef) { processAssignmentTo(varRef, condLabel, inTrueBranch); } else logger[Sawyer::Message::DEBUG] << "FOUND NO REFERENCE TO VARIABLE" << endl; } i++; } } else if(funcName == "__VERIFIER_error" && prepareReachabilityAnalysisZ3) { SgExprListExp* funcArgs = funcCall->get_args(); SgExpressionPtrList funcArgsPtrs = funcArgs->get_expressions(); assert(funcArgsPtrs.size() == 1); SgExpression* argument = *funcArgsPtrs.begin(); SgIntVal* intArgument = dynamic_cast<SgIntVal*>(argument); assert(intArgument != NULL); if(intArgument->get_value() == RERSVerifierErrorNumber) //(2) { int RERSErrorOccuredNumber = nextNumber("RERSErrorOccured", condLabel, inTrueBranch); logger[Sawyer::Message::DEBUG] << "Next number for variable RERSErrorOccured: " << RERSErrorOccuredNumber << endl; AstValueAttribute<int>* numberAtt = new AstValueAttribute<int>(RERSErrorOccuredNumber); funcCall->setAttribute("SSA_NUMBER", numberAtt); } } else logger[Sawyer::Message::DEBUG] << "Ignoring function call" << endl; } else //Unexpected { logger[Sawyer::Message::ERROR] << "ERROR: SgExpression could not be handled: " << ex->class_name() << endl; assert(false); } }
void Fortran_to_C::translateArraySubscript(SgPntrArrRefExp* pntrArrRefExp) { // get lhs operand SgVarRefExp* arrayName = isSgVarRefExp(pntrArrRefExp->get_lhs_operand()); SgExpression* baseExp = isSgExpression(arrayName); // get array symbol SgVariableSymbol* arraySymbol = arrayName->get_symbol(); // get array type and dim_info SgArrayType* arrayType = isSgArrayType(arraySymbol->get_type()); ROSE_ASSERT(arrayType); SgExprListExp* dimInfo = arrayType->get_dim_info(); // get rhs operand SgExprListExp* arraySubscript = isSgExprListExp(pntrArrRefExp->get_rhs_operand()); if(arrayType->findBaseType()->variantT() == V_SgTypeString) { arraySubscript->prepend_expression(buildIntVal(1)); } /* No matter it is single or multi dimensional array, pntrArrRefExp always has a child, SgExprListExp, to store the subscript information. */ if(arraySubscript != NULL) { // get the list of subscript SgExpressionPtrList subscriptExprList = arraySubscript->get_expressions(); // get the list of dimension inforamtion from array definition. SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions(); // Create new SgExpressionPtrList for the linearalized array subscript. SgExpressionPtrList newSubscriptExprList; // rank info has to match between subscripts and dim_info ROSE_ASSERT(arraySubscript->get_expressions().size() == dimInfo->get_expressions().size()); if(subscriptExprList.size() == 1) { Rose_STL_Container<SgExpression*>::iterator j1 = subscriptExprList.begin(); Rose_STL_Container<SgExpression*>::iterator j2 = dimExpressionPtrList.begin(); SgExpression* newIndexExp = get0basedIndex(*j1, *j2); pntrArrRefExp->set_rhs_operand(newIndexExp); } else { Rose_STL_Container<SgExpression*>::reverse_iterator j1 = subscriptExprList.rbegin(); Rose_STL_Container<SgExpression*>::reverse_iterator j2 = dimExpressionPtrList.rbegin(); SgExpression* newIndexExp = get0basedIndex(*j1, *j2); SgPntrArrRefExp* newPntrArrRefExp = buildPntrArrRefExp(baseExp, newIndexExp); baseExp->set_parent(newPntrArrRefExp); j1 = j1 + 1; j2 = j2 + 1; for(; j1< (subscriptExprList.rend()-1); ++j1, ++j2) { SgExpression* newIndexExp = get0basedIndex(*j1, *j2); baseExp = isSgExpression(newPntrArrRefExp); newPntrArrRefExp = buildPntrArrRefExp(baseExp, newIndexExp); baseExp->set_parent(newPntrArrRefExp); } newIndexExp = get0basedIndex(*j1, *j2); pntrArrRefExp->set_lhs_operand(newPntrArrRefExp); pntrArrRefExp->set_rhs_operand(newIndexExp); newIndexExp->set_parent(pntrArrRefExp); } } }
void mlmTransform::transformCallExp(SgCallExpression* callExp) { ROSE_ASSERT(callExp); SgFunctionRefExp* funcName = isSgFunctionRefExp(callExp->get_function()); if(!funcName) return; SgExprListExp* funcArgList = callExp->get_args(); SgExpressionPtrList argList = funcArgList->get_expressions(); SgScopeStatement* scope = getScope(callExp); //cout << funcName->get_symbol()->get_name() << endl; /** if it is malloc, search for the mlm attribute and append the memory level **/ if(strncmp("malloc",funcName->get_symbol()->get_name().str(),6) == 0) { if(argList.size() != 1) return; SgExprListExp* funcArgList = callExp->get_args(); // check if LHS of malloc has an attribute assigned SgNode* parentNode = callExp->get_parent(); // parent node can be a casting expression if(isSgCastExp(parentNode)) { parentNode = parentNode->get_parent(); } // the mlm attribute AstAttribute* attr = NULL; // So far we spot two candidates for parentNode that we need to transform if(isSgAssignOp(parentNode)) { SgAssignOp* assignOp = isSgAssignOp(parentNode); SgExpression* lhs = isSgExpression(assignOp->get_lhs_operand()); if(!isSgVarRefExp(lhs)) { //cout << "lhs:" << assignOp->get_lhs_operand()->class_name() << endl; // if pointer is packaged inside a struct, then we need to look down in lhs. if(isSgDotExp(lhs)) { lhs = isSgDotExp(lhs)->get_rhs_operand(); } } SgVarRefExp* lhsVarRef = isSgVarRefExp(lhs); ROSE_ASSERT(lhsVarRef); SgSymbol* symbol = lhsVarRef->get_symbol(); ROSE_ASSERT(symbol); //retrieve the attribute from symbol attr = symbol->getAttribute("mlmAttribute"); //cout << "LHS symbol name: " << symbol->get_name() << endl; } else if(isSgAssignInitializer(parentNode)) { SgInitializedName* initName = isSgInitializedName(parentNode->get_parent()); ROSE_ASSERT(initName); SgSymbol* symbol = initName->get_symbol_from_symbol_table(); if(!symbol) return; ROSE_ASSERT(symbol); //retrieve the attribute from symbol attr = symbol->getAttribute("mlmAttribute"); //cout << "Initialized symbol name: " << symbol->get_name() << endl; } else { // do nothing because no attribute assigned or we always set to default } // if there is a mlm attribute attached to the symbol, then create new malloc if(attr) { mlmAttribute* mlmAttr = dynamic_cast<mlmAttribute*> (attr); SgExprListExp* funcArgList = callExp->get_args(); funcArgList->append_expression(buildIntVal(mlmAttr->getMemType())); replaceExpression(callExp, buildFunctionCallExp("mlm_malloc",deepCopy(callExp->get_type()),deepCopy(funcArgList),getScope(callExp))); } } else if(strncmp("memcpy",funcName->get_symbol()->get_name().str(),6) == 0) { // cout << "replacing memcpy" << endl; if(argList.size() != 3) return; Rose_STL_Container<SgNode*> varList = NodeQuery::querySubTree(funcArgList, V_SgVarRefExp); SgVarRefExp* dst = isSgVarRefExp(varList[0]); SgVarRefExp* src = isSgVarRefExp(varList[1]); AstAttribute* attrDst = dst->get_symbol()->getAttribute("mlmAttribute"); AstAttribute* attrSrc = src->get_symbol()->getAttribute("mlmAttribute"); mlmAttribute* mlmAttrDst = dynamic_cast<mlmAttribute*>(attrDst); mlmAttribute* mlmAttrSrc = dynamic_cast<mlmAttribute*>(attrSrc); // if((mlmAttrDst && !mlmAttrSrc) || (mlmAttrDst && mlmAttrSrc && (mlmAttrDst->getMemType() < mlmAttrDst->getMemType()))) // { // replaceExpression(callExp, buildFunctionCallExp("mlm_memcpy",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope),true); // DeletepragmasList2.push_back(callExp); // } // // else if((!mlmAttrDst && mlmAttrSrc) || (mlmAttrDst && mlmAttrSrc && (mlmAttrDst->getMemType() > mlmAttrDst->getMemType()))) // 09/30/14 Following Simon's suggestion, we always insert wait for the mlm_memcpy // { string tagName = generateUniqueVariableName(scope,"copy_tag"); SgVariableDeclaration* newDecl = buildVariableDeclaration(tagName, buildOpaqueType("mlm_Tag",getGlobalScope(callExp)), buildAssignInitializer(buildFunctionCallExp("mlm_memcpy",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope))); SgExprStatement* waitStmt = buildFunctionCallStmt("mlm_waitComplete", buildVoidType(), buildExprListExp(buildVarRefExp(tagName,scope)), scope); insertStatement(getEnclosingStatement(callExp),newDecl,true); insertStatement(getEnclosingStatement(callExp),waitStmt,true); removeStatement(getEnclosingStatement(callExp)); // } } else if(strncmp("free",funcName->get_symbol()->get_name().str(),4) == 0) { // cout << "replacing free" << endl; if(argList.size() != 1) return; SgExpression* varExp = isSgExpression(argList[0]); //cout << "exp:" << varExp->class_name() << endl; if(!isSgVarRefExp(varExp)) { if(isSgCastExp(varExp)) { varExp = isSgCastExp(varExp)->get_operand_i(); } // if pointer is packaged inside a struct, then we need to look down in lhs. if(isSgDotExp(varExp)) { varExp = isSgDotExp(varExp)->get_rhs_operand(); } } SgVarRefExp* varRef = isSgVarRefExp(varExp); ROSE_ASSERT(varRef); AstAttribute* attr = varRef->get_symbol()->getAttribute("mlmAttribute"); if(attr) { replaceExpression(callExp, buildFunctionCallExp("mlm_free",deepCopy(callExp->get_type()),deepCopy(funcArgList),scope),false); } } }