void ExprWalker::visit(SgInitializedName* sgn) { VariableId vid = vidm.variableId(sgn); // some SgInitializedName do not have symbols // VariableId is not created for such SgInitializedName // check and return if we are processing such SgInitializedName if(!vid.isValid()) { //cerr << "WARNING: Skipping SgInitializedName sgn->get_name() = " << sgn->get_name() << " with no symbol\n"; return; } DefUseVarsInfo rduvi; SgInitializer* initializer = sgn->get_initializer(); if(initializer) { rduvi = getDefUseVarsInfo_rec(initializer, vidm, false); } // SgInitializedName always define a variable // it should always be in def_set VarsInfo& def_vars_info = duvi.getDefVarsInfoMod(); // determine the type info VariableIdTypeInfo sgn_type_info = getVariableIdTypeInfo(vid, vidm); if(vidm.getModeVariableIdForEachArrayElement() && sgn_type_info == arrayType) // When defining an array, define all its elements. duvi.addAllArrayElements(sgn, vidm, true); else def_vars_info.first.insert(VariableIdInfo(vid, sgn_type_info)); duvi = duvi + rduvi; }
VariableValueRangeInfo VariableConstInfo::createVariableValueRangeInfo(VariableId varId, VarConstSetMap& map) { ROSE_ASSERT(map.size()>0); ROSE_ASSERT(varId.isValid()); set<CppCapsuleConstIntLattice> cppCapsuleSet=map[varId]; AType::ConstIntLattice minVal; AType::ConstIntLattice maxVal; // in case the set of collected assignments is empty, bot is returned (min and max remain bot). if(cppCapsuleSet.size()==0) return VariableValueRangeInfo(AType::ConstIntLattice(AType::Bot())); for(set<CppCapsuleConstIntLattice>::iterator i=cppCapsuleSet.begin(); i!=cppCapsuleSet.end(); ++i) { AType::ConstIntLattice aint=(*i).getValue(); if(aint.isTop()) { return VariableValueRangeInfo(AType::ConstIntLattice(AType::Top())); } if(minVal.isBot() && maxVal.isBot()) { minVal=aint; maxVal=aint; continue; } if((aint<minVal).isTrue()) minVal=aint; if((aint>maxVal).isTrue()) maxVal=aint; } if(minVal.isBot()||maxVal.isBot()) return VariableValueRangeInfo(AType::ConstIntLattice(AType::Bot())); return VariableValueRangeInfo(minVal,maxVal); }
// base case for the recursion void SPRAY::ComputeAddressTakenInfo::OperandToVariableId::visit(SgVarRefExp *sgn) { if(debuglevel > 0) debugPrint(sgn); VariableId id = cati.vidm.variableId(sgn); ROSE_ASSERT(id.isValid()); // insert the id into VariableIdSet cati.addressTakenInfo.second.insert(id); }
/*! * \author Markus Schordan * \date 2012. */ string VariableIdMapping::uniqueShortVariableName(VariableId varId) { if(!isTemporaryVariableId(varId)) { if(!varId.isValid()) return "$invalidId"; else return variableName(varId)+"_"+varId.toString().substr(1); //return SgNodeHelper::uniqueLongVariableName(getSymbol(varId)); } else { return string("tmp")+"_"+varId.toString().substr(1); } }
VariableIdMapping::VariableIdSet VariableIdMapping::variableIdsOfAstSubTree(SgNode* node) { VariableIdSet vset; RoseAst ast(node); for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) { VariableId vid; // default creates intentionally an invalid id. if(SgVariableDeclaration* varDecl=isSgVariableDeclaration(*i)) { vid=variableId(varDecl); } else if(SgVarRefExp* varRefExp=isSgVarRefExp(*i)) { vid=variableId(varRefExp); } else if(SgInitializedName* initName=isSgInitializedName(*i)) { vid=variableId(initName); } if(vid.isValid()) vset.insert(vid); } return vset; }
void ExprWalker::visit(SgVarRefExp* sgn) { // get the VariableId VariableId vid = vidm.variableId(sgn); ROSE_ASSERT(vid.isValid()); // determine type info VariableIdTypeInfo sgn_type_info = getVariableIdTypeInfo(vid, vidm); VarsInfo& def_vars_info = duvi.getDefVarsInfoMod(); VarsInfo& use_vars_info = duvi.getUseVarsInfoMod(); if(isModExpr) { def_vars_info.first.insert(VariableIdInfo(vid, sgn_type_info)); } else { use_vars_info.first.insert(VariableIdInfo(vid, sgn_type_info)); } }
void ExprWalker::visit(SgVarRefExp* sgn) { // get the VariableId VariableId vid = vidm.variableId(sgn); ROSE_ASSERT(vid.isValid()); // determine type info VariableIdTypeInfo sgn_type_info = getVariableIdTypeInfo(vid, vidm); VarsInfo& def_vars_info = duvi.getDefVarsInfoMod(); VarsInfo& use_vars_info = duvi.getUseVarsInfoMod(); if(vidm.getModeVariableIdForEachArrayElement() && sgn_type_info == arrayType) { // If found a reference to whole array, def/use all its elements. duvi.addAllArrayElements(SageInterface::convertRefToInitializedName(sgn), vidm, isModExpr); } else if(isModExpr) { def_vars_info.first.insert(VariableIdInfo(vid, sgn_type_info)); } else { use_vars_info.first.insert(VariableIdInfo(vid, sgn_type_info)); } }
list<SingleEvalResultConstInt> ExprAnalyzer::evalConstInt(SgNode* node,EState estate, bool useConstraints, bool safeConstraintPropagation) { assert(estate.pstate()); // ensure state exists SingleEvalResultConstInt res; //cout<<"DEBUG: evalConstInt: "<<node->unparseToString()<<astTermWithNullValuesToString(node)<<endl; // guard: for floating-point expression: return immediately with most general result // TODO: refine to walk the tree, when assignments are allowed in sub-expressions // MS: 2014-06-27: this cannot run in parallel because exp->get_type() seg-faults #if 0 if(SgExpression* exp=isSgExpression(node)) { bool isFloatingPointType; // ROSE workaround. get_type cannot be run in parallel #pragma omp critical { isFloatingPointType=SgNodeHelper::isFloatingPointType(exp->get_type()); } if(isFloatingPointType) { res.estate=estate; res.result=AType::ConstIntLattice(AType::Top()); return listify(res); } } #endif // initialize with default values from argument(s) res.estate=estate; res.result=AType::ConstIntLattice(AType::Bot()); if(SgNodeHelper::isPostfixIncDecOp(node)) { cout << "Error: incdec-op not supported in conditions yet."<<endl; exit(1); } if(SgConditionalExp* condExp=isSgConditionalExp(node)) { list<SingleEvalResultConstInt> resultList; SgExpression* cond=condExp->get_conditional_exp(); list<SingleEvalResultConstInt> condResultList=evalConstInt(cond,estate,useConstraints,safeConstraintPropagation); if(condResultList.size()==0) { cerr<<"Error: evaluating condition of conditional operator inside expressions gives no result."<<endl; exit(1); } if(condResultList.size()==2) { list<SingleEvalResultConstInt>::iterator i=condResultList.begin(); SingleEvalResultConstInt singleResult1=*i; ++i; SingleEvalResultConstInt singleResult2=*i; if((singleResult1.value()==singleResult2.value()).isTrue()) { cout<<"Info: evaluating condition of conditional operator gives two equal results"<<endl; } } if(condResultList.size()>1) { cerr<<"Error: evaluating condition of conditional operator gives more than one result. Not supported yet."<<endl; exit(1); } SingleEvalResultConstInt singleResult=*condResultList.begin(); if(singleResult.result.isTop()) { SgExpression* trueBranch=condExp->get_true_exp(); list<SingleEvalResultConstInt> trueBranchResultList=evalConstInt(trueBranch,estate,useConstraints,safeConstraintPropagation); SgExpression* falseBranch=condExp->get_false_exp(); list<SingleEvalResultConstInt> falseBranchResultList=evalConstInt(falseBranch,estate,useConstraints,safeConstraintPropagation); // append falseBranchResultList to trueBranchResultList (moves elements), O(1). trueBranchResultList.splice(trueBranchResultList.end(), falseBranchResultList); return trueBranchResultList; } if(singleResult.result.isTrue()) { SgExpression* trueBranch=condExp->get_true_exp(); list<SingleEvalResultConstInt> trueBranchResultList=evalConstInt(trueBranch,estate,useConstraints,safeConstraintPropagation); return trueBranchResultList; } if(singleResult.result.isFalse()) { SgExpression* falseBranch=condExp->get_false_exp(); list<SingleEvalResultConstInt> falseBranchResultList=evalConstInt(falseBranch,estate,useConstraints,safeConstraintPropagation); return falseBranchResultList; } // dummy return value to avoid compiler warning cerr<<"Error: evaluating conditional operator inside expressions - unknown behavior (condition may have evaluated to bot)."<<endl; exit(1); return resultList; } if(dynamic_cast<SgBinaryOp*>(node)) { //cout << "BinaryOp:"<<SgNodeHelper::nodeToString(node)<<endl; SgNode* lhs=SgNodeHelper::getLhs(node); list<SingleEvalResultConstInt> lhsResultList=evalConstInt(lhs,estate,useConstraints,safeConstraintPropagation); SgNode* rhs=SgNodeHelper::getRhs(node); list<SingleEvalResultConstInt> rhsResultList=evalConstInt(rhs,estate,useConstraints,safeConstraintPropagation); //assert(lhsResultList.size()==1); //assert(rhsResultList.size()==1); list<SingleEvalResultConstInt> resultList; for(list<SingleEvalResultConstInt>::iterator liter=lhsResultList.begin(); liter!=lhsResultList.end(); ++liter) { for(list<SingleEvalResultConstInt>::iterator riter=rhsResultList.begin(); riter!=rhsResultList.end(); ++riter) { SingleEvalResultConstInt lhsResult=*liter; SingleEvalResultConstInt rhsResult=*riter; switch(node->variantT()) { case V_SgEqualityOp: { res.result=(lhsResult.result==rhsResult.result); res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; // record new constraint VariableId varId; if(variable(lhs,varId) && rhsResult.isConstInt()) { // if var is top add two states with opposing constraints if(!res.estate.pstate()->varIsConst(varId)) { SingleEvalResultConstInt tmpres1=res; SingleEvalResultConstInt tmpres2=res; tmpres1.exprConstraints.addConstraint(Constraint(Constraint::EQ_VAR_CONST,varId,rhsResult.value())); tmpres1.result=true; tmpres2.exprConstraints.addConstraint(Constraint(Constraint::NEQ_VAR_CONST,varId,rhsResult.value())); tmpres2.result=false; resultList.push_back(tmpres1); resultList.push_back(tmpres2); //return resultList; MS: removed 3/11/2014 break; } } if(lhsResult.isConstInt() && variable(rhs,varId)) { // only add the equality constraint if no constant is bound to the respective variable if(!res.estate.pstate()->varIsConst(varId)) { SingleEvalResultConstInt tmpres1=res; SingleEvalResultConstInt tmpres2=res; tmpres1.exprConstraints.addConstraint(Constraint(Constraint::EQ_VAR_CONST,varId,lhsResult.value())); tmpres1.result=true; tmpres2.exprConstraints.addConstraint(Constraint(Constraint::NEQ_VAR_CONST,varId,lhsResult.value())); tmpres2.result=false; resultList.push_back(tmpres1); resultList.push_back(tmpres2); break; } } resultList.push_back(res); break; } case V_SgNotEqualOp: { res.result=(lhsResult.result!=rhsResult.result); res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; // record new constraint VariableId varId; if(variable(lhs,varId) && rhsResult.isConstInt()) { // only add the equality constraint if no constant is bound to the respective variable if(!res.estate.pstate()->varIsConst(varId)) { SingleEvalResultConstInt tmpres1=res; SingleEvalResultConstInt tmpres2=res; tmpres1.exprConstraints.addConstraint(Constraint(Constraint::NEQ_VAR_CONST,varId,rhsResult.value())); tmpres1.result=true; tmpres2.exprConstraints.addConstraint(Constraint(Constraint::EQ_VAR_CONST,varId,rhsResult.value())); tmpres2.result=false; resultList.push_back(tmpres1); resultList.push_back(tmpres2); break; } } if(lhsResult.isConstInt() && variable(rhs,varId)) { // only add the equality constraint if no constant is bound to the respective variable if(!res.estate.pstate()->varIsConst(varId)) { SingleEvalResultConstInt tmpres1=res; SingleEvalResultConstInt tmpres2=res; tmpres1.exprConstraints.addConstraint(Constraint(Constraint::NEQ_VAR_CONST,varId,lhsResult.value())); tmpres1.result=true; tmpres2.exprConstraints.addConstraint(Constraint(Constraint::EQ_VAR_CONST,varId,lhsResult.value())); tmpres2.result=false; resultList.push_back(tmpres1); resultList.push_back(tmpres2); break; } } resultList.push_back(res); break; } case V_SgAndOp: { //cout << "SgAndOp: "<<lhsResult.result.toString()<<"&&"<<rhsResult.result.toString()<<" ==> "; res.result=(lhsResult.result&&rhsResult.result); //cout << res.result.toString()<<endl; #if 0 cout << lhsResult.exprConstraints.toString(); cout << "&&"; cout << rhsResult.exprConstraints.toString(); cout << " == > "; #endif if(lhsResult.result.isFalse()) { res.exprConstraints=lhsResult.exprConstraints; // rhs is not considered due to short-circuit AND semantics } if(lhsResult.result.isTrue() && rhsResult.result.isFalse()) { res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; // nothing to do } if(lhsResult.result.isTrue() && rhsResult.result.isTrue()) { res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; } // in case of top we do not propagate constraints if(lhsResult.result.isTop() && !safeConstraintPropagation) { res.exprConstraints+=lhsResult.exprConstraints; } if(rhsResult.result.isTop() && !safeConstraintPropagation) { res.exprConstraints+=rhsResult.exprConstraints; } resultList.push_back(res); // cout << res.exprConstraints.toString(); //cout << endl; break; } case V_SgOrOp: { res.result=(lhsResult.result||rhsResult.result); // we encode short-circuit CPP-OR semantics here! if(lhsResult.result.isTrue()) { res.result=lhsResult.result; res.exprConstraints=lhsResult.exprConstraints; } if(lhsResult.result.isFalse() && rhsResult.result.isFalse()) { res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; } if(lhsResult.result.isFalse() && rhsResult.result.isTrue()) { res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; } // in case of top we do not propagate constraints if(lhsResult.result.isTop() && !safeConstraintPropagation) { res.exprConstraints+=lhsResult.exprConstraints; } if(rhsResult.result.isTop() && !safeConstraintPropagation) { res.exprConstraints+=rhsResult.exprConstraints; } resultList.push_back(res); break; } case V_SgAddOp: { res.result=(lhsResult.result+rhsResult.result); res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgSubtractOp: { res.result=(lhsResult.result-rhsResult.result); res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgMultiplyOp: { res.result=(lhsResult.result*rhsResult.result); res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgDivideOp: { res.result=(lhsResult.result/rhsResult.result); res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgModOp: { res.result=(lhsResult.result%rhsResult.result); res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgGreaterOrEqualOp: { res.result=(lhsResult.result>=rhsResult.result); if(boolOptions["relop-constraints"]) { if(res.result.isTop()) throw "Error: Top found in relational operator (not supported yet)."; } res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgGreaterThanOp: { res.result=(lhsResult.result>rhsResult.result); if(boolOptions["relop-constraints"]) { if(res.result.isTop()) throw "Error: Top found in relational operator (not supported yet)."; } res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgLessThanOp: { res.result=(lhsResult.result<rhsResult.result); if(boolOptions["relop-constraints"]) { if(res.result.isTop()) throw "Error: Top found in relational operator (not supported yet)."; } res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgLessOrEqualOp: { res.result=(lhsResult.result<=rhsResult.result); if(boolOptions["relop-constraints"]) { if(res.result.isTop()) throw "Error: Top found in relational operator (not supported yet)."; } res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } case V_SgPntrArrRefExp: { // assume top for array elements (array elements are not stored in state) //cout<<"DEBUG: ARRAY-ACCESS2: ARR"<<node->unparseToString()<<"Index:"<<rhsResult.value()<<"skip:"<<getSkipArrayAccesses()<<endl; if(rhsResult.value().isTop()||getSkipArrayAccesses()==true) { res.result=AType::Top(); res.exprConstraints=lhsResult.exprConstraints+rhsResult.exprConstraints; resultList.push_back(res); break; } else { if(SgVarRefExp* varRefExp=isSgVarRefExp(lhs)) { const PState* pstate=estate.pstate(); PState pstate2=*pstate; // also removes constness VariableId arrayVarId=_variableIdMapping->variableId(varRefExp); // two cases if(_variableIdMapping->hasArrayType(arrayVarId)) { // has already correct id // nothing to do } else if(_variableIdMapping->hasPointerType(arrayVarId)) { // in case it is a pointer retrieve pointer value //cout<<"DEBUG: pointer-array access!"<<endl; if(pstate->varExists(arrayVarId)) { AValue aValuePtr=pstate2[arrayVarId].getValue(); // convert integer to VariableId int aValueInt=aValuePtr.getIntValue(); // change arrayVarId to refered array! //cout<<"DEBUG: defering pointer-to-array: ptr:"<<_variableIdMapping->variableName(arrayVarId); arrayVarId=_variableIdMapping->variableIdFromCode(aValueInt); //cout<<" to "<<_variableIdMapping->variableName(arrayVarId)<<endl;//DEBUG } else { cerr<<"Error: pointer variable does not exist in PState."<<endl; exit(1); } } else { cerr<<"Error: unkown type of array or pointer."<<endl; exit(1); } VariableId arrayElementId; AValue aValue=rhsResult.value(); if(aValue.isConstInt()) { int index=aValue.getIntValue(); arrayElementId=_variableIdMapping->variableIdOfArrayElement(arrayVarId,index); //cout<<"DEBUG: arrayElementVarId:"<<arrayElementId.toString()<<":"<<_variableIdMapping->variableName(arrayVarId)<<" Index:"<<index<<endl; } else { cerr<<"Error: array index cannot be evaluated to a constant. Not supported yet."<<endl; cerr<<"expr: "<<varRefExp->unparseToString()<<endl; exit(1); } ROSE_ASSERT(arrayElementId.isValid()); // read value of variable var id (same as for VarRefExp - TODO: reuse) if(pstate->varExists(arrayElementId)) { res.result=pstate2[arrayElementId].getValue(); //cout<<"DEBUG: retrieved value:"<<res.result<<endl; if(res.result.isTop() && useConstraints) { AType::ConstIntLattice val=res.estate.constraints()->varConstIntLatticeValue(arrayElementId); res.result=val; } return listify(res); } else { cerr<<"Error: Array Element does not exist (out of array access?)"<<endl; cerr<<"array-element-id: "<<arrayElementId.toString()<<" name:"<<_variableIdMapping->variableName(arrayElementId)<<endl; cerr<<"PState: "<<pstate->toString(_variableIdMapping)<<endl; cerr<<"AST: "<<node->unparseToString()<<endl; exit(1); } } else { cerr<<"Error: array-access uses expr for denoting the array. Not supported yet."<<endl; cerr<<"expr: "<<lhs->unparseToString()<<endl; cerr<<"arraySkip: "<<getSkipArrayAccesses()<<endl; exit(1); } } break; } default: cerr << "Binary Op:"<<SgNodeHelper::nodeToString(node)<<"(nodetype:"<<node->class_name()<<")"<<endl; throw "Error: evalConstInt::unkown binary operation."; } } } return resultList; } if(dynamic_cast<SgUnaryOp*>(node)) { SgNode* child=SgNodeHelper::getFirstChild(node); list<SingleEvalResultConstInt> operandResultList=evalConstInt(child,estate,useConstraints,safeConstraintPropagation); //assert(operandResultList.size()==1); list<SingleEvalResultConstInt> resultList; for(list<SingleEvalResultConstInt>::iterator oiter=operandResultList.begin(); oiter!=operandResultList.end(); ++oiter) { SingleEvalResultConstInt operandResult=*oiter; switch(node->variantT()) { case V_SgNotOp: res.result=!operandResult.result; // we do NOT invert the constraints, instead we negate the operand result (TODO: investigate) res.exprConstraints=operandResult.exprConstraints; resultList.push_back(res); break; case V_SgCastExp: { // TODO: model effect of cast when sub language is extended //SgCastExp* castExp=isSgCastExp(node); res.result=operandResult.result; res.exprConstraints=operandResult.exprConstraints; resultList.push_back(res); break; } // unary minus case V_SgMinusOp: { res.result=-operandResult.result; // using overloaded operator res.exprConstraints=operandResult.exprConstraints; resultList.push_back(res); break; } default: cerr << "@NODE:"<<node->sage_class_name()<<endl; throw "Error: evalConstInt::unknown unary operation."; } // end switch } return resultList; } ROSE_ASSERT(!dynamic_cast<SgBinaryOp*>(node) && !dynamic_cast<SgUnaryOp*>(node)); // ALL REMAINING CASES DO NOT GENERATE CONSTRAINTS // EXPRESSION LEAF NODES switch(node->variantT()) { case V_SgBoolValExp: { SgBoolValExp* boolValExp=isSgBoolValExp(node); assert(boolValExp); int boolVal= boolValExp->get_value(); if(boolVal==0) { res.result=false; return listify(res); } if(boolVal==1) { res.result=true; return listify(res); } break; } case V_SgDoubleVal: { //SgDoubleVal* doubleValNode=isSgDoubleVal(node); // floating point values are currently not computed res.result=AType::Top(); return listify(res); } case V_SgIntVal: { SgIntVal* intValNode=isSgIntVal(node); int intVal=intValNode->get_value(); res.result=intVal; return listify(res); } case V_SgVarRefExp: { VariableId varId; bool isVar=ExprAnalyzer::variable(node,varId); assert(isVar); const PState* pstate=estate.pstate(); if(pstate->varExists(varId)) { PState pstate2=*pstate; // also removes constness if(_variableIdMapping->hasArrayType(varId)) { // CODE-POINT-1 // for arrays (by default the address is used) return its pointer value (the var-id-code) res.result=AType::ConstIntLattice(varId.getIdCode()); } else { res.result=pstate2[varId].getValue(); // this include assignment of pointer values } if(res.result.isTop() && useConstraints) { // in case of TOP we try to extract a possibly more precise value from the constraints AType::ConstIntLattice val=res.estate.constraints()->varConstIntLatticeValue(varId); // TODO: TOPIFY-MODE: most efficient here res.result=val; } return listify(res); } else { res.result=AType::Top(); cerr << "WARNING: variable not in PState (var="<<_variableIdMapping->uniqueLongVariableName(varId)<<"). Initialized with top."<<endl; return listify(res); } break; } case V_SgFunctionCallExp: { if(getSkipSelectedFunctionCalls()) { // return default value return listify(res); } else { throw "Error: evalConstInt::function call inside expression."; } } default: cerr << "@NODE:"<<node->sage_class_name()<<endl; throw "Error: evalConstInt::unknown operation failed."; } // end of switch throw "Error: evalConstInt failed."; }