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 ""; } }