// 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; } }
void Fortran_to_C::linearizeArrayDeclaration(SgArrayType* originalArrayType) { // Get dim_info SgExprListExp* dimInfo = originalArrayType->get_dim_info(); // Get dim list SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions(); SgExpression* newDimExpr; Rose_STL_Container<SgExpression*>::iterator j = dimExpressionPtrList.begin(); while(j != dimExpressionPtrList.end()) { SgExpression* indexExpression = getFortranDimensionSize(*j); /* Total array size is equal to the multiplication of all individual dimension size. */ if(j != dimExpressionPtrList.begin()){ newDimExpr = buildMultiplyOp(newDimExpr, indexExpression); } else /* If it's first dimension, array size is just its first dimension size. */ { newDimExpr = indexExpression; } ++j; } // calling set_index won't replace the default index expression. I have to delete the default manually. removeList.push_back(originalArrayType->get_index()); originalArrayType->set_index(newDimExpr); newDimExpr->set_parent(originalArrayType); originalArrayType->set_rank(1); }
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; }
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); } } }
/*! * \author Markus Schordan * \date 2014. */ void SPRAY::LVTransferFunctions::transferFunctionCall(Label lab, SgFunctionCallExp* callExp, SgExpressionPtrList& arguments,Lattice& element0) { LVLattice* element1=dynamic_cast<LVLattice*>(&element0); ROSE_ASSERT(element1); LVLattice& element=*element1; // uses and defs in argument-expressions for(SgExpressionPtrList::iterator i=arguments.begin();i!=arguments.end();++i) { transferExpression(lab,*i,element); } }
/*! * \author Markus Schordan * \date 2014. */ void SPRAY::IntervalTransferFunctions::transferFunctionCall(Label lab, SgFunctionCallExp* callExp, SgExpressionPtrList& arguments,Lattice& element) { // uses and defs in argument-expressions int paramNr=0; IntervalPropertyState* ips=dynamic_cast<IntervalPropertyState*>(&element); for(SgExpressionPtrList::iterator i=arguments.begin();i!=arguments.end();++i) { // TODO: add one variable $paramX for each parameter to the state and bind it to the value of the argument VariableId paramId=getParameterVariableId(paramNr); ips->addVariable(paramId); ips->setVariable(paramId,evalExpression(lab,*i,element)); } }
/*! * \author Markus Schordan * \date 2013. */ void RDTransferFunctions::transferFunctionCall(Label lab, SgFunctionCallExp* callExp, SgExpressionPtrList& arguments,Lattice& element0) { RDLattice& element=dynamic_cast<RDLattice&>(element0); // uses and defs in argument-expressions int paramNr=0; for(SgExpressionPtrList::iterator i=arguments.begin();i!=arguments.end();++i) { VariableId paramId=getParameterVariableId(paramNr); transferExpression(lab,*i,element); // insert parameter variable element.insertPair(lab,paramId); paramNr++; } }
// given a function call, sets argParamMap to map all the parameters of this function to their // corresponding simple arguments, if those arguments are passed by reference void FunctionState::setParamArgByRefMap(SgFunctionCallExp* call, map<varID, varID>& paramArgByRefMap) { Function func(call); SgExpressionPtrList args = call->get_args()->get_expressions(); SgInitializedNamePtrList params = func.get_params(); SgExpressionPtrList::iterator itArgs; SgInitializedNamePtrList::iterator itParams; //cout << " #params="<<params.size()<<" #args="<<args.size()<<"\n"; for(itParams = params.begin(), itArgs = args.begin(); itParams!=params.end() && itArgs!=args.end(); itParams++, itArgs++) { /*SgType* typeParam = (*itParams)->get_type(); SgType* typeArg = cfgUtils::unwrapCasts((*itArgs))->get_type();*/ /*printf("FunctionState::setParamArgByRefMap() *itArgs=<%s | %s> isValidVar=%d\n", (*itArgs)->unparseToString().c_str(), (*itArgs)->class_name().c_str(), varID::isValidVarExp(*itArgs)); printf(" typeArg=<%s | %s>\n", typeArg->unparseToString().c_str(), typeArg->class_name().c_str()); printf(" itParams=<%s | %s>\n", (*itParams)->unparseToString().c_str(), (*itParams)->class_name().c_str()); printf(" typeParam=<%s | %s> isReference=%d\n", typeParam->unparseToString().c_str(), typeParam->class_name().c_str(), isSgReferenceType(typeParam));*/ /* // if the argument is a named variable AND if(varID::isValidVarExp(*itArgs) && // if the argument has an array type, it's contents will be passed by reference OR ((isSgArrayType(typeArg) || isSgPointerType(typeArg)) || // if the argument is a regular variable, by the parameter has a reference type, // or the variable is being passed via a pointer, the variable must be passed by reference isSgReferenceType(typeParam))) { varID argVar(*itArgs); varID paramVar(*itParams); // add this mapping paramArgByRefMap[paramVar] = argVar; }*/ varID argVar = SgExpr2Var(*itArgs); varID paramVar(*itParams); // add this mapping paramArgByRefMap[paramVar] = argVar; /* // if the argument is a non-array variable being passed via a pointer else if(isSgAddressOfOp(*itArgs) && SgPointerType(typeArg) && SgPointerType(typeParam)*/ } }
void Fortran_to_C::translateArrayDeclaration(SgArrayType* originalArrayType) { // Get dim_info SgExprListExp* dimInfo = originalArrayType->get_dim_info(); // Get dim list SgExpressionPtrList dimExpressionPtrList = dimInfo->get_expressions(); // Get array base_type SgType* baseType = originalArrayType->get_base_type(); Rose_STL_Container<SgExpression*>::iterator j = dimExpressionPtrList.begin(); SgExpression* indexExpression = getFortranDimensionSize(*j); //std::cout << "array rank:" << originalArrayType->get_rank() << std::endl; if(originalArrayType->get_rank() == 1) { originalArrayType->set_base_type(baseType); originalArrayType->set_index(indexExpression); indexExpression->set_parent(originalArrayType); constantFolding(indexExpression); } else { SgArrayType* newType = buildArrayType(baseType,indexExpression); baseType->set_parent(newType); j = j + 1; for(; j< (dimExpressionPtrList.end()-1); ++j) { indexExpression = getFortranDimensionSize(*j); baseType = newType; newType = buildArrayType(baseType,indexExpression); baseType->set_parent(newType); } j = dimExpressionPtrList.end()-1; indexExpression = getFortranDimensionSize(*j); originalArrayType->set_base_type(newType); originalArrayType->set_index(indexExpression); indexExpression->set_parent(originalArrayType); } }
bool expressionTreeEqualStar(const SgExpressionPtrList& as, const SgExpressionPtrList& bs) { SgExpressionPtrList::const_iterator i, j; for (i = as.begin(), j = bs.begin(); i != as.end() && j != bs.end(); ++i, ++j) if (!expressionTreeEqual(*i, *j)) return false; if (i != as.end() || j != bs.end()) return false; // Mismatched lengths return true; }
// Main inliner code. Accepts a function call as a parameter, and inlines // only that single function call. Returns true if it succeeded, and false // otherwise. The function call must be to a named function, static member // function, or non-virtual non-static member function, and the function // must be known (not through a function pointer or member function // pointer). Also, the body of the function must already be visible. // Recursive procedures are handled properly (when allowRecursion is set), by // inlining one copy of the procedure into itself. Any other restrictions on // what can be inlined are bugs in the inliner code. bool doInline(SgFunctionCallExp* funcall, bool allowRecursion) { #if 0 // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag. ROSE_ASSERT(funcall != NULL); ROSE_ASSERT(funcall->get_parent() != NULL); SgGlobal* globalScope = TransformationSupport::getGlobalScope(funcall); ROSE_ASSERT(globalScope != NULL); // checkTransformedFlagsVisitor(funcall->get_parent()); checkTransformedFlagsVisitor(globalScope); #endif SgExpression* funname = funcall->get_function(); SgExpression* funname2 = isSgFunctionRefExp(funname); SgDotExp* dotexp = isSgDotExp(funname); SgArrowExp* arrowexp = isSgArrowExp(funname); SgExpression* thisptr = 0; if (dotexp || arrowexp) { funname2 = isSgBinaryOp(funname)->get_rhs_operand(); if (dotexp) { SgExpression* lhs = dotexp->get_lhs_operand(); // FIXME -- patch this into p_lvalue bool is_lvalue = lhs->get_lvalue(); if (isSgInitializer(lhs)) is_lvalue = false; if (!is_lvalue) { SgAssignInitializer* ai = SageInterface::splitExpression(lhs); ROSE_ASSERT (isSgInitializer(ai->get_operand())); #if 1 printf ("ai = %p ai->isTransformation() = %s \n",ai,ai->isTransformation() ? "true" : "false"); #endif SgInitializedName* in = isSgInitializedName(ai->get_parent()); ROSE_ASSERT (in); removeRedundantCopyInConstruction(in); lhs = dotexp->get_lhs_operand(); // Should be a var ref now } thisptr = new SgAddressOfOp(SgNULL_FILE, lhs); } else if (arrowexp) { thisptr = arrowexp->get_lhs_operand(); } else { assert (false); } } if (!funname2) { // std::cout << "Inline failed: not a call to a named function" << std::endl; return false; // Probably a call through a fun ptr } SgFunctionSymbol* funsym = 0; if (isSgFunctionRefExp(funname2)) funsym = isSgFunctionRefExp(funname2)->get_symbol(); else if (isSgMemberFunctionRefExp(funname2)) funsym = isSgMemberFunctionRefExp(funname2)->get_symbol(); else assert (false); assert (funsym); if (isSgMemberFunctionSymbol(funsym) && isSgMemberFunctionSymbol(funsym)->get_declaration()->get_functionModifier().isVirtual()) { // std::cout << "Inline failed: cannot inline virtual member functions" << std::endl; return false; } SgFunctionDeclaration* fundecl = funsym->get_declaration(); fundecl = fundecl ? isSgFunctionDeclaration(fundecl->get_definingDeclaration()) : NULL; SgFunctionDefinition* fundef = fundecl ? fundecl->get_definition() : NULL; if (!fundef) { // std::cout << "Inline failed: no definition is visible" << std::endl; return false; // No definition of the function is visible } if (!allowRecursion) { SgNode* my_fundef = funcall; while (my_fundef && !isSgFunctionDefinition(my_fundef)) { // printf ("Before reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); my_fundef = my_fundef->get_parent(); ROSE_ASSERT(my_fundef != NULL); // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); } // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); assert (isSgFunctionDefinition(my_fundef)); if (isSgFunctionDefinition(my_fundef) == fundef) { std::cout << "Inline failed: trying to inline a procedure into itself" << std::endl; return false; } } SgVariableDeclaration* thisdecl = 0; SgName thisname("this__"); thisname << ++gensym_counter; SgInitializedName* thisinitname = 0; if (isSgMemberFunctionSymbol(funsym) && !fundecl->get_declarationModifier().get_storageModifier().isStatic()) { assert (thisptr != NULL); SgType* thisptrtype = thisptr->get_type(); const SgSpecialFunctionModifier& specialMod = funsym->get_declaration()->get_specialFunctionModifier(); if (specialMod.isConstructor()) { SgFunctionType* ft = funsym->get_declaration()->get_type(); ROSE_ASSERT (ft); SgMemberFunctionType* mft = isSgMemberFunctionType(ft); ROSE_ASSERT (mft); SgType* ct = mft->get_class_type(); thisptrtype = new SgPointerType(ct); } SgConstVolatileModifier& thiscv = fundecl->get_declarationModifier().get_typeModifier().get_constVolatileModifier(); // if (thiscv.isConst() || thiscv.isVolatile()) { FIXME thisptrtype = new SgModifierType(thisptrtype); isSgModifierType(thisptrtype)->get_typeModifier().get_constVolatileModifier() = thiscv; // } // cout << thisptrtype->unparseToString() << " --- " << thiscv.isConst() << " " << thiscv.isVolatile() << endl; SgAssignInitializer* assignInitializer = new SgAssignInitializer(SgNULL_FILE, thisptr); assignInitializer->set_endOfConstruct(SgNULL_FILE); #if 1 printf ("before new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false"); #endif thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, assignInitializer); #if 1 printf ("(after new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false"); #endif thisdecl->set_endOfConstruct(SgNULL_FILE); thisdecl->get_definition()->set_endOfConstruct(SgNULL_FILE); thisdecl->set_definingDeclaration(thisdecl); thisinitname = (thisdecl->get_variables()).back(); //thisinitname = lastElementOfContainer(thisdecl->get_variables()); // thisinitname->set_endOfConstruct(SgNULL_FILE); assignInitializer->set_parent(thisinitname); markAsTransformation(assignInitializer); // printf ("Built new SgVariableDeclaration #1 = %p \n",thisdecl); // DQ (6/23/2006): New test ROSE_ASSERT(assignInitializer->get_parent() != NULL); } // Get the list of actual argument expressions from the function call, which we'll later use to initialize new local // variables in the inlined code. We need to detach the actual arguments from the AST here since we'll be reattaching // them below (otherwise we would violate the invariant that the AST is a tree). SgFunctionDefinition* targetFunction = PRE::getFunctionDefinition(funcall); SgExpressionPtrList funargs = funcall->get_args()->get_expressions(); funcall->get_args()->get_expressions().clear(); BOOST_FOREACH (SgExpression *actual, funargs) actual->set_parent(NULL); // Make a copy of the to-be-inlined function so we're not modifying and (re)inserting the original. SgBasicBlock* funbody_raw = fundef->get_body(); SgInitializedNamePtrList& params = fundecl->get_args(); std::vector<SgInitializedName*> inits; SgTreeCopy tc; SgFunctionDefinition* function_copy = isSgFunctionDefinition(fundef->copy(tc)); ROSE_ASSERT (function_copy); SgBasicBlock* funbody_copy = function_copy->get_body(); renameLabels(funbody_copy, targetFunction); ASSERT_require(funbody_raw->get_symbol_table()->size() == funbody_copy->get_symbol_table()->size()); // We don't need to keep the copied SgFunctionDefinition now that the labels in it have been moved to the target function // (having it in the memory pool confuses the AST tests), but we must not delete the formal argument list or the body // because we need them below. if (function_copy->get_declaration()) { ASSERT_require(function_copy->get_declaration()->get_parent() == function_copy); function_copy->get_declaration()->set_parent(NULL); function_copy->set_declaration(NULL); } if (function_copy->get_body()) { ASSERT_require(function_copy->get_body()->get_parent() == function_copy); function_copy->get_body()->set_parent(NULL); function_copy->set_body(NULL); } delete function_copy; function_copy = NULL; #if 0 SgPragma* pragmaBegin = new SgPragma("start_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaBeginDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaBegin); pragmaBeginDecl->set_endOfConstruct(SgNULL_FILE); pragmaBegin->set_parent(pragmaBeginDecl); pragmaBeginDecl->set_definingDeclaration(pragmaBeginDecl); funbody_copy->prepend_statement(pragmaBeginDecl); pragmaBeginDecl->set_parent(funbody_copy); #endif // In the to-be-inserted function body, create new local variables with distinct non-conflicting names, one per formal // argument and having the same type as the formal argument. Initialize those new local variables with the actual // arguments. Also, build a paramMap that maps each formal argument (SgInitializedName) to its corresponding new local // variable (SgVariableSymbol). ReplaceParameterUseVisitor::paramMapType paramMap; SgInitializedNamePtrList::iterator formalIter = params.begin(); SgExpressionPtrList::iterator actualIter = funargs.begin(); for (size_t argNumber=0; formalIter != params.end() && actualIter != funargs.end(); ++argNumber, ++formalIter, ++actualIter) { SgInitializedName *formalArg = *formalIter; SgExpression *actualArg = *actualIter; // Build the new local variable. // FIXME[Robb P. Matzke 2014-12-12]: we need a better way to generate a non-conflicting local variable name SgAssignInitializer* initializer = new SgAssignInitializer(SgNULL_FILE, actualArg, formalArg->get_type()); ASSERT_not_null(initializer); initializer->set_endOfConstruct(SgNULL_FILE); #if 1 printf ("initializer = %p initializer->isTransformation() = %s \n",initializer,initializer->isTransformation() ? "true" : "false"); #endif SgName shadow_name(formalArg->get_name()); shadow_name << "__" << ++gensym_counter; SgVariableDeclaration* vardecl = new SgVariableDeclaration(SgNULL_FILE, shadow_name, formalArg->get_type(), initializer); vardecl->set_definingDeclaration(vardecl); vardecl->set_endOfConstruct(SgNULL_FILE); vardecl->get_definition()->set_endOfConstruct(SgNULL_FILE); vardecl->set_parent(funbody_copy); // Insert the new local variable into the (near) beginning of the to-be-inserted function body. We insert them in the // order their corresponding actuals/formals appear, although the C++ standard does not require this order of // evaluation. SgInitializedName* init = vardecl->get_variables().back(); inits.push_back(init); initializer->set_parent(init); init->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin() + argNumber, vardecl); SgVariableSymbol* sym = new SgVariableSymbol(init); paramMap[formalArg] = sym; funbody_copy->insert_symbol(shadow_name, sym); sym->set_parent(funbody_copy->get_symbol_table()); } // Similarly for "this". We create a local variable in the to-be-inserted function body that will be initialized with the // caller's "this". if (thisdecl) { thisdecl->set_parent(funbody_copy); thisinitname->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin(), thisdecl); SgVariableSymbol* thisSym = new SgVariableSymbol(thisinitname); funbody_copy->insert_symbol(thisname, thisSym); thisSym->set_parent(funbody_copy->get_symbol_table()); ReplaceThisWithRefVisitor(thisSym).traverse(funbody_copy, postorder); } ReplaceParameterUseVisitor(paramMap).traverse(funbody_copy, postorder); SgName end_of_inline_name = "rose_inline_end__"; end_of_inline_name << ++gensym_counter; SgLabelStatement* end_of_inline_label = new SgLabelStatement(SgNULL_FILE, end_of_inline_name); end_of_inline_label->set_endOfConstruct(SgNULL_FILE); #if 0 printf ("\n\nCalling AST copy mechanism on a SgBasicBlock \n"); // Need to set the parent of funbody_copy to avoid error. funbody_copy->set_parent(funbody_raw->get_parent()); printf ("This is a copy of funbody_raw = %p to build funbody_copy = %p \n",funbody_raw,funbody_copy); printf ("funbody_raw->get_statements().size() = %" PRIuPTR " \n",funbody_raw->get_statements().size()); printf ("funbody_copy->get_statements().size() = %" PRIuPTR " \n",funbody_copy->get_statements().size()); printf ("funbody_raw->get_symbol_table()->size() = %d \n",(int)funbody_raw->get_symbol_table()->size()); printf ("funbody_copy->get_symbol_table()->size() = %d \n",(int)funbody_copy->get_symbol_table()->size()); printf ("Output the symbol table for funbody_raw \n"); funbody_raw->get_symbol_table()->print("debugging copy problem"); // printf ("Output the symbol table for funbody_copy \n"); // funbody_copy->get_symbol_table()->print("debugging copy problem"); SgProject* project_copy = TransformationSupport::getProject(funbody_raw); ROSE_ASSERT(project_copy != NULL); const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 4000; generateAstGraph(project_copy,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH); #endif funbody_copy->append_statement(end_of_inline_label); end_of_inline_label->set_scope(targetFunction); SgLabelSymbol* end_of_inline_label_sym = new SgLabelSymbol(end_of_inline_label); end_of_inline_label_sym->set_parent(targetFunction->get_symbol_table()); targetFunction->get_symbol_table()->insert(end_of_inline_label->get_name(), end_of_inline_label_sym); // To ensure that there is some statement after the label SgExprStatement* dummyStatement = SageBuilder::buildExprStatement(SageBuilder::buildNullExpression()); dummyStatement->set_endOfConstruct(SgNULL_FILE); funbody_copy->append_statement(dummyStatement); dummyStatement->set_parent(funbody_copy); #if 0 SgPragma* pragmaEnd = new SgPragma("end_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaEndDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaEnd); pragmaEndDecl->set_endOfConstruct(SgNULL_FILE); pragmaEnd->set_parent(pragmaEndDecl); pragmaEndDecl->set_definingDeclaration(pragmaEndDecl); funbody_copy->append_statement(pragmaEndDecl); pragmaEndDecl->set_parent(funbody_copy); #endif ChangeReturnsToGotosPrevisitor previsitor = ChangeReturnsToGotosPrevisitor(end_of_inline_label, funbody_copy); replaceExpressionWithStatement(funcall, &previsitor); // Make sure the AST is consistent. To save time, we'll just fix things that we know can go wrong. For instance, the // SgAsmExpression.p_lvalue data member is required to be true for certain operators and is set to false in other // situations. Since we've introduced new expressions into the AST we need to adjust their p_lvalue according to the // operators where they were inserted. markLhsValues(targetFunction); #ifdef NDEBUG AstTests::runAllTests(SageInterface::getProject()); #endif #if 0 // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag. ROSE_ASSERT(funcall != NULL); ROSE_ASSERT(funcall->get_parent() != NULL); ROSE_ASSERT(globalScope != NULL); // checkTransformedFlagsVisitor(funcall->get_parent()); checkTransformedFlagsVisitor(globalScope); #endif // DQ (4/7/2015): This fixes something I was required to fix over the weekend and which is fixed more directly, I think. // Mark the things we insert as being transformations so they get inserted into the output by backend() markAsTransformation(funbody_copy); return true; }
//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 ControlDependenceGraph::_buildInterprocedural() { // Go through the SGNODE dependence nodes and create the appropriate // call site nodes, entry nodes etc. SgFunctionDefinition *func = isSgFunctionDefinition(_head); ROSE_ASSERT(func != NULL); // First create the entry node for the procedure _interprocedural->procedureEntry.entry = new DependenceNode(DependenceNode::ENTRY, func->get_declaration()); DependenceNode *entry = createNode(_interprocedural->procedureEntry.entry); // Link the entry node up with all the nodes in the CDG which do not have // predecessors for (set < SimpleDirectedGraphNode * >::iterator i = _nodes.begin(); i != _nodes.end(); i++) { DependenceNode *node = dynamic_cast < DependenceNode * >(*i); if ((node->numPredecessors() == 0) && (node != entry)) { establishEdge(entry, node); } } // create a formal out return argument, control dependent on the entry // node string return_name = func->get_declaration()->get_name().str(); return_name = return_name + " return"; _interprocedural->procedureEntry.formal_return = new DependenceNode(DependenceNode::FORMALOUT, return_name); DependenceNode *formal_return = createNode(_interprocedural->procedureEntry.formal_return); establishEdge(entry, formal_return); // for each of the arguments in the function parameter list, add a // formal-in and formal-out node SgFunctionParameterList *paramlist = func->get_declaration()->get_parameterList(); SgInitializedNamePtrList params = paramlist->get_args(); for (SgInitializedNamePtrList::iterator i = params.begin(); i != params.end(); i++) { SgInitializedName *name = *i; DependenceNode *formal_in = new DependenceNode(DependenceNode::FORMALIN, name->get_name().str()); DependenceNode *formal_out = new DependenceNode(DependenceNode::FORMALOUT, name->get_name().str()); establishEdge(entry, createNode(formal_in)); establishEdge(entry, createNode(formal_out)); _interprocedural->procedureEntry.formal_in[name] = formal_in; _interprocedural->procedureEntry.formal_out[name] = formal_out; // To preserve the order of arguments, we insert them into arg_order _interprocedural->procedureEntry.arg_order.push_back(name); } // Now we go through each of the SgNodes in our CDG. If any of them // contain a function call, we want to build a call site node for them. map < SgNode *, DependenceNode * >::iterator sgnode_iterator; for (sgnode_iterator = _sgnode_map.begin(); sgnode_iterator != _sgnode_map.end(); sgnode_iterator++) { SgNode *currnode = sgnode_iterator->first; list < SgFunctionCallExp * >calls = InterproceduralInfo::extractFunctionCalls(currnode); if (calls.empty()) continue; for (list < SgFunctionCallExp * >::iterator i = calls.begin(); i != calls.end(); i++) { SgFunctionCallExp *call = *i; // This needs to be replaced with some call graph analysis SgFunctionRefExp *func = isSgFunctionRefExp(call->get_function()); ROSE_ASSERT(func != NULL); SgName func_name = func->get_symbol()->get_name(); InterproceduralInfo::CallSiteStructure callstructure; callstructure.callsite = new DependenceNode(DependenceNode::CALLSITE, call); // the call site is control dependent on the statement (i.e. for // the call site to happen, the statement must be executed) DependenceNode *callsite = createNode(callstructure.callsite); // addLink(callsite, getNode(currnode)); establishEdge(getNode(currnode), callsite); // create an actual out node for the return value, control // dependent on callsite string return_name = func_name.str(); return_name = return_name + " return"; callstructure.actual_return = new DependenceNode(DependenceNode::ACTUALOUT, return_name); DependenceNode *actual_return = createNode(callstructure.actual_return); establishEdge(callsite, actual_return); // For each argument in the function call, build an actual_in and // actual_out, control dependent on callsite SgExpressionPtrList args = call->get_args()->get_expressions(); for (SgExpressionPtrList::iterator j = args.begin(); j != args.end(); j++) { SgExpression *arg = *j; DependenceNode *actual_in = new DependenceNode(DependenceNode::ACTUALIN, arg); DependenceNode *actual_out = new DependenceNode(DependenceNode::ACTUALOUT, arg); establishEdge(callsite, createNode(actual_in)); establishEdge(callsite, createNode(actual_out)); callstructure.actual_in[arg] = actual_in; callstructure.actual_out[arg] = actual_out; // To preserve the order of expressions in the parameter list, // // we insert them into expr_order callstructure.expr_order.push_back(arg); } // add the callstructure to interprocedural info _interprocedural->callsite_map[call] = callstructure; } } }
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); } } }
void Fortran_to_C::linearizeArraySubscript(SgPntrArrRefExp* pntrArrRefExp) { // get lhs operand SgVarRefExp* arrayName = isSgVarRefExp(pntrArrRefExp->get_lhs_operand()); // 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()); /* No matter it is single or multi dimensional array, pntrArrRefExp always has a child, SgExprListExp, to store the subscript information. */ if(arrayType->findBaseType()->variantT() == V_SgTypeString) { arraySubscript->prepend_expression(buildIntVal(1)); } 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()); /* The subscript conversion is following this example: case 1: dimension a(d1,d2,d3,d4) ====> dimension a(d1*d2*d3*d4) a(s1,s2,s3,s4) ====> a(s1-1 + d1*(s2-1 + d2*( s3-1 + d3*(s4-1)))) case 2: dimension a(d1L:d1H,d2L:d2H) ====> dimension a((d1H-d1L+1)*(d2H-d2L+1)) a(s1,s2) ====> a(s1-d1L + (d1H-d1L+1)*(s2-d2L)) */ Rose_STL_Container<SgExpression*>::reverse_iterator j1 = subscriptExprList.rbegin(); Rose_STL_Container<SgExpression*>::reverse_iterator j2 = dimExpressionPtrList.rbegin(); // Need to know current size of both current and previous dimension SgExpression* newSubscript; while((j1 != subscriptExprList.rend()) && (j2 != dimExpressionPtrList.rend())) { // get the lowerBound for each dimension SgExpression* newDimIndex; SgExpression* dimSize; /* get the dimension size at each dimension */ SgSubscriptExpression* subscriptExpression = isSgSubscriptExpression(*j2); /* This is for the 1st type of array declaration: a(10,15,20) Fortran is 1-based array. Lowerbound is 1 by default. */ if(subscriptExpression == NULL) { dimSize = deepCopy(*j2); } /* This is for the 2nd type of array declaration: a(1:10,5:15,10:20) Actual dimension size = upperBound - lowerBound + 1 */ else { dimSize = buildAddOp(buildSubtractOp(deepCopy(subscriptExpression->get_upperBound()), deepCopy(subscriptExpression->get_lowerBound())), buildIntVal(1)); } // convert the 1-based subscript to 0-based subscript newDimIndex = get0basedIndex(*j1, *j2); if(j1 != subscriptExprList.rbegin()) { newSubscript = buildAddOp(newDimIndex, buildMultiplyOp(dimSize,newSubscript)); } else { newSubscript = newDimIndex; delete(dimSize); } ++j1; ++j2; } // end of while loop newSubscriptExprList.push_back(newSubscript); SgExprListExp* newSubscriptList = buildExprListExp(newSubscriptExprList); // un-link and remove the rhs operand pntrArrRefExp->get_rhs_operand()->set_parent(NULL); removeList.push_back(pntrArrRefExp->get_rhs_operand()); // add the new subscriptExpression into rhs operand pntrArrRefExp->set_rhs_operand(newSubscriptList); newSubscriptList->set_parent(pntrArrRefExp); } // end of arraySubscript != NULL }
/*! * \author Markus Schordan * \date 2014. */ void SPRAY::IntervalTransferFunctions::transferFunctionCall(Label lab, SgFunctionCallExp* callExp, SgExpressionPtrList& arguments,Lattice& element) { // uses and defs in argument-expressions for(SgExpressionPtrList::iterator i=arguments.begin();i!=arguments.end();++i) { transferExpression(lab,*i,element); } }