All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.wala.ssa.SymbolTable Maven / Gradle / Ivy

/*
 * 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 com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.debug.Assertions;
import java.util.Arrays;
import java.util.HashMap;

/**
 * A symbol table which associates information with each variable (value number) in an SSA IR.
 *
 * 

By convention, symbol numbers start at 1 ... the "this" parameter will be symbol number 1 in a * virtual method. * *

This class is used heavily during SSA construction by {@link SSABuilder}. */ public class SymbolTable implements Cloneable { private static final int MAX_VALUE_NUMBER = Integer.MAX_VALUE / 4; /** value numbers for parameters to this method */ private final int[] parameters; /** Mapping from Constant -> value number */ private HashMap constants = HashMapFactory.make(10); private boolean copy = false; /** * @param numberOfParameters in the IR .. should be ir.getNumberOfParameters() */ public SymbolTable(int numberOfParameters) { if (numberOfParameters < 0) { throw new IllegalArgumentException("Illegal numberOfParameters: " + 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(); } int findOrCreateConstant(Object o) { return findOrCreateConstant(o, false); } /** * Common part of getConstant functions. * * @param o instance of a Java 'boxed-primitive' class, String or NULL. * @return value number for constant. */ int findOrCreateConstant(Object o, boolean isDefault) { ConstantValue v = new ConstantValue(o); Integer result = constants.get(v); if (result == null) { assert !(copy && !isDefault) : "making value for " + o; int r = getNewValueNumber(); result = r; constants.put(v, result); assert r < nextFreeValueNumber; values[r] = v; } else { assert values[result] instanceof ConstantValue; } return result; } public void setConstantValue(int vn, ConstantValue val) { try { assert vn < nextFreeValueNumber; values[vn] = val; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid vn: " + vn, e); } } private Object[] defaultValues; /** * Set the default value for a value number. The notion of a default value is for use by languages * that do not require variables to be defined before they are used. In this situation, SSA * conversion can fail since it depends on the assumption that values are always defined when * used. The default value is the constant to be used in cases when a given value is used without * having been defined. Currently, this is used only by CAst front ends for languages with this * "feature". */ public void setDefaultValue(int vn, final Object defaultValue) { assert vn < nextFreeValueNumber; if (defaultValues == null) { defaultValues = new Object[vn * 2 + 1]; } if (defaultValues.length <= vn) { defaultValues = Arrays.copyOf(defaultValues, vn * 2 + 1); } defaultValues[vn] = defaultValue; } public int getDefaultValue(int vn) { return findOrCreateConstant(defaultValues[vn], true); } public int getNullConstant() { return findOrCreateConstant(null); } public int getConstant(boolean b) { return findOrCreateConstant(b); } public int getConstant(int i) { return findOrCreateConstant(i); } public int getConstant(long l) { return findOrCreateConstant(l); } public int getConstant(float f) { return findOrCreateConstant(f); } public int getConstant(double d) { return findOrCreateConstant(d); } public int getOtherConstant(Object v) { return findOrCreateConstant(v); } 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' */ public int getParameter(int i) throws IllegalArgumentException { try { return parameters[i]; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid i: " + i, e); } } private void expandForNewValueNumber(int vn) { if (vn >= values.length) { values = Arrays.copyOf(values, 2 * vn); } } 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 < 0 || i > MAX_VALUE_NUMBER) { throw new IllegalArgumentException("Illegal i: " + i); } try { if (i != -1) { if (i >= values.length || values[i] == null) { if (nextFreeValueNumber <= i) { nextFreeValueNumber = i + 1; } expandForNewValueNumber(i); } } } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid i: " + i, e); } } public String getValueString(int valueNumber) { if (valueNumber < 0 || valueNumber > getMaxValueNumber() || values[valueNumber] == null || values[valueNumber] instanceof PhiValue) { return "v" + valueNumber; } else { return "v" + valueNumber + ':' + values[valueNumber].toString(); } } public boolean isConstant(int v) { try { return v < values.length && values[v] instanceof ConstantValue; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isZero(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).isZeroConstant(); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isOne(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).isOneConstant(); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isTrue(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).isTrueConstant(); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isZeroOrFalse(int v) { return isZero(v) || isFalse(v); } public boolean isOneOrTrue(int v) { return isOne(v) || isTrue(v); } public boolean isFalse(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).isFalseConstant(); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isBooleanOrZeroOneConstant(int v) { return isBooleanConstant(v) || isZero(v) || isOne(v); } public boolean isBooleanConstant(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof Boolean; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isIntegerConstant(int v) { try { return (values[v] instanceof ConstantValue) && (((ConstantValue) values[v]).getValue() instanceof Integer); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isLongConstant(int v) { try { return (values[v] instanceof ConstantValue) && (((ConstantValue) values[v]).getValue() instanceof Long); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isFloatConstant(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof Float; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isDoubleConstant(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof Double; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isNumberConstant(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof Number; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isStringConstant(int v) { try { return (values[v] instanceof ConstantValue) && ((ConstantValue) values[v]).getValue() instanceof String; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } public boolean isNullConstant(int v) { try { return (values.length > v) && (values[v] instanceof ConstantValue) && (((ConstantValue) values[v]).getValue() == null); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("invalid v: " + v, e); } } /** * @throws IllegalArgumentException if rhs is null */ public int newPhi(int[] rhs) throws IllegalArgumentException { if (rhs == null) { throw new IllegalArgumentException("rhs is null"); } int result = getNewValueNumber(); SSAPhiInstruction phi = new SSAPhiInstruction(SSAInstruction.NO_INDEX, result, rhs.clone()); assert result < nextFreeValueNumber; values[result] = new PhiValue(phi); return result; } /** Return the PhiValue that is associated with a given value number */ public PhiValue getPhiValue(int valueNumber) { try { return (PhiValue) values[valueNumber]; } catch (ArrayIndexOutOfBoundsException | ClassCastException e) { throw new IllegalArgumentException("invalid valueNumber: " + valueNumber, e); } } public int getMaxValueNumber() { // return values.length - 1; return nextFreeValueNumber - 1; } public int[] getParameterValueNumbers() { return parameters; } public int getNumberOfParameters() { return parameters.length; } public String getStringValue(int v) throws IllegalArgumentException { if (!isStringConstant(v)) { throw new IllegalArgumentException("not a string constant: value number " + v); } return (String) ((ConstantValue) values[v]).getValue(); } public float getFloatValue(int v) throws IllegalArgumentException { if (!isNumberConstant(v)) { throw new IllegalArgumentException("value number " + v + " is not a numeric constant."); } return ((Number) ((ConstantValue) values[v]).getValue()).floatValue(); } public double getDoubleValue(int v) throws IllegalArgumentException { if (!isNumberConstant(v)) { throw new IllegalArgumentException("value number " + v + " is not a numeric constant."); } return ((Number) ((ConstantValue) values[v]).getValue()).doubleValue(); } 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(); } public long getLongValue(int v) throws IllegalArgumentException { if (!isNumberConstant(v)) { throw new IllegalArgumentException("value number " + v + " is not a numeric constant."); } return ((Number) ((ConstantValue) values[v]).getValue()).longValue(); } public Object getConstantValue(int v) throws IllegalArgumentException { if (!isConstant(v)) { throw new IllegalArgumentException("value number " + v + " is not a constant."); } 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 (valueNumber < 1 || valueNumber >= values.length) { throw new IllegalArgumentException("Invalid value number " + valueNumber); } return values[valueNumber]; } /** * @return true iff this valueNumber is a parameter */ public boolean isParameter(int valueNumber) { return valueNumber <= getNumberOfParameters(); } public SymbolTable copy() { try { SymbolTable nt = (SymbolTable) clone(); nt.values = this.values.clone(); if (this.defaultValues != null) { nt.defaultValues = this.defaultValues.clone(); } nt.constants = HashMapFactory.make(this.constants); nt.copy = true; return nt; } catch (CloneNotSupportedException e) { Assertions.UNREACHABLE(); return null; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy