191 lines
5.1 KiB
Java
191 lines
5.1 KiB
Java
/*******************************************************************************
|
|
* 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.ArrayList;
|
|
import java.util.Iterator;
|
|
|
|
import com.ibm.wala.util.collections.EmptyIterator;
|
|
import com.ibm.wala.util.collections.Iterator2Iterable;
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
import com.ibm.wala.util.intset.IntIterator;
|
|
import com.ibm.wala.util.intset.IntSet;
|
|
import com.ibm.wala.util.intset.IntSetUtil;
|
|
import com.ibm.wala.util.intset.MutableIntSet;
|
|
|
|
/**
|
|
* An object which represent Def-Use information for an SSA {@link IR}
|
|
*/
|
|
public class DefUse {
|
|
static final boolean DEBUG = false;
|
|
|
|
/**
|
|
* A mapping from integer (value number) -> {@link SSAInstruction} that defines the value
|
|
*/
|
|
final private SSAInstruction[] defs;
|
|
|
|
/**
|
|
* A mapping from integer (value number) -> bit vector holding integers representing instructions that use the value number
|
|
*/
|
|
final private MutableIntSet[] uses;
|
|
|
|
/**
|
|
* A Mapping from integer -> Instruction
|
|
*/
|
|
final protected ArrayList<SSAInstruction> allInstructions = new ArrayList<>();
|
|
|
|
/**
|
|
* prevent the IR from being collected while this is live.
|
|
*/
|
|
private final IR ir;
|
|
|
|
/**
|
|
* @param ir an IR in SSA form.
|
|
* @throws IllegalArgumentException if ir is null
|
|
*/
|
|
public DefUse(final IR ir) {
|
|
if (ir == null) {
|
|
throw new IllegalArgumentException("ir is null");
|
|
}
|
|
this.ir = ir;
|
|
|
|
// set up mapping from integer -> instruction
|
|
initAllInstructions();
|
|
defs = new SSAInstruction[getMaxValueNumber() + 1];
|
|
uses = new MutableIntSet[getMaxValueNumber() + 1];
|
|
if (DEBUG) {
|
|
System.err.println(("DefUse: defs.length " + defs.length));
|
|
}
|
|
Iterator<SSAInstruction> it = allInstructions.iterator();
|
|
for (int i = 0; i < allInstructions.size(); i++) {
|
|
SSAInstruction s = it.next();
|
|
if (s == null) {
|
|
continue;
|
|
}
|
|
for (int j = 0; j < getNumberOfDefs(s); j++) {
|
|
defs[getDef(s, j)] = s;
|
|
}
|
|
for (int j = 0; j < getNumberOfUses(s); j++) {
|
|
int use = getUse(s, j);
|
|
try {
|
|
if (use != -1) {
|
|
if (uses[use] == null) {
|
|
uses[use] = IntSetUtil.make();
|
|
}
|
|
uses[use].add(i);
|
|
}
|
|
} catch (ArrayIndexOutOfBoundsException e) {
|
|
assert false : "unexpected value number " + use;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return the maximum value number in a particular IR
|
|
*/
|
|
protected int getMaxValueNumber() {
|
|
return ir.getSymbolTable().getMaxValueNumber();
|
|
}
|
|
|
|
/**
|
|
* Initialize the allInstructions field with every {@link SSAInstruction} in the ir.
|
|
*/
|
|
protected void initAllInstructions() {
|
|
for (SSAInstruction inst : Iterator2Iterable.make(ir.iterateAllInstructions())) {
|
|
allInstructions.add(inst);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* What is the ith value number defined by instruction s?
|
|
*/
|
|
protected int getDef(SSAInstruction s, int i) {
|
|
return s.getDef(i);
|
|
}
|
|
|
|
/**
|
|
* What is the ith value number used by instruction s?
|
|
*/
|
|
protected int getUse(SSAInstruction s, int i) {
|
|
return s.getUse(i);
|
|
}
|
|
|
|
/**
|
|
* How many value numbers does instruction s def?
|
|
*/
|
|
protected int getNumberOfDefs(SSAInstruction s) {
|
|
return s.getNumberOfDefs();
|
|
}
|
|
|
|
/**
|
|
* How many value numbers does instruction s use?
|
|
*/
|
|
protected int getNumberOfUses(SSAInstruction s) {
|
|
return s.getNumberOfUses();
|
|
}
|
|
|
|
/**
|
|
* @return the {@link SSAInstruction} that defines the variable with value number v.
|
|
*/
|
|
public SSAInstruction getDef(int v) {
|
|
return (v < defs.length) ? defs[v] : null;
|
|
}
|
|
|
|
/**
|
|
* Return all uses of the variable with the given value number
|
|
*/
|
|
public Iterator<SSAInstruction> getUses(int v) {
|
|
if (uses[v] == null) {
|
|
return EmptyIterator.instance();
|
|
} else {
|
|
return new UseIterator(uses[v]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* return an {@link Iterator} of all instructions that use any of a set of variables
|
|
*/
|
|
private class UseIterator implements Iterator<SSAInstruction> {
|
|
final IntIterator it;
|
|
|
|
/**
|
|
* @param uses the set of value numbers whose uses this object iterates over
|
|
*/
|
|
UseIterator(IntSet uses) {
|
|
it = uses.intIterator();
|
|
}
|
|
|
|
@Override
|
|
public boolean hasNext() {
|
|
return it.hasNext();
|
|
}
|
|
|
|
@Override
|
|
public SSAInstruction next() {
|
|
return allInstructions.get(it.next());
|
|
}
|
|
|
|
@Override
|
|
public void remove() {
|
|
Assertions.UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param v a value number
|
|
* @return the number of uses of the variable with the given value number
|
|
*/
|
|
public int getNumberOfUses(int v) {
|
|
return uses[v] == null ? 0 : uses[v].size();
|
|
}
|
|
}
|