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; }
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); }
// 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; } }
/*! * \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++; } }
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); } }
// 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)*/ } }
// 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 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; } } }
/*! * \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); } }