From: yeom Date: Tue, 10 Apr 2012 22:48:07 +0000 (+0000) Subject: start implementing basic approach X-Git-Url: http://plrg.eecs.uci.edu/git/?p=IRC.git;a=commitdiff_plain;h=28876fc6038265b38688ea04cd0f5d8241604bd6 start implementing basic approach --- diff --git a/Robust/src/Analysis/SSJava/FlowGraph.java b/Robust/src/Analysis/SSJava/FlowGraph.java new file mode 100644 index 00000000..f9790963 --- /dev/null +++ b/Robust/src/Analysis/SSJava/FlowGraph.java @@ -0,0 +1,96 @@ +package Analysis.SSJava; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import IR.Descriptor; +import IR.MethodDescriptor; + +public class FlowGraph { + + MethodDescriptor md; + + Set nodeSet; + FlowNode thisVarNode; + + // maps the composite representation of field/var descriptors to infer nodes + Map, FlowNode> mapDescTupleToInferNode; + + // maps an infer node to the set of neighbors which is pointed by the node + Map, Set> mapNodeToNeighborSet; + + boolean debug = true; + + public FlowGraph(MethodDescriptor md) { + this.md = md; + nodeSet = new HashSet(); + mapDescTupleToInferNode = new HashMap, FlowNode>(); + mapNodeToNeighborSet = new HashMap, Set>(); + + // create a node for 'this' varialbe + FlowNode thisNode = new FlowNode(null, md.getThis()); + NTuple thisVarTuple = new NTuple(); + thisVarTuple.add(md.getThis()); + mapDescTupleToInferNode.put(thisVarTuple, thisNode); + thisVarNode = thisNode; + + } + + public void addNeighbor(FlowNode node, FlowNode neighbor) { + Set set = mapNodeToNeighborSet.get(node); + if (set == null) { + set = new HashSet(); + } + set.add(neighbor); + + System.out.println("add a new neighbor " + neighbor + " to " + node); + } + + public void addValueFlowEdge(NTuple fromDescTuple, NTuple toDescTuple) { + + FlowNode fromNode = mapDescTupleToInferNode.get(fromDescTuple); + FlowNode toNode = mapDescTupleToInferNode.get(toDescTuple); + + System.out.println("create an edge from " + fromNode + " to " + toNode); + + int fromTupleSize = fromDescTuple.size(); + NTuple curTuple = new NTuple(); + for (int i = 0; i < fromTupleSize; i++) { + Descriptor desc = fromDescTuple.get(i); + curTuple.add(desc); + addNeighbor(getInferNode(curTuple), toNode); + } + + int toTupleSize = toDescTuple.size(); + curTuple = new NTuple(); + for (int i = 0; i < toTupleSize; i++) { + Descriptor desc = toDescTuple.get(i); + curTuple.add(desc); + addNeighbor(fromNode, getInferNode(curTuple)); + } + + } + + public FlowNode getInferNode(NTuple descTuple) { + if (mapDescTupleToInferNode.containsKey(descTuple)) { + return mapDescTupleToInferNode.get(descTuple); + } + return null; + } + + public FlowNode getThisVarNode() { + return thisVarNode; + } + + public void createNewFlowNode(NTuple base) { + + FlowNode node = new FlowNode(base); + mapDescTupleToInferNode.put(base, node); + + System.out.println("Creating new node=" + node); + + } + +} diff --git a/Robust/src/Analysis/SSJava/FlowNode.java b/Robust/src/Analysis/SSJava/FlowNode.java new file mode 100644 index 00000000..cc7d4ee1 --- /dev/null +++ b/Robust/src/Analysis/SSJava/FlowNode.java @@ -0,0 +1,46 @@ +package Analysis.SSJava; + +import java.util.Set; + +import IR.Descriptor; + +public class FlowNode { + + // descriptor tuple is a unique identifier of the flow node + private NTuple descTuple; + + // if the infer node represents the base type of field access, + // this set contains fields of the base type + private Set fieldNodeSet; + + public FlowNode(Descriptor desc) { + this(null, desc); + } + + public FlowNode(NTuple base) { + this(base, null); + } + + public FlowNode(NTuple base, Descriptor desc) { + descTuple = new NTuple(); + if (base != null) { + descTuple.addAll(base); + } + if (desc != null) { + descTuple.add(desc); + } + } + + public NTuple getDescTuple() { + return descTuple; + } + + public Descriptor getOwnDescriptor() { + return descTuple.get(descTuple.size() - 1); + } + + public String toString() { + return "[FlowNode]::" + descTuple; + } + +} diff --git a/Robust/src/Analysis/SSJava/InferGraph.java b/Robust/src/Analysis/SSJava/InferGraph.java deleted file mode 100644 index e49b62d8..00000000 --- a/Robust/src/Analysis/SSJava/InferGraph.java +++ /dev/null @@ -1,71 +0,0 @@ -package Analysis.SSJava; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import IR.Descriptor; - -public class InferGraph { - - Set nodeSet; - - // having one location for the top location - private static final int topLocationID = 1; - - // unique ID seed - private static int uniqueID = 10000; - - // maps descriptors (field and local var descriptors) to its unique integer id - Map mapDescriptorToUniqueID; - - // maps field/var descriptros to infer nodes - Map mapDescToInferNode; - - boolean debug = true; - - public InferGraph() { - nodeSet = new HashSet(); - mapDescToInferNode = new HashMap(); - mapDescriptorToUniqueID = new HashMap(); - } - - public void addValueFlowEdge(Descriptor fromDesc, Descriptor toDesc) { - - } - - public InferNode getInferNode(Descriptor desc) { - if (mapDescToInferNode.containsKey(desc)) { - - } - return null; - } - - public void assignTopLocationToDescriptor(Descriptor desc) { - mapDescriptorToUniqueID.put(desc, Integer.valueOf((topLocationID))); - debug_uniqueid_print(desc); - } - - public void assignUniqueIDtoDescriptor(Descriptor desc) { - mapDescriptorToUniqueID.put(desc, getUniqueID()); - debug_uniqueid_print(desc); - } - - private int getUniqueID() { - return uniqueID++; - } - - private void debug_uniqueid_print(Descriptor d) { - if (debug) { - int id = mapDescriptorToUniqueID.get(d).intValue(); - System.out.print(d + " -> "); - if (id == topLocationID) { - System.out.println("TOP"); - } else { - System.out.println(id); - } - - } - } -} diff --git a/Robust/src/Analysis/SSJava/InferNode.java b/Robust/src/Analysis/SSJava/InferNode.java deleted file mode 100644 index b00b4e0f..00000000 --- a/Robust/src/Analysis/SSJava/InferNode.java +++ /dev/null @@ -1,26 +0,0 @@ -package Analysis.SSJava; - -import IR.Descriptor; - -public class InferNode { - - private Descriptor desc; - private int id; - - public Descriptor getDesc() { - return desc; - } - - public void setDesc(Descriptor desc) { - this.desc = desc; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - -} diff --git a/Robust/src/Analysis/SSJava/LocationInference.java b/Robust/src/Analysis/SSJava/LocationInference.java index 2bb1330b..275b5293 100644 --- a/Robust/src/Analysis/SSJava/LocationInference.java +++ b/Robust/src/Analysis/SSJava/LocationInference.java @@ -4,14 +4,17 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.Iterator; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import IR.ClassDescriptor; import IR.Descriptor; import IR.FieldDescriptor; import IR.MethodDescriptor; +import IR.NameDescriptor; +import IR.Operation; import IR.State; import IR.SymbolTable; import IR.VarDescriptor; @@ -34,7 +37,6 @@ import IR.Tree.NameNode; import IR.Tree.OpNode; import IR.Tree.ReturnNode; import IR.Tree.SubBlockNode; -import IR.Tree.SwitchBlockNode; import IR.Tree.SwitchStatementNode; import IR.Tree.TertiaryNode; @@ -45,17 +47,16 @@ public class LocationInference { List toanalyzeList; List toanalyzeMethodList; + Map mapMethodDescriptorToFlowGraph; boolean debug = true; - InferGraph graph; - public LocationInference(SSJavaAnalysis ssjava, State state) { this.ssjava = ssjava; this.state = state; this.toanalyzeList = new ArrayList(); this.toanalyzeMethodList = new ArrayList(); - this.graph = new InferGraph(); + this.mapMethodDescriptorToFlowGraph = new HashMap(); } public void setupToAnalyze() { @@ -97,51 +98,8 @@ public class LocationInference { return toanalyzeMethodList.remove(0); } - private void checkDeclarationInClass(ClassDescriptor cd) { - // Check to see that fields are okay - for (Iterator field_it = cd.getFields(); field_it.hasNext();) { - FieldDescriptor fd = (FieldDescriptor) field_it.next(); - - if (!(fd.isFinal() && fd.isStatic())) { - analyzeFieldDeclaration(cd, fd); - } else { - // for static final, assign top location by default - graph.assignTopLocationToDescriptor(fd); - } - } - } - - private void analyzeFieldDeclaration(ClassDescriptor cd, FieldDescriptor fd) { - graph.assignUniqueIDtoDescriptor(fd); - } - public void inference() { - // 1) assign a unique id to every field & variable - setupToAnalyze(); - - while (!toAnalyzeIsEmpty()) { - ClassDescriptor cd = toAnalyzeNext(); - - System.out.println("SSJAVA: Location Inference on the class: " + cd); - checkDeclarationInClass(cd); - - setupToAnalazeMethod(cd); - while (!toAnalyzeMethodIsEmpty()) { - MethodDescriptor md = toAnalyzeMethodNext(); - - if (ssjava.needTobeAnnotated(md)) { - // assigns unique id to the method parameters - assignUniqueIDMethodParamteres(cd, md); - - if (state.SSJAVADEBUG) { - System.out.println("SSJAVA: Location Inference on the method: " + md); - } - assignUniqueIDMethodBody(cd, md); - } - } - } - // 2) construct value flow graph setupToAnalyze(); @@ -156,6 +114,8 @@ public class LocationInference { if (state.SSJAVADEBUG) { System.out.println("SSJAVA: Constructing a flow graph: " + md); } + FlowGraph fg = new FlowGraph(md); + mapMethodDescriptorToFlowGraph.put(md, fg); analyzeMethodBody(cd, md); } } @@ -165,109 +125,395 @@ public class LocationInference { private void analyzeMethodBody(ClassDescriptor cd, MethodDescriptor md) { BlockNode bn = state.getMethodBody(md); - // checkLocationFromBlockNode(md, md.getParameterTable(), bn, constraints); + analyzeBlockNode(md, md.getParameterTable(), bn); } - private void assignUniqueIDMethodParamteres(ClassDescriptor cd, MethodDescriptor md) { - - List paramList = new ArrayList(); - for (int i = 0; i < md.numParameters(); i++) { - // process annotations on method parameters - VarDescriptor vd = (VarDescriptor) md.getParameter(i); - graph.assignUniqueIDtoDescriptor(vd); - } - - } - - private void assignUniqueIDMethodBody(ClassDescriptor cd, MethodDescriptor md) { - BlockNode bn = state.getMethodBody(md); - assignUniqueIDBlockNode(md, md.getParameterTable(), bn); - } - - private void assignUniqueIDBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) { + private void analyzeBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) { bn.getVarTable().setParent(nametable); for (int i = 0; i < bn.size(); i++) { BlockStatementNode bsn = bn.get(i); - assignUniqueIDBlockStatementNode(md, bn.getVarTable(), bsn); + analyzeBlockStatementNode(md, bn.getVarTable(), bsn); } } - private void assignUniqueIDBlockStatementNode(MethodDescriptor md, SymbolTable nametable, + private void analyzeBlockStatementNode(MethodDescriptor md, SymbolTable nametable, BlockStatementNode bsn) { switch (bsn.kind()) { + case Kind.BlockExpressionNode: + analyzeBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn); + break; case Kind.DeclarationNode: - assignUniqueIDDeclarationNode(md, nametable, (DeclarationNode) bsn); + analyzeFlowDeclarationNode(md, nametable, (DeclarationNode) bsn, new NTuple()); break; case Kind.IfStatementNode: - assignUniqueIDIfStatementNode(md, nametable, (IfStatementNode) bsn); + analyzeIfStatementNode(md, nametable, (IfStatementNode) bsn); break; case Kind.LoopNode: - assignUniqueIDLoopNode(md, nametable, (LoopNode) bsn); + analyzeLoopNode(md, nametable, (LoopNode) bsn); + break; + + case Kind.ReturnNode: + analyzeReturnNode(md, nametable, (ReturnNode) bsn); break; case Kind.SubBlockNode: - assignUniqueIDSubBlockNode(md, nametable, (SubBlockNode) bsn); + analyzeSubBlockNode(md, nametable, (SubBlockNode) bsn); break; case Kind.ContinueBreakNode: break; case Kind.SwitchStatementNode: - assignUniqueIDSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn); + analyzeSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn); + break; + } } - private void assignUniqueIDSwitchStatementNode(MethodDescriptor md, SymbolTable nametable, - SwitchStatementNode ssn) { - BlockNode sbn = ssn.getSwitchBody(); - for (int i = 0; i < sbn.size(); i++) { - SwitchBlockNode node = (SwitchBlockNode) sbn.get(i); - assignUniqueIDBlockNode(md, nametable, node.getSwitchBlockStatement()); + private void analyzeSwitchStatementNode(MethodDescriptor md, SymbolTable nametable, + SwitchStatementNode bsn) { + // TODO Auto-generated method stub + + } + + private void analyzeSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode bsn) { + // TODO Auto-generated method stub + + } + + private void analyzeReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode bsn) { + // TODO Auto-generated method stub + + } + + private void analyzeLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode bsn) { + // TODO Auto-generated method stub + + } + + private void analyzeIfStatementNode(MethodDescriptor md, SymbolTable nametable, + IfStatementNode bsn) { + // TODO Auto-generated method stub + + } + + private NTuple analyzeFlowDeclarationNode(MethodDescriptor md, SymbolTable nametable, + DeclarationNode dn, NTuple base) { + + VarDescriptor vd = dn.getVarDescriptor(); + base.add(vd); + getFlowGraph(md).createNewFlowNode(base); + + if (dn.getExpression() != null) { + + NTuple rhsDescTuple = + analyzeFlowExpressionNode(md, nametable, dn.getExpression(), new NTuple()); + + // add a new flow edge from rhs to lhs + if (rhsDescTuple != null) { // rhs is null when values come from the top + // location + getFlowGraph(md).addValueFlowEdge(rhsDescTuple, base); + } + } + + return null; + } - private void assignUniqueIDSubBlockNode(MethodDescriptor md, SymbolTable nametable, - SubBlockNode sbn) { - assignUniqueIDBlockNode(md, nametable, sbn.getBlockNode()); + private void analyzeBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, + BlockExpressionNode ben) { + analyzeFlowExpressionNode(md, nametable, ben.getExpression(), null); } - private void assignUniqueIDLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) { + private NTuple analyzeFlowExpressionNode(MethodDescriptor md, SymbolTable nametable, + ExpressionNode en, NTuple base) { - if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) { - assignUniqueIDBlockNode(md, nametable, ln.getBody()); - } else { - // check 'for loop' case - BlockNode bn = ln.getInitializer(); - bn.getVarTable().setParent(nametable); - assignUniqueIDBlockNode(md, bn.getVarTable(), ln.getUpdate()); - assignUniqueIDBlockNode(md, bn.getVarTable(), ln.getBody()); + switch (en.kind()) { + + case Kind.AssignmentNode: + analyzeFlowAssignmentNode(md, nametable, (AssignmentNode) en, base); + break; + + case Kind.FieldAccessNode: + analyzeFieldAccessNode(md, nametable, (FieldAccessNode) en); + break; + + case Kind.NameNode: + return analyzeFlowNameNode(md, nametable, (NameNode) en, base); + + case Kind.OpNode: + // return analyzeOpNode(md, nametable, (OpNode) en, new + // HashSet()); + break; + + case Kind.CreateObjectNode: + analyzeCreateObjectNode(md, nametable, (CreateObjectNode) en); + break; + + case Kind.ArrayAccessNode: + analyzeArrayAccessNode(md, nametable, (ArrayAccessNode) en); + break; + + case Kind.LiteralNode: + analyzeLiteralNode(md, nametable, (LiteralNode) en); + break; + + case Kind.MethodInvokeNode: + analyzeMethodInvokeNode(md, nametable, (MethodInvokeNode) en); + break; + + case Kind.TertiaryNode: + analyzeTertiaryNode(md, nametable, (TertiaryNode) en); + break; + + case Kind.CastNode: + analyzeCastNode(md, nametable, (CastNode) en); + break; + + // case Kind.InstanceOfNode: + // checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td); + // return null; + + // case Kind.ArrayInitializerNode: + // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en, + // td); + // return null; + + // case Kind.ClassTypeNode: + // checkClassTypeNode(md, nametable, (ClassTypeNode) en, td); + // return null; + + // case Kind.OffsetNode: + // checkOffsetNode(md, nametable, (OffsetNode)en, td); + // return null; + + } + return null; + + } + + private void analyzeCastNode(MethodDescriptor md, SymbolTable nametable, CastNode en) { + // TODO Auto-generated method stub + + } + + private void analyzeTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode en) { + // TODO Auto-generated method stub + + } + + private void analyzeMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, + MethodInvokeNode en) { + // TODO Auto-generated method stub + + } + + private void analyzeLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode en) { + // TODO Auto-generated method stub + + } + + private void analyzeArrayAccessNode(MethodDescriptor md, SymbolTable nametable, ArrayAccessNode en) { + // TODO Auto-generated method stub + + } + + private void analyzeCreateObjectNode(MethodDescriptor md, SymbolTable nametable, + CreateObjectNode en) { + // TODO Auto-generated method stub + + } + + private Set analyzeOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, + Set nodeSet) { + + ClassDescriptor cd = md.getClassDesc(); + + // left operand + NTuple leftOpTuple = + analyzeFlowExpressionNode(md, nametable, on.getLeft(), new NTuple()); + + if (on.getRight() != null) { + // right operand + NTuple rightOpTuple = + analyzeFlowExpressionNode(md, nametable, on.getRight(), new NTuple()); } + Operation op = on.getOp(); + + switch (op.getOp()) { + + case Operation.UNARYPLUS: + case Operation.UNARYMINUS: + case Operation.LOGIC_NOT: + // single operand + // return leftLoc; + + case Operation.LOGIC_OR: + case Operation.LOGIC_AND: + case Operation.COMP: + case Operation.BIT_OR: + case Operation.BIT_XOR: + case Operation.BIT_AND: + case Operation.ISAVAILABLE: + case Operation.EQUAL: + case Operation.NOTEQUAL: + case Operation.LT: + case Operation.GT: + case Operation.LTE: + case Operation.GTE: + case Operation.ADD: + case Operation.SUB: + case Operation.MULT: + case Operation.DIV: + case Operation.MOD: + case Operation.LEFTSHIFT: + case Operation.RIGHTSHIFT: + case Operation.URIGHTSHIFT: + + Set inputSet = new HashSet(); + // inputSet.add(leftLoc); + // inputSet.add(rightLoc); + // CompositeLocation glbCompLoc = + // CompositeLattice.calculateGLB(inputSet, generateErrorMessage(cd, on)); + // return glbCompLoc; + + default: + throw new Error(op.toString()); + } } - private void assignUniqueIDIfStatementNode(MethodDescriptor md, SymbolTable nametable, - IfStatementNode isn) { + private NTuple analyzeFlowNameNode(MethodDescriptor md, SymbolTable nametable, + NameNode nn, NTuple base) { - assignUniqueIDBlockNode(md, nametable, isn.getTrueBlock()); + NameDescriptor nd = nn.getName(); + if (nd.getBase() != null) { + analyzeFlowExpressionNode(md, nametable, nn.getExpression(), base); + } else { + String varname = nd.toString(); + if (varname.equals("this")) { + // 'this' itself! + base.add(md.getThis()); + return base; + } + + Descriptor d = (Descriptor) nametable.get(varname); + + // CompositeLocation localLoc = null; + if (d instanceof VarDescriptor) { + VarDescriptor vd = (VarDescriptor) d; + // localLoc = d2loc.get(vd); + // the type of var descriptor has a composite location! + // loc = ((SSJavaType) + // vd.getType().getExtension()).getCompLoc().clone(); + base.add(vd); + } else if (d instanceof FieldDescriptor) { + // the type of field descriptor has a location! + FieldDescriptor fd = (FieldDescriptor) d; + if (fd.isStatic()) { + if (fd.isFinal()) { + // if it is 'static final', the location has TOP since no one can + // change its value + // loc.addLocation(Location.createTopLocation(md)); + // return loc; + } else { + // if 'static', the location has pre-assigned global loc + // MethodLattice localLattice = ssjava.getMethodLattice(md); + // String globalLocId = localLattice.getGlobalLoc(); + // if (globalLocId == null) { + // throw new + // Error("Global location element is not defined in the method " + + // md); + // } + // Location globalLoc = new Location(md, globalLocId); + // + // loc.addLocation(globalLoc); + } + } else { + // the location of field access starts from this, followed by field + // location + base.add(md.getThis()); + } - if (isn.getFalseBlock() != null) { - assignUniqueIDBlockNode(md, nametable, isn.getFalseBlock()); + // Location fieldLoc = (Location) fd.getType().getExtension(); + // loc.addLocation(fieldLoc); + base.add(fd); + } else if (d == null) { + // access static field + // FieldDescriptor fd = nn.getField(); + // + // MethodLattice localLattice = ssjava.getMethodLattice(md); + // String globalLocId = localLattice.getGlobalLoc(); + // if (globalLocId == null) { + // throw new + // Error("Method lattice does not define global variable location at " + // + generateErrorMessage(md.getClassDesc(), nn)); + // } + // loc.addLocation(new Location(md, globalLocId)); + // + // Location fieldLoc = (Location) fd.getType().getExtension(); + // loc.addLocation(fieldLoc); + // + // return loc; + + } } + getFlowGraph(md).createNewFlowNode(base); + + return base; + } - private void assignUniqueIDDeclarationNode(MethodDescriptor md, SymbolTable nametable, - DeclarationNode dn) { + private void analyzeFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode en) { + // TODO Auto-generated method stub - VarDescriptor vd = dn.getVarDescriptor(); - graph.assignUniqueIDtoDescriptor(vd); + } + + private void analyzeFlowAssignmentNode(MethodDescriptor md, SymbolTable nametable, + AssignmentNode an, NTuple base) { + + System.out.println("analyzeFlowAssignmentNode=" + an); + + ClassDescriptor cd = md.getClassDesc(); + + boolean postinc = true; + if (an.getOperation().getBaseOp() == null + || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation() + .getBaseOp().getOp() != Operation.POSTDEC)) { + postinc = false; + } + + // if LHS is array access node, need to capture value flows between an array + // and its index value + analyzeFlowExpressionNode(md, nametable, an.getDest(), base); + // NTuple lhsDescTuple = analyzeFlowExpressionNode(md, + // nametable, an.getDest(), base); + + if (!postinc) { + // analyze value flows of rhs expression + NTuple rhsDescTuple = + analyzeFlowExpressionNode(md, nametable, an.getSrc(), new NTuple()); + + } else { + + // postinc case + // src & dest are same + + } + + } + + public FlowGraph getFlowGraph(MethodDescriptor md) { + return mapMethodDescriptorToFlowGraph.get(md); } }