2006-11-22 17:38:46 +00:00
|
|
|
/*******************************************************************************
|
|
|
|
* Copyright (c) 2002 - 2006 IBM Corporation.
|
|
|
|
* All rights reserved. This program and the accompanying materials
|
|
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
|
|
* which accompanies this distribution, and is available at
|
|
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
|
|
*
|
|
|
|
* Contributors:
|
|
|
|
* IBM Corporation - initial API and implementation
|
|
|
|
*******************************************************************************/
|
|
|
|
package com.ibm.wala.ssa;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
|
|
import com.ibm.wala.util.collections.HashMapFactory;
|
2007-04-04 13:00:04 +00:00
|
|
|
import com.ibm.wala.util.debug.*;
|
2006-11-22 17:38:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* By convention, symbol numbers start at 1 ... the "this" parameter will be
|
|
|
|
* symbol number 1 in a virtual method.
|
|
|
|
*
|
|
|
|
* @author sfink
|
|
|
|
*/
|
|
|
|
public class SymbolTable {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* value numbers for parameters to this method
|
|
|
|
*/
|
2007-06-01 21:38:35 +00:00
|
|
|
final private int[] parameters;
|
2006-11-22 17:38:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Mapping from Constant -> value number
|
|
|
|
*/
|
2007-06-05 14:01:26 +00:00
|
|
|
final private HashMap<ConstantValue, Integer> constants = HashMapFactory.make(10);
|
2006-11-22 17:38:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
*
|
|
|
|
* @param numberOfParameters
|
|
|
|
* in the IR .. should be ir.getNumberOfParameters()
|
|
|
|
*/
|
|
|
|
public SymbolTable(int numberOfParameters) {
|
|
|
|
parameters = new int[numberOfParameters];
|
|
|
|
for (int i = 0; i < parameters.length; i++) {
|
|
|
|
parameters[i] = getNewValueNumber();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Values. Note: this class must maintain the following invariant:
|
|
|
|
* values.length > nextFreeValueNumber.
|
|
|
|
*/
|
|
|
|
private Value[] values = new Value[5];
|
|
|
|
|
|
|
|
private int nextFreeValueNumber = 1;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Method newSymbol.
|
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public int newSymbol() {
|
|
|
|
return getNewValueNumber();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Common part of getConstant functions.
|
|
|
|
*
|
|
|
|
* @param o
|
|
|
|
* instance of a Java 'boxed-primitive' class, String or NULL.
|
|
|
|
* @return value number for constant.
|
|
|
|
*/
|
2007-04-04 13:00:04 +00:00
|
|
|
int findOrCreateConstant(Object o) {
|
2006-11-22 17:38:46 +00:00
|
|
|
ConstantValue v = new ConstantValue(o);
|
|
|
|
Integer result = constants.get(v);
|
|
|
|
if (result == null) {
|
|
|
|
int r = getNewValueNumber();
|
|
|
|
result = new Integer(r);
|
|
|
|
constants.put(v, result);
|
|
|
|
values[r] = v;
|
|
|
|
}
|
|
|
|
return result.intValue();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setConstantValue(int vn, ConstantValue val) {
|
|
|
|
values[vn] = val;
|
|
|
|
}
|
|
|
|
|
2007-04-04 13:00:04 +00:00
|
|
|
public void setDefaultValue(int vn, final Object defaultValue) {
|
|
|
|
Assertions._assert(values[vn] == null);
|
|
|
|
|
|
|
|
Trace.println("setting default for " + vn + " to " + defaultValue);
|
|
|
|
|
|
|
|
values[vn] = new Value() {
|
|
|
|
public boolean isStringConstant() { return false; }
|
|
|
|
|
|
|
|
public boolean isNullConstant() { return false; }
|
|
|
|
|
|
|
|
public int getDefaultValue(SymbolTable symtab) {
|
|
|
|
return findOrCreateConstant( defaultValue );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
/**
|
|
|
|
* Method getNullConstant.
|
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
public int getNullConstant() {
|
|
|
|
return findOrCreateConstant(null);
|
|
|
|
}
|
|
|
|
|
2007-04-04 13:00:04 +00:00
|
|
|
public int getConstant(boolean b) {
|
|
|
|
return findOrCreateConstant(new Boolean(b));
|
|
|
|
}
|
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
public int getConstant(int i) {
|
|
|
|
return findOrCreateConstant(new Integer(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getConstant(long l) {
|
|
|
|
return findOrCreateConstant(new Long(l));
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getConstant(float f) {
|
|
|
|
return findOrCreateConstant(new Float(f));
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getConstant(double d) {
|
|
|
|
return findOrCreateConstant(new Double(d));
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getConstant(String s) {
|
|
|
|
return findOrCreateConstant(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the value number of the ith parameter
|
|
|
|
*
|
|
|
|
* By convention, for a non-static method, the 0th parameter is 'this'
|
|
|
|
*
|
|
|
|
* @param i
|
|
|
|
* @return int
|
|
|
|
*/
|
2007-01-15 18:31:55 +00:00
|
|
|
public int getParameter(int i) throws IllegalArgumentException {
|
|
|
|
if (parameters.length <= i) {
|
|
|
|
throw new IllegalArgumentException("parameters too small for index " + i + ", length = " + parameters.length);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
return parameters[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void expandForNewValueNumber(int vn) {
|
|
|
|
if (vn >= values.length) {
|
|
|
|
Value[] temp = values;
|
|
|
|
values = new Value[2 * vn];
|
|
|
|
System.arraycopy(temp, 0, values, 0, temp.length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private int getNewValueNumber() {
|
|
|
|
int result = nextFreeValueNumber++;
|
|
|
|
expandForNewValueNumber(result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ensure that the symbol table has allocated space for the particular value
|
|
|
|
* number
|
|
|
|
*
|
|
|
|
* @param i
|
|
|
|
* a value number
|
|
|
|
*/
|
|
|
|
public void ensureSymbol(int i) {
|
|
|
|
if (i != -1) {
|
|
|
|
if (i >= values.length || values[i] == null) {
|
|
|
|
if (nextFreeValueNumber <= i) {
|
|
|
|
nextFreeValueNumber = i + 1;
|
|
|
|
}
|
|
|
|
expandForNewValueNumber(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getValueString(int valueNumber) {
|
|
|
|
if (valueNumber < 0 || valueNumber > getMaxValueNumber() || values[valueNumber] == null) {
|
|
|
|
return "v" + valueNumber;
|
|
|
|
} else {
|
|
|
|
return "v" + valueNumber + ":" + values[valueNumber].toString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isConstant(int v) {
|
|
|
|
return v < values.length && values[v] instanceof ConstantValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isZero(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).isZeroConstant();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isOne(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).isOneConstant();
|
|
|
|
}
|
|
|
|
|
2007-04-04 13:00:04 +00:00
|
|
|
public boolean isTrue(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).isTrueConstant();
|
|
|
|
}
|
|
|
|
|
2007-04-04 17:40:44 +00:00
|
|
|
public boolean isZeroOrFalse(int v) {
|
|
|
|
return isZero(v) || isFalse(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isOneOrTrue(int v) {
|
|
|
|
return isOne(v) || isTrue(v);
|
|
|
|
}
|
|
|
|
|
2007-04-04 13:00:04 +00:00
|
|
|
public boolean isFalse(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).isFalseConstant();
|
|
|
|
}
|
|
|
|
|
2007-04-04 17:40:44 +00:00
|
|
|
public boolean isBooleanOrZeroOneConstant(int v) {
|
|
|
|
return isBooleanConstant(v) || isZero(v) || isOne(v);
|
|
|
|
}
|
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
public boolean isBooleanConstant(int v) {
|
2007-04-04 13:00:04 +00:00
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof Boolean;
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isIntegerConstant(int v) {
|
2007-04-04 13:00:04 +00:00
|
|
|
return (values[v] instanceof ConstantValue) && (((ConstantValue) values[v]).getValue() instanceof Integer);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isLongConstant(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && (((ConstantValue) values[v]).getValue() instanceof Long);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isFloatConstant(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof Float;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isDoubleConstant(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof Double;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isNumberConstant(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof Number;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isStringConstant(int v) {
|
|
|
|
return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof String;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isNullConstant(int v) {
|
|
|
|
return (values.length > v) && (values[v] instanceof ConstantValue) && (((ConstantValue) values[v]).getValue() == null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2007-05-08 21:49:58 +00:00
|
|
|
* @throws IllegalArgumentException if rhs is null
|
2006-11-22 17:38:46 +00:00
|
|
|
*/
|
2007-04-26 17:29:50 +00:00
|
|
|
public int newPhi(int[] rhs) throws IllegalArgumentException {
|
2007-05-08 21:49:58 +00:00
|
|
|
if (rhs == null) {
|
|
|
|
throw new IllegalArgumentException("rhs is null");
|
|
|
|
}
|
2006-11-22 17:38:46 +00:00
|
|
|
int result = getNewValueNumber();
|
2007-05-30 15:16:05 +00:00
|
|
|
SSAPhiInstruction phi = new SSAPhiInstruction(result, rhs.clone());
|
2006-11-22 17:38:46 +00:00
|
|
|
values[result] = new PhiValue(phi);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the PhiValue that is associated with a given value number
|
|
|
|
*/
|
|
|
|
public PhiValue getPhiValue(int valueNumber) {
|
|
|
|
return (PhiValue) values[valueNumber];
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getMaxValueNumber() {
|
|
|
|
// return values.length - 1;
|
|
|
|
return nextFreeValueNumber - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int[] getParameterValueNumbers() {
|
|
|
|
return parameters;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getNumberOfParameters() {
|
|
|
|
return parameters.length;
|
|
|
|
}
|
|
|
|
|
2007-01-15 18:31:55 +00:00
|
|
|
public String getStringValue(int v) throws IllegalArgumentException {
|
|
|
|
if (!isStringConstant(v)) {
|
|
|
|
throw new IllegalArgumentException("not a string constant: value number " + v);
|
|
|
|
}
|
2006-11-22 17:38:46 +00:00
|
|
|
|
|
|
|
return (String) ((ConstantValue) values[v]).getValue();
|
|
|
|
}
|
|
|
|
|
2007-01-15 18:31:55 +00:00
|
|
|
public double getDoubleValue(int v) throws IllegalArgumentException {
|
|
|
|
if (!isNumberConstant(v)) {
|
|
|
|
throw new IllegalArgumentException("value number " + v + " is not a numeric constant.");
|
|
|
|
}
|
2006-11-22 17:38:46 +00:00
|
|
|
return ((Number) ((ConstantValue) values[v]).getValue()).doubleValue();
|
|
|
|
}
|
2007-06-25 18:56:14 +00:00
|
|
|
|
|
|
|
public int getIntValue(int v) throws IllegalArgumentException {
|
|
|
|
if (!isNumberConstant(v)) {
|
|
|
|
throw new IllegalArgumentException("value number " + v + " is not a numeric constant.");
|
|
|
|
}
|
|
|
|
return ((Number) ((ConstantValue) values[v]).getValue()).intValue();
|
|
|
|
}
|
2006-11-22 17:38:46 +00:00
|
|
|
|
2007-01-15 18:31:55 +00:00
|
|
|
public Object getConstantValue(int v) throws IllegalArgumentException{
|
|
|
|
if (!isConstant(v)) {
|
|
|
|
throw new IllegalArgumentException("value number " + v + " is not a constant.");
|
|
|
|
}
|
2006-11-22 17:38:46 +00:00
|
|
|
|
|
|
|
Object value = ((ConstantValue) values[v]).getValue();
|
|
|
|
if (value == null) {
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the Value object for given value number or null if we have no
|
|
|
|
* special information about the value
|
|
|
|
*/
|
|
|
|
public Value getValue(int valueNumber) {
|
|
|
|
if (Assertions.verifyAssertions) {
|
|
|
|
if (valueNumber < 1 || valueNumber >= values.length) {
|
|
|
|
Assertions._assert(valueNumber >= 0, "Invalid value number " + valueNumber);
|
|
|
|
Assertions._assert(valueNumber < values.length, "Invalid value number " + valueNumber);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return values[valueNumber];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param valueNumber
|
|
|
|
* @return true iff this valueNumber is a paramter
|
|
|
|
*/
|
|
|
|
public boolean isParameter(int valueNumber) {
|
|
|
|
return valueNumber <= getNumberOfParameters();
|
|
|
|
}
|
|
|
|
}
|