| package org.checkerframework.dataflow.constantpropagation; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import org.checkerframework.dataflow.analysis.FlowExpressions; |
| import org.checkerframework.dataflow.analysis.Store; |
| import org.checkerframework.dataflow.cfg.node.IntegerLiteralNode; |
| import org.checkerframework.dataflow.cfg.node.LocalVariableNode; |
| import org.checkerframework.dataflow.cfg.node.Node; |
| import org.checkerframework.dataflow.constantpropagation.Constant.Type; |
| |
| public class ConstantPropagationStore implements |
| Store<ConstantPropagationStore> { |
| |
| /** Information about variables gathered so far. */ |
| Map<Node, Constant> contents; |
| |
| public ConstantPropagationStore() { |
| contents = new HashMap<>(); |
| } |
| |
| protected ConstantPropagationStore(Map<Node, Constant> contents) { |
| this.contents = contents; |
| } |
| |
| public Constant getInformation(Node n) { |
| if (contents.containsKey(n)) { |
| return contents.get(n); |
| } |
| return new Constant(Type.TOP); |
| } |
| |
| public void mergeInformation(Node n, Constant val) { |
| Constant value; |
| if (contents.containsKey(n)) { |
| value = val.leastUpperBound(contents.get(n)); |
| } else { |
| value = val; |
| } |
| // TODO: remove (only two nodes supported atm) |
| assert n instanceof IntegerLiteralNode |
| || n instanceof LocalVariableNode; |
| contents.put(n, value); |
| } |
| |
| public void setInformation(Node n, Constant val) { |
| // TODO: remove (only two nodes supported atm) |
| assert n instanceof IntegerLiteralNode |
| || n instanceof LocalVariableNode; |
| contents.put(n, val); |
| } |
| |
| @Override |
| public ConstantPropagationStore copy() { |
| return new ConstantPropagationStore(new HashMap<>(contents)); |
| } |
| |
| @Override |
| public ConstantPropagationStore leastUpperBound( |
| ConstantPropagationStore other) { |
| Map<Node, Constant> newContents = new HashMap<>(); |
| |
| // go through all of the information of the other class |
| for (Entry<Node, Constant> e : other.contents.entrySet()) { |
| Node n = e.getKey(); |
| Constant otherVal = e.getValue(); |
| if (contents.containsKey(n)) { |
| // merge if both contain information about a variable |
| newContents.put(n, otherVal.leastUpperBound(contents.get(n))); |
| } else { |
| // add new information |
| newContents.put(n, otherVal); |
| } |
| } |
| |
| for (Entry<Node, Constant> e : contents.entrySet()) { |
| Node n = e.getKey(); |
| Constant thisVal = e.getValue(); |
| if (!other.contents.containsKey(n)) { |
| // add new information |
| newContents.put(n, thisVal); |
| } |
| } |
| |
| return new ConstantPropagationStore(newContents); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o == null) |
| return false; |
| if (!(o instanceof ConstantPropagationStore)) |
| return false; |
| ConstantPropagationStore other = (ConstantPropagationStore) o; |
| // go through all of the information of the other object |
| for (Entry<Node, Constant> e : other.contents.entrySet()) { |
| Node n = e.getKey(); |
| Constant otherVal = e.getValue(); |
| if (otherVal.isBottom()) |
| continue; // no information |
| if (contents.containsKey(n)) { |
| if (!otherVal.equals(contents.get(n))) { |
| return false; |
| } |
| } else { |
| return false; |
| } |
| } |
| // go through all of the information of the this object |
| for (Entry<Node, Constant> e : contents.entrySet()) { |
| Node n = e.getKey(); |
| Constant thisVal = e.getValue(); |
| if (thisVal.isBottom()) |
| continue; // no information |
| if (other.contents.containsKey(n)) { |
| continue; |
| } else { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| int s = 0; |
| for (Entry<Node, Constant> e : contents.entrySet()) { |
| if (!e.getValue().isBottom()) { |
| s += e.hashCode(); |
| } |
| } |
| return s; |
| } |
| |
| @Override |
| public String toString() { |
| // only output local variable information |
| Map<Node, Constant> smallerContents = new HashMap<>(); |
| for (Entry<Node, Constant> e : contents.entrySet()) { |
| if (e.getKey() instanceof LocalVariableNode) { |
| smallerContents.put(e.getKey(), e.getValue()); |
| } |
| } |
| return smallerContents.toString(); |
| } |
| |
| @Override |
| public boolean canAlias(FlowExpressions.Receiver a, |
| FlowExpressions.Receiver b) { |
| return true; |
| } |
| |
| @Override |
| public boolean hasDOToutput() { |
| return false; |
| } |
| |
| @Override |
| public String toDOToutput() { |
| return ""; |
| } |
| |
| } |