/* * This file is part of JOP, the Java Optimized Processor * see <http://www.jopdesign.com/> * * Copyright (C) 2008, Wolfgang Puffitsch * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jopdesign.dfa.analyses; import java.io.Serializable; import java.util.Arrays; @SuppressWarnings({"AccessingNonPublicFieldOfAnotherObject"}) public class Interval implements Serializable { private static final long serialVersionUID = 1L; public static final int TOP = Integer.MAX_VALUE; public static final int BOT = Integer.MIN_VALUE; private int lb; private boolean lv; private int ub; private boolean uv; public Interval(Interval val) { lb = val.lb; lv = val.lv; ub = val.ub; uv = val.uv; } public Interval() { lb = BOT; lv = false; ub = TOP; uv = false; } public Interval(int lb, int ub) { this.lb = lb; this.lv = true; this.ub = ub; this.uv = true; } public int getLb() { return lb; } public void setLb(int lb) { this.lb = lb; this.lv = true; } public boolean hasLb() { return lv; } public int getUb() { return ub; } public void setUb(int ub) { this.ub = ub; this.uv = true; } public boolean hasUb() { return uv; } public void add(int val) { if (lv) { long l = lb+val; if (l > Integer.MAX_VALUE || l < Integer.MIN_VALUE) { lb = BOT; lv = false; } else { lb += val; } } if (uv) { long l = ub+val; if (l > Integer.MAX_VALUE || l < Integer.MIN_VALUE) { ub = TOP; uv = false; } else { ub += val; } } } public void add(Interval val) { if (lv && val.lv) { long l = lb+val.lb; if (l > Integer.MAX_VALUE || l < Integer.MIN_VALUE) { lb = BOT; lv = false; } else { lb += val.lb; } } else { lb = BOT; lv = false; } if (uv && val.uv) { long l = ub+val.ub; if (l > Integer.MAX_VALUE || l < Integer.MIN_VALUE) { ub = TOP; uv = false; } else { ub += val.ub; } } else { ub = TOP; uv = false; } } public void sub(Interval val) { if (lv && val.uv) { long l = lb-val.ub; if (l > Integer.MAX_VALUE || l < Integer.MIN_VALUE) { lb = BOT; lv = false; } else { lb -= val.ub; } } else { lb = BOT; lv = false; } if (uv && val.lv) { long l = ub-val.lb; if (l > Integer.MAX_VALUE || l < Integer.MIN_VALUE) { ub = TOP; uv = false; } else { ub -= val.lb; } } else { ub = TOP; uv = false; } } public void ushr(Interval val) { if (lv && val.lv) { lb >>>= val.lb; ub >>>= val.lb; } else { lb = BOT; lv = false; ub = TOP; uv = false; } } public void shr(Interval val) { if (lv && val.lv) { lb >>= val.lb; ub >>= val.lb; } else { lb = BOT; lv = false; ub = TOP; uv = false; } } public void div(Interval val) { if (lv && val.lv) { if ((val.lb > 0 && val.ub > 0) // val does not contain zero || (val.lb < 0 && val.ub < 0)) { long[] bounds = new long[4]; bounds[0] = lb/val.lb; bounds[1] = lb/val.ub; bounds[2] = ub/val.lb; bounds[3] = ub/val.ub; Arrays.sort(bounds); long resL = bounds[0]; long resU = bounds[3]; if (resL == (long)(int)resL && resU == (long)(int)resU) { lb = (int)resL; ub = (int)resU; } } else { lb = BOT; lv = false; ub = TOP; uv = false; } } else { lb = BOT; lv = false; ub = TOP; uv = false; } } public void mul(Interval val) { if (lv && val.lv) { long[] bounds = new long[4]; bounds[0] = lb*val.lb; bounds[1] = lb*val.ub; bounds[2] = ub*val.lb; bounds[3] = ub*val.ub; Arrays.sort(bounds); long resL = bounds[0]; long resU = bounds[3]; if (resL == (long)(int)resL && resU == (long)(int)resU) { lb = (int)resL; ub = (int)resU; } else { lb = BOT; lv = false; ub = TOP; uv = false; } } else { lb = BOT; lv = false; ub = TOP; uv = false; } } public void neg() { boolean newLv; int newLb; boolean newUv; int newUb; newLv = uv; newLb = -ub; newUv = lv; newUb = -lb; lv = newLv; lb = newLb; uv = newUv; ub = newUb; } public void join(Interval val) { lb = Math.min(lb, val.lb); lv = lv && val.lv; ub = Math.max(ub, val.ub); uv = uv && val.uv; } public void constrain(Interval val) { if (lv && val.lv) { lb = Math.max(lb, val.lb); } else if (val.lv) { lb = val.lb; lv = true; } if (uv && val.uv) { ub = Math.min(ub, val.ub); } else if (val.uv) { ub = val.ub; uv = true; } } public void widen(Interval val) { if (val.lv && lb > val.lb) { lb = val.lb; } if (val.uv && ub < val.ub) { ub = val.ub; } } public int hashCode() { return lb*31 + ub*31*31; } public boolean equals(Object obj) { if (!(obj instanceof Interval)) return false; Interval i = (Interval) obj; if (lb != i.lb || ub != i.ub) return false; return true; } public boolean compare(Object obj) { Interval i = (Interval) obj; if (lb < i.lb || ub > i.ub) return false; return true; } public String toString() { return "("+(lv?lb:"BOT")+","+(uv?ub:"TOP")+")"; } }