// The transfer function that is applied to SgFunctionCallExp nodes to perform the appropriate state transfers // fw - =true if this is a forward analysis and =false if this is a backward analysis // n - the dataflow node that is being processed // state - The NodeState object that describes the dataflow state immediately before (if fw=true) or immediately after // (if fw=false) the SgFunctionCallExp node, as established by earlier analysis passes // dfInfo - The Lattices that this transfer function operates on. The function propagates them // to the calling function and overwrites them with the dataflow result of calling this function. // retState - Pointer reference to a Lattice* vector that will be assigned to point to the lattices of // the function call's return value. The callee may not modify these lattices. // Returns true if any of the input lattices changed as a result of the transfer function and // false otherwise. bool ContextInsensitiveInterProceduralDataflow::transfer( const Function& func, const DataflowNode& n, NodeState& state, const vector<Lattice*>& dfInfo, vector<Lattice*>** retState, bool fw) { bool modified = false; SgFunctionCallExp* call = isSgFunctionCallExp(n.getNode()); Function callee(call); ROSE_ASSERT(call); if(analysisDebugLevel > 0) Dbg::dbg << "ContextInsensitiveInterProceduralDataflow::transfer "<<func.get_name().getString()<<"()=>"<<callee.get_name().getString()<<"()\n"; if(callee.get_definition()) { FunctionState* funcS = FunctionState::getDefinedFuncState(callee); // The lattices before the function (forward: before=above, after=below; backward: before=below, after=above) const vector<Lattice*>* funcLatticesBefore; if(fw) funcLatticesBefore = &(funcS->state.getLatticeAbove((Analysis*)intraAnalysis)); else funcLatticesBefore = &(funcS->state.getLatticeBelow((Analysis*)intraAnalysis)); //if(analysisDebugLevel > 0) // printf(" dfInfo.size()=%d, funcLatticesBefore->size()=%d, this=%p\n", dfInfo.size(), funcLatticesBefore->size(), this); // Update the function's entry/exit state with the caller's state at the call site vector<Lattice*>::const_iterator itCalleeBefore, itCallerBefore; for(itCallerBefore = dfInfo.begin(), itCalleeBefore = funcLatticesBefore->begin(); itCallerBefore!=dfInfo.end() && itCalleeBefore!=funcLatticesBefore->end(); itCallerBefore++, itCalleeBefore++) { Lattice* calleeL = *itCalleeBefore; Lattice* callerL = *itCallerBefore; if(analysisDebugLevel>=1) { Dbg::dbg << " callerL=["<<calleeL<<"] "<<callerL->str(" ")<<endl; Dbg::dbg << " Before calleeL=["<<calleeL<<"] "<<calleeL->str(" ")<<endl; } // Create a copy of the current lattice, remapped for the called function's variables Lattice* remappedL = callerL->copy(); map<varID, varID> argParamMap; FunctionState::setArgParamMap(call, argParamMap); /*Dbg::dbg << "#argParamMap="<<argParamMap.size()<<endl; for(map<varID, varID>::iterator it = argParamMap.begin(); it!=argParamMap.end(); it++) { printf("argParamMap[%s] = %s \n", it->first.str().c_str(), it->second.str().c_str()); }*/ remappedL->remapVars(argParamMap, callee); Dbg::dbg << " remappedL=["<<calleeL<<"] "<<remappedL->str(" ")<<endl; // update the callee's Lattice with the new information at the call site modified = calleeL->meetUpdate(remappedL) || modified; if(analysisDebugLevel>=1) Dbg::dbg << " After modified = "<<modified << "calleeL=["<<calleeL<<"] "<<calleeL->str(" ")<<endl; //!!! delete remappedL; } // If this resulted in the dataflow information before the callee changing, add it to the remaining list. if(modified) { if(analysisDebugLevel > 0) Dbg::dbg << "ContextInsensitiveInterProceduralDataflow::transfer Incoming Dataflow info modified\n"; // Record that the callee function needs to be re-analyzed because of new information from the caller TraverseCallGraphDataflow::addToRemaining(getFunc(callee)); remainingDueToCallers.insert(getFunc(callee)); } // The lattices after the function (forward: before=above, after=below; backward: before=below, after=above). const vector<Lattice*>* funcLatticesAfter; if(fw) funcLatticesAfter = &(funcS->state.getLatticeBelow((Analysis*)intraAnalysis)); else funcLatticesAfter = &(funcS->state.getLatticeAbove((Analysis*)intraAnalysis)); //Dbg::dbg << " funcLatticesAfter->size()="<<funcLatticesAfter->size()<<endl; if(analysisDebugLevel>=1) Dbg::dbg << " ----%%%%%%%%%%%%%%%%%%%%---------\n"; // Transfer the result of the function call into the dfInfo Lattices. vector<Lattice*>::const_iterator itCalleeAfter, itCallerAfter; for(itCallerAfter = dfInfo.begin(), itCalleeAfter = funcLatticesAfter->begin(); itCallerAfter!=dfInfo.end() && itCalleeAfter!=funcLatticesAfter->end(); itCallerAfter++, itCalleeAfter++) { Lattice* callerL = *itCallerAfter; Lattice* calleeL = *itCalleeAfter; //Dbg::dbg << " calleeL-after=["<<calleeL<<"] "<<calleeL->str(" ")<<endl; // Create a copy of the current lattice, remapped for the callee function's variables Lattice* remappedL = calleeL->copy(); if(analysisDebugLevel>=1) Dbg::dbg << " remappedL-after=["<<remappedL<<"] "<<calleeL->str(" ")<<endl << remappedL->str(" ")<<endl; map<varID, varID> paramArgByRefMap; FunctionState::setParamArgByRefMap(call, paramArgByRefMap); /*Dbg::dbg << "#paramArgByRefMap="<<paramArgByRefMap.size()<<endl; for(map<varID, varID>::iterator it = paramArgByRefMap.begin(); it!=paramArgByRefMap.end(); it++) { Dbg::dbg << "paramArgByRefMap["<<it->first.str()<<"] = "<<it->second.str()<<endl; */ remappedL->remapVars(paramArgByRefMap, func); //Dbg::dbg << " callerL-after=["<<callerL<<"] "<<callerL->str(" ")<<endl; Dbg::dbg << " +remappedL-after=["<<remappedL<<"] "<<remappedL->str(" ")<<endl; // update the caller's Lattice with the new information at the call site callerL->incorporateVars(remappedL); if(analysisDebugLevel>=1) Dbg::dbg << " ==> callerL-after=["<<callerL<<"] "<<callerL->str(" ")<<endl; //Dbg::dbg << " calleeL-after=["<<calleeL<<"] "<<calleeL->str(" ")<<endl; modified = true; //!!! delete remappedL; } // Point retState to the lattices of the function's return values *retState = &(funcS->retState.getLatticeBelowMod((Analysis*)intraAnalysis)); /*Dbg::dbg << " retState="<<retState<<endl; for(vector<Lattice*>::iterator l=(*retState)->begin(); l!=(*retState)->end(); l++) Dbg::dbg << " "<<(*l)->str(" ")<<endl;*/ } // Don't do anything for functions with no definitions else { } return modified; }