1 package Analysis.SSJava;
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.Comparator;
6 import java.util.HashMap;
7 import java.util.HashSet;
12 import IR.ClassDescriptor;
14 import IR.FieldDescriptor;
15 import IR.MethodDescriptor;
16 import IR.NameDescriptor;
19 import IR.SymbolTable;
20 import IR.VarDescriptor;
21 import IR.Tree.ArrayAccessNode;
22 import IR.Tree.AssignmentNode;
23 import IR.Tree.BlockExpressionNode;
24 import IR.Tree.BlockNode;
25 import IR.Tree.BlockStatementNode;
26 import IR.Tree.CastNode;
27 import IR.Tree.CreateObjectNode;
28 import IR.Tree.DeclarationNode;
29 import IR.Tree.ExpressionNode;
30 import IR.Tree.FieldAccessNode;
31 import IR.Tree.IfStatementNode;
33 import IR.Tree.LiteralNode;
34 import IR.Tree.LoopNode;
35 import IR.Tree.MethodInvokeNode;
36 import IR.Tree.NameNode;
37 import IR.Tree.OpNode;
38 import IR.Tree.ReturnNode;
39 import IR.Tree.SubBlockNode;
40 import IR.Tree.SwitchStatementNode;
41 import IR.Tree.TertiaryNode;
43 public class LocationInference {
46 SSJavaAnalysis ssjava;
48 List<ClassDescriptor> toanalyzeList;
49 List<MethodDescriptor> toanalyzeMethodList;
50 Map<MethodDescriptor, FlowGraph> mapMethodDescriptorToFlowGraph;
54 public LocationInference(SSJavaAnalysis ssjava, State state) {
57 this.toanalyzeList = new ArrayList<ClassDescriptor>();
58 this.toanalyzeMethodList = new ArrayList<MethodDescriptor>();
59 this.mapMethodDescriptorToFlowGraph = new HashMap<MethodDescriptor, FlowGraph>();
62 public void setupToAnalyze() {
63 SymbolTable classtable = state.getClassSymbolTable();
64 toanalyzeList.clear();
65 toanalyzeList.addAll(classtable.getValueSet());
66 Collections.sort(toanalyzeList, new Comparator<ClassDescriptor>() {
67 public int compare(ClassDescriptor o1, ClassDescriptor o2) {
68 return o1.getClassName().compareToIgnoreCase(o2.getClassName());
73 public void setupToAnalazeMethod(ClassDescriptor cd) {
75 SymbolTable methodtable = cd.getMethodTable();
76 toanalyzeMethodList.clear();
77 toanalyzeMethodList.addAll(methodtable.getValueSet());
78 Collections.sort(toanalyzeMethodList, new Comparator<MethodDescriptor>() {
79 public int compare(MethodDescriptor o1, MethodDescriptor o2) {
80 return o1.getSymbol().compareToIgnoreCase(o2.getSymbol());
85 public boolean toAnalyzeMethodIsEmpty() {
86 return toanalyzeMethodList.isEmpty();
89 public boolean toAnalyzeIsEmpty() {
90 return toanalyzeList.isEmpty();
93 public ClassDescriptor toAnalyzeNext() {
94 return toanalyzeList.remove(0);
97 public MethodDescriptor toAnalyzeMethodNext() {
98 return toanalyzeMethodList.remove(0);
101 public void inference() {
103 // 2) construct value flow graph
107 while (!toAnalyzeIsEmpty()) {
108 ClassDescriptor cd = toAnalyzeNext();
110 setupToAnalazeMethod(cd);
111 while (!toAnalyzeMethodIsEmpty()) {
112 MethodDescriptor md = toAnalyzeMethodNext();
113 if (ssjava.needTobeAnnotated(md)) {
114 if (state.SSJAVADEBUG) {
115 System.out.println("SSJAVA: Constructing a flow graph: " + md);
117 FlowGraph fg = new FlowGraph(md);
118 mapMethodDescriptorToFlowGraph.put(md, fg);
119 analyzeMethodBody(cd, md);
126 private void analyzeMethodBody(ClassDescriptor cd, MethodDescriptor md) {
127 BlockNode bn = state.getMethodBody(md);
128 analyzeBlockNode(md, md.getParameterTable(), bn);
131 private void analyzeBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
133 bn.getVarTable().setParent(nametable);
134 for (int i = 0; i < bn.size(); i++) {
135 BlockStatementNode bsn = bn.get(i);
136 analyzeBlockStatementNode(md, bn.getVarTable(), bsn);
141 private void analyzeBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
142 BlockStatementNode bsn) {
144 switch (bsn.kind()) {
145 case Kind.BlockExpressionNode:
146 analyzeBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
149 case Kind.DeclarationNode:
150 analyzeFlowDeclarationNode(md, nametable, (DeclarationNode) bsn, new NTuple<Descriptor>());
153 case Kind.IfStatementNode:
154 analyzeIfStatementNode(md, nametable, (IfStatementNode) bsn);
158 analyzeLoopNode(md, nametable, (LoopNode) bsn);
161 case Kind.ReturnNode:
162 analyzeReturnNode(md, nametable, (ReturnNode) bsn);
165 case Kind.SubBlockNode:
166 analyzeSubBlockNode(md, nametable, (SubBlockNode) bsn);
169 case Kind.ContinueBreakNode:
172 case Kind.SwitchStatementNode:
173 analyzeSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn);
180 private void analyzeSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
181 SwitchStatementNode bsn) {
182 // TODO Auto-generated method stub
186 private void analyzeSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode bsn) {
187 // TODO Auto-generated method stub
191 private void analyzeReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode bsn) {
192 // TODO Auto-generated method stub
196 private void analyzeLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode bsn) {
197 // TODO Auto-generated method stub
201 private void analyzeIfStatementNode(MethodDescriptor md, SymbolTable nametable,
202 IfStatementNode bsn) {
203 // TODO Auto-generated method stub
207 private NTuple<Descriptor> analyzeFlowDeclarationNode(MethodDescriptor md, SymbolTable nametable,
208 DeclarationNode dn, NTuple<Descriptor> base) {
210 VarDescriptor vd = dn.getVarDescriptor();
212 getFlowGraph(md).createNewFlowNode(base);
214 if (dn.getExpression() != null) {
216 NTuple<Descriptor> rhsDescTuple =
217 analyzeFlowExpressionNode(md, nametable, dn.getExpression(), new NTuple<Descriptor>());
219 // add a new flow edge from rhs to lhs
220 if (rhsDescTuple != null) { // rhs is null when values come from the top
222 getFlowGraph(md).addValueFlowEdge(rhsDescTuple, base);
231 private void analyzeBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
232 BlockExpressionNode ben) {
233 analyzeFlowExpressionNode(md, nametable, ben.getExpression(), null);
236 private NTuple<Descriptor> analyzeFlowExpressionNode(MethodDescriptor md, SymbolTable nametable,
237 ExpressionNode en, NTuple<Descriptor> base) {
241 case Kind.AssignmentNode:
242 analyzeFlowAssignmentNode(md, nametable, (AssignmentNode) en, base);
245 case Kind.FieldAccessNode:
246 analyzeFieldAccessNode(md, nametable, (FieldAccessNode) en);
250 return analyzeFlowNameNode(md, nametable, (NameNode) en, base);
253 // return analyzeOpNode(md, nametable, (OpNode) en, new
254 // HashSet<FlowNode>());
257 case Kind.CreateObjectNode:
258 analyzeCreateObjectNode(md, nametable, (CreateObjectNode) en);
261 case Kind.ArrayAccessNode:
262 analyzeArrayAccessNode(md, nametable, (ArrayAccessNode) en);
265 case Kind.LiteralNode:
266 analyzeLiteralNode(md, nametable, (LiteralNode) en);
269 case Kind.MethodInvokeNode:
270 analyzeMethodInvokeNode(md, nametable, (MethodInvokeNode) en);
273 case Kind.TertiaryNode:
274 analyzeTertiaryNode(md, nametable, (TertiaryNode) en);
278 analyzeCastNode(md, nametable, (CastNode) en);
281 // case Kind.InstanceOfNode:
282 // checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td);
285 // case Kind.ArrayInitializerNode:
286 // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en,
290 // case Kind.ClassTypeNode:
291 // checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
294 // case Kind.OffsetNode:
295 // checkOffsetNode(md, nametable, (OffsetNode)en, td);
303 private void analyzeCastNode(MethodDescriptor md, SymbolTable nametable, CastNode en) {
304 // TODO Auto-generated method stub
308 private void analyzeTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode en) {
309 // TODO Auto-generated method stub
313 private void analyzeMethodInvokeNode(MethodDescriptor md, SymbolTable nametable,
314 MethodInvokeNode en) {
315 // TODO Auto-generated method stub
319 private void analyzeLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode en) {
320 // TODO Auto-generated method stub
324 private void analyzeArrayAccessNode(MethodDescriptor md, SymbolTable nametable, ArrayAccessNode en) {
325 // TODO Auto-generated method stub
329 private void analyzeCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
330 CreateObjectNode en) {
331 // TODO Auto-generated method stub
335 private Set<FlowNode> analyzeOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,
336 Set<FlowNode> nodeSet) {
338 ClassDescriptor cd = md.getClassDesc();
341 NTuple<Descriptor> leftOpTuple =
342 analyzeFlowExpressionNode(md, nametable, on.getLeft(), new NTuple<Descriptor>());
344 if (on.getRight() != null) {
346 NTuple<Descriptor> rightOpTuple =
347 analyzeFlowExpressionNode(md, nametable, on.getRight(), new NTuple<Descriptor>());
350 Operation op = on.getOp();
352 switch (op.getOp()) {
354 case Operation.UNARYPLUS:
355 case Operation.UNARYMINUS:
356 case Operation.LOGIC_NOT:
360 case Operation.LOGIC_OR:
361 case Operation.LOGIC_AND:
363 case Operation.BIT_OR:
364 case Operation.BIT_XOR:
365 case Operation.BIT_AND:
366 case Operation.ISAVAILABLE:
367 case Operation.EQUAL:
368 case Operation.NOTEQUAL:
378 case Operation.LEFTSHIFT:
379 case Operation.RIGHTSHIFT:
380 case Operation.URIGHTSHIFT:
382 Set<CompositeLocation> inputSet = new HashSet<CompositeLocation>();
383 // inputSet.add(leftLoc);
384 // inputSet.add(rightLoc);
385 // CompositeLocation glbCompLoc =
386 // CompositeLattice.calculateGLB(inputSet, generateErrorMessage(cd, on));
387 // return glbCompLoc;
390 throw new Error(op.toString());
394 private NTuple<Descriptor> analyzeFlowNameNode(MethodDescriptor md, SymbolTable nametable,
395 NameNode nn, NTuple<Descriptor> base) {
397 NameDescriptor nd = nn.getName();
398 if (nd.getBase() != null) {
399 analyzeFlowExpressionNode(md, nametable, nn.getExpression(), base);
401 String varname = nd.toString();
402 if (varname.equals("this")) {
404 base.add(md.getThis());
408 Descriptor d = (Descriptor) nametable.get(varname);
410 // CompositeLocation localLoc = null;
411 if (d instanceof VarDescriptor) {
412 VarDescriptor vd = (VarDescriptor) d;
413 // localLoc = d2loc.get(vd);
414 // the type of var descriptor has a composite location!
415 // loc = ((SSJavaType)
416 // vd.getType().getExtension()).getCompLoc().clone();
418 } else if (d instanceof FieldDescriptor) {
419 // the type of field descriptor has a location!
420 FieldDescriptor fd = (FieldDescriptor) d;
423 // if it is 'static final', the location has TOP since no one can
425 // loc.addLocation(Location.createTopLocation(md));
428 // if 'static', the location has pre-assigned global loc
429 // MethodLattice<String> localLattice = ssjava.getMethodLattice(md);
430 // String globalLocId = localLattice.getGlobalLoc();
431 // if (globalLocId == null) {
433 // Error("Global location element is not defined in the method " +
436 // Location globalLoc = new Location(md, globalLocId);
438 // loc.addLocation(globalLoc);
441 // the location of field access starts from this, followed by field
443 base.add(md.getThis());
446 // Location fieldLoc = (Location) fd.getType().getExtension();
447 // loc.addLocation(fieldLoc);
449 } else if (d == null) {
450 // access static field
451 // FieldDescriptor fd = nn.getField();
453 // MethodLattice<String> localLattice = ssjava.getMethodLattice(md);
454 // String globalLocId = localLattice.getGlobalLoc();
455 // if (globalLocId == null) {
457 // Error("Method lattice does not define global variable location at "
458 // + generateErrorMessage(md.getClassDesc(), nn));
460 // loc.addLocation(new Location(md, globalLocId));
462 // Location fieldLoc = (Location) fd.getType().getExtension();
463 // loc.addLocation(fieldLoc);
470 getFlowGraph(md).createNewFlowNode(base);
476 private void analyzeFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode en) {
477 // TODO Auto-generated method stub
481 private void analyzeFlowAssignmentNode(MethodDescriptor md, SymbolTable nametable,
482 AssignmentNode an, NTuple<Descriptor> base) {
484 System.out.println("analyzeFlowAssignmentNode=" + an);
486 ClassDescriptor cd = md.getClassDesc();
488 boolean postinc = true;
489 if (an.getOperation().getBaseOp() == null
490 || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
491 .getBaseOp().getOp() != Operation.POSTDEC)) {
495 // if LHS is array access node, need to capture value flows between an array
496 // and its index value
497 analyzeFlowExpressionNode(md, nametable, an.getDest(), base);
498 // NTuple<Descriptor> lhsDescTuple = analyzeFlowExpressionNode(md,
499 // nametable, an.getDest(), base);
502 // analyze value flows of rhs expression
503 NTuple<Descriptor> rhsDescTuple =
504 analyzeFlowExpressionNode(md, nametable, an.getSrc(), new NTuple<Descriptor>());
509 // src & dest are same
515 public FlowGraph getFlowGraph(MethodDescriptor md) {
516 return mapMethodDescriptorToFlowGraph.get(md);