/** * */ package xsched.analysis.wala.schedule_extraction; import com.ibm.wala.dataflow.graph.AbstractMeetOperator; import com.ibm.wala.dataflow.graph.ITransferFunctionProvider; import com.ibm.wala.fixedpoint.impl.UnaryOperator; import com.ibm.wala.fixpoint.IVariable; import com.ibm.wala.ssa.ISSABasicBlock; import com.ibm.wala.ssa.SSAInstruction; final class TransferFunctionProvider implements ITransferFunctionProvider<ISSABasicBlock, FlowData> { TransferFunctionProvider() { } private final AbstractMeetOperator<FlowData> meetOperator = new AbstractMeetOperator<FlowData>() { private final boolean DEBUG = false; //the meet operator will not be called if there is only one incoming edge; if there //are more than one incoming edges, we are a join node and use a different node visitor to handle //potential phi nodes @Override public boolean isUnaryNoOp() { return false; } @SuppressWarnings("unchecked") @Override public byte evaluate(FlowData lhs, IVariable[] rhs) { if(rhs.length == 1) { NormalNodeFlowData lhsData = (NormalNodeFlowData)lhs; EdgeFlowData rhsEdge = (EdgeFlowData)rhs[0]; assert ! rhsEdge.isInitial(); NormalNodeFlowData rhsData = rhsEdge.getData(); if(lhsData.stateEquals(rhsData)) { if(DEBUG) System.out.println("TransferFunctionProvider: meet " + lhs + " value did NOT change"); return NOT_CHANGED; } else { if(DEBUG) System.out.println("TransferFunctionProvider: meet " + lhs + " value did change"); lhsData.copyState(rhsData); return CHANGED; } } assert rhs.length > 1; assert lhs instanceof JoinNodeFlowData; EdgeFlowData[] incoming = new EdgeFlowData[rhs.length]; for(int i = 0; i < rhs.length; i++) { EdgeFlowData edge = (EdgeFlowData)rhs[i]; assert edge != null; incoming[i] = edge; } JoinNodeFlowData result = new JoinNodeFlowData(((JoinNodeFlowData)lhs).basicBlock, incoming.length); result.initAndMergeFromIncoming(incoming); if(lhs.stateEquals(result)) { if(DEBUG) System.out.println("TransferFunctionProvider: meet " + lhs + " value did NOT change"); return NOT_CHANGED; } else { if(DEBUG) System.out.println("TransferFunctionProvider: meet " + lhs + " value did change"); lhs.copyState(result); return CHANGED; } } @Override public int hashCode() { return System.identityHashCode(this); } @Override public boolean equals(Object o) { return o == this; } @Override public String toString() { return "Meet Operator"; } }; private final UnaryOperator<FlowData> edgeTransferFunction = new UnaryOperator<FlowData>() { //private final boolean DEBUG = false; @Override public byte evaluate(FlowData lhs, FlowData rhs) { assert lhs instanceof EdgeFlowData; assert rhs instanceof NormalNodeFlowData; lhs.copyState(rhs); return CHANGED; //the edge flow data will just take the node flow data as its new state if copied // if(lhs.stateEquals(rhs)) { // if(DEBUG) // System.out.println("TransferFunctionProvider: edge transfer function " + lhs + " value did NOT change"); // return NOT_CHANGED; // } else { // if(DEBUG) // System.out.println("TransferFunctionProvider: edge transfer function " + lhs + " value did change"); // lhs.copyState(rhs); // return CHANGED; // } } @Override public String toString() { return "EDGE-FLOW"; } @Override public int hashCode() { return System.identityHashCode(this); } @Override public boolean equals(Object o) { return this == o; } }; @Override public UnaryOperator<FlowData> getNodeTransferFunction(final ISSABasicBlock node) { return new UnaryOperator<FlowData>() { private final boolean DEBUG = false; @Override public byte evaluate(FlowData lhs, FlowData rhs) { //lhs can be a JoinNodeFlowData, too assert lhs instanceof NormalNodeFlowData; //Note: rhs can be a EdgeFlowData or a NormalNodeFlowData. I guess for only one incoming edge we don't get actual edges because //we said that meet for unary ops is a no-op NormalNodeFlowData rhsData = (rhs instanceof EdgeFlowData) ? ((EdgeFlowData)rhs).getData() : (NormalNodeFlowData)rhs; assert ! rhsData.isInitial(); NormalNodeFlowData data = rhsData.duplicate(((NormalNodeFlowData)lhs).basicBlock); NormalNodeVisitor visitor = data.nodeVisitor(); for(SSAInstruction instruction : node) { instruction.visit(visitor); } if(!node.isEntryBlock() && lhs.stateEquals(data)) { if(DEBUG) System.out.println("TransferFunctionProvider: node transfer function " + lhs + " value did NOT change"); return NOT_CHANGED; } else { if(DEBUG) System.out.println("TransferFunctionProvider: node transfer function " + lhs + " value did change"); lhs.copyState(data); return CHANGED; } } @Override public String toString() { return "NODE-FLOW"; } @Override public int hashCode() { return 9973 * node.hashCode(); } @Override public boolean equals(Object o) { return this == o; } }; } @Override public AbstractMeetOperator<FlowData> getMeetOperator() { return meetOperator; } @Override public UnaryOperator<FlowData> getEdgeTransferFunction(final ISSABasicBlock src, final ISSABasicBlock dst) { return edgeTransferFunction; } @Override public boolean hasEdgeTransferFunctions() { return true; } @Override public boolean hasNodeTransferFunctions() { return true; } }