/* Copyright (c) 2006, Sriram Srinivasan * * You may distribute this software under the terms of the license * specified in the file "License" */ package kilim.analysis; import static kilim.Constants.D_UNDEFINED; import static kilim.Constants.D_NULL; import java.util.Arrays; /** * A SSA value that represents all objects produced at a particular * location in the code. Value objects are used by dataflow analysis * (@see BasicBlock) * */ public class Value { public static Object NO_VAL = new Object(); public static Value V_UNDEFINED = new Value(0, D_UNDEFINED, NO_VAL); private String typeDesc; private Object constVal; private int numSites; private int[] sites; public int getNumSites() {return numSites;} public int[] getCreationSites() {return sites;} public String getTypeDesc() {return typeDesc;} public Object getConstVal() {return constVal;} private Value(int aPos, String aDesc, Object aConst) { sites = new int[2]; numSites = 1; sites[0] = aPos; typeDesc = aDesc; constVal = aConst; //System.out.println("V[" + aPos + ":" + aDesc + ((aConst == NO_VAL) ? "" : (": " + aConst)) + "]"); } private Value(int newNumSites, int[] newSites, String newType, Object newConst) { Arrays.sort(newSites, 0, newNumSites); numSites = newNumSites; sites = newSites; typeDesc = newType; constVal = newConst; /*//debug StringBuilder sb = new StringBuilder(80); sb.append("V["); for (int i = 0; i < newNumSites; i++) { if (i > 0) sb.append(","); sb.append(newSites[i]); } sb.append(":").append(newType).append(":"); if (newConst != NO_VAL) { sb.append(": ").append(newConst.toString()); } sb.append("]"); System.out.println(sb); */ } /** * Produces a new value (if necessary), if the instructions are different or * the types are different. The types are merged to form a least common * upper bound, and the instruction sets are unioned. * @param vb * @return this if the result of the merge is no different, or the new value */ public Value merge(Value other) { int[] newSites = new int[this.numSites + other.numSites]; for (int i = 0; i < newSites.length; i++) newSites[i] = -1; int newNumSites = mergeSites(newSites, other); String newType; try { newType = TypeDesc.mergeType(this.typeDesc, other.typeDesc); } catch (IncompatibleTypesException e) { newType = D_UNDEFINED; } Object newConst = (constVal.equals(other.constVal)) ? constVal : NO_VAL; if (newNumSites != numSites || newType != typeDesc || newConst != constVal) { return new Value(newNumSites, newSites, newType, newConst); } else { return this; // no change } } private int mergeSites(int[]newSites, Value other) { int uniqueNumSites = 0; for (int i = 0; i < numSites; i++) { uniqueNumSites += addTo(newSites, sites[i]); } for (int i = 0; i < other.numSites; i++) { uniqueNumSites += addTo(newSites, other.sites[i]); } return uniqueNumSites; } private int addTo(int[] newSites, int site) { for (int i = 0; i < newSites.length; i++) { int s = newSites[i]; if (s == -1) { newSites[i] = site; return 1; // added an element } if (s == site) return 0; // added no elements } return 0; } @Override public boolean equals(Object obj) { // TODO FIXME : This is WRONG. Two values can be created at the same site when // entering a method (all incoming parameter values are given location 0). // That would make two distinct params with the same type equal. if (this == obj) return true; Value other = (Value)obj; if (this.typeDesc.equals(other.typeDesc) && this.constVal.equals(other.constVal) && this.numSites == other.numSites) { // Check sites for (int i = 0; i < this.numSites; i++) { if (sites[i] != other.sites[i]) { return false; } } return true; } return false; } @Override public int hashCode() { int h = typeDesc.hashCode(); for (int i = 0; i < numSites; i++) { h ^= sites[i]; } return h; } public static Value make(int pos, String desc) { return new Value(pos, desc, NO_VAL); } public static Value make(int pos, String desc, Object aConstVal) { return new Value(pos, desc, aConstVal); } public boolean isCategory2() { return category() == 2; } public boolean isCategory1() { return category() == 1; } @Override public String toString() { if (numSites == 0 && typeDesc == D_UNDEFINED) return "undef"; StringBuffer sb = new StringBuffer(40); sb.append(typeDesc).append('['); for (int i = 0; i < numSites; i++) { if (i > 0) sb.append(' '); sb.append(sites[i]); } sb.append(']'); if (constVal != NO_VAL) { sb.append(" == ").append(constVal.toString()); } return sb.toString(); } public boolean isConstant() { return constVal != NO_VAL || typeDesc == D_NULL; } public int category() { return TypeDesc.isDoubleWord(typeDesc) ? 2 : 1; } }