示例#1
0
// 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;
}