/*******************************************************************************
* Copyright (c) 2007 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.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
* An implementation of {@link SSAIndirectionData} specialized for IRs originated from Shrike.
*/
public class ShrikeIndirectionData implements SSAIndirectionData<ShrikeIndirectionData.ShrikeLocalName> {
/**
* In Shrike, the only "source" level entities which have names relevant to indirect pointer operations are bytecode locals.
*/
public static class ShrikeLocalName implements com.ibm.wala.ssa.SSAIndirectionData.Name {
private final int bytecodeLocalNumber;
public ShrikeLocalName(int bytecodeLocalNumber) {
this.bytecodeLocalNumber = bytecodeLocalNumber;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + bytecodeLocalNumber;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ShrikeLocalName other = (ShrikeLocalName) obj;
if (bytecodeLocalNumber != other.bytecodeLocalNumber)
return false;
return true;
}
@Override
public String toString() {
return "(local:" + bytecodeLocalNumber + ")";
}
}
private final Map<ShrikeLocalName, Integer>[] defs;
private final Map<ShrikeLocalName, Integer>[] uses;
@SuppressWarnings("unchecked")
public ShrikeIndirectionData(int instructionArrayLength) {
defs = new HashMap[instructionArrayLength];
uses = new HashMap[instructionArrayLength];
}
@Override
public int getDef(int instructionIndex, ShrikeLocalName name) {
if (defs[instructionIndex] == null || !defs[instructionIndex].containsKey(name)) {
return -1;
} else {
return defs[instructionIndex].get(name);
}
}
@Override
public int getUse(int instructionIndex, ShrikeLocalName name) {
if (uses[instructionIndex] == null || !uses[instructionIndex].containsKey(name)) {
return -1;
} else {
return uses[instructionIndex].get(name);
}
}
@Override
public void setDef(int instructionIndex, ShrikeLocalName name, int newDef) {
if (defs[instructionIndex] == null) {
defs[instructionIndex] = new HashMap<ShrikeLocalName, Integer>(2);
}
defs[instructionIndex].put(name, newDef);
}
@Override
public void setUse(int instructionIndex, ShrikeLocalName name, int newUse) {
if (uses[instructionIndex] == null) {
uses[instructionIndex] = new HashMap<ShrikeLocalName, Integer>(2);
}
uses[instructionIndex].put(name, newUse);
}
@Override
public Collection<ShrikeLocalName> getNames() {
HashSet<ShrikeLocalName> result = new HashSet<ShrikeLocalName>();
for (int i = 0; i < uses.length; i++) {
if (uses[i] != null) {
result.addAll(uses[i].keySet());
}
if (defs[i] != null) {
result.addAll(defs[i].keySet());
}
}
return result;
}
@Override
public String toString() {
StringBuffer result = new StringBuffer();
for (int i = 0; i < defs.length; i++) {
if (defs[i] != null) {
result.append(i + " <- " + defs[i] + "\n");
}
if (uses[i] != null) {
result.append(i + " -> " + uses[i] + "\n");
}
}
return result.toString();
}
}