/*******************************************************************************
* Copyright (c) 2013 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.cast.ir.ssa;
import java.util.Collection;
import java.util.Collections;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.debug.Assertions;
/**
* IR instruction to check whether a field is defined on some object. The field
* is represented either by a {@link FieldReference} or by a local value number.
*/
public class AstIsDefinedInstruction extends SSAInstruction {
/**
* name of the field. If non-null, fieldVal should be -1.
*/
private final FieldReference fieldRef;
/**
* value number holding the field string. If non-negative,
* fieldRef should be null.
*/
private final int fieldVal;
/**
* the base pointer
*/
private final int rval;
/**
* gets 1 if the field is defined, 0 otherwise.
*/
private final int lval;
/**
* This constructor should only be used from {@link SSAInstruction#copyForSSA(SSAInstructionFactory, int[], int[])}
*/
public AstIsDefinedInstruction(int iindex, int lval, int rval, int fieldVal, FieldReference fieldRef) {
super(iindex);
this.lval = lval;
this.rval = rval;
this.fieldVal = fieldVal;
this.fieldRef = fieldRef;
}
public AstIsDefinedInstruction(int iindex, int lval, int rval, FieldReference fieldRef) {
super(iindex);
this.lval = lval;
this.rval = rval;
this.fieldVal = -1;
this.fieldRef = fieldRef;
}
public AstIsDefinedInstruction(int iindex, int lval, int rval, int fieldVal) {
super(iindex);
this.lval = lval;
this.rval = rval;
this.fieldVal = fieldVal;
this.fieldRef = null;
}
public AstIsDefinedInstruction(int iindex, int lval, int rval) {
super(iindex);
this.lval = lval;
this.rval = rval;
this.fieldVal = -1;
this.fieldRef = null;
}
@Override
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) {
assert fieldVal == -1 || fieldRef == null;
return ((AstInstructionFactory) insts).IsDefinedInstruction(iindex, (defs == null) ? lval : defs[0], (uses == null) ? rval : uses[0],
(uses == null || fieldVal == -1) ? fieldVal : uses[1], fieldRef);
}
@Override
public String toString(SymbolTable symbolTable) {
if (fieldVal == -1 && fieldRef == null) {
return getValueString(symbolTable, lval) + " = isDefined(" + getValueString(symbolTable, rval) + ")";
} else if (fieldVal == -1) {
return getValueString(symbolTable, lval) + " = isDefined(" + getValueString(symbolTable, rval) + "," + fieldRef.getName()
+ ")";
} else if (fieldRef == null) {
return getValueString(symbolTable, lval) + " = isDefined(" + getValueString(symbolTable, rval) + ","
+ getValueString(symbolTable, fieldVal) + ")";
} else {
Assertions.UNREACHABLE();
return null;
}
}
@Override
public void visit(IVisitor v) {
((AstInstructionVisitor) v).visitIsDefined(this);
}
@Override
public Collection<TypeReference> getExceptionTypes() {
return Collections.emptySet();
}
@Override
public boolean hasDef() {
return true;
}
@Override
public int getDef() {
return lval;
}
@Override
public int getDef(int i) {
assert i == 0;
return lval;
}
@Override
public int getNumberOfDefs() {
return 1;
}
@Override
public int getNumberOfUses() {
return (fieldVal == -1) ? 1 : 2;
}
@Override
public int getUse(int j) {
if (j == 0) {
return rval;
} else if (j == 1 && fieldVal != -1) {
return fieldVal;
} else {
Assertions.UNREACHABLE();
return -1;
}
}
@Override
public boolean isFallThrough() {
return true;
}
@Override
public int hashCode() {
return 3077 * fieldVal * rval;
}
public FieldReference getFieldRef() {
return fieldRef;
}
}