serp.bytecode.CmpInstruction Maven / Gradle / Ivy
The newest version!
package serp.bytecode;
import serp.bytecode.visitor.*;
/**
* An instruction comparing two stack values. Examples include
* lcmp, fcmpl
, etc.
*
* @author Abe White
*/
public class CmpInstruction extends TypedInstruction {
private static Class[][] _mappings = new Class[][] {
{ int.class, long.class },
{ byte.class, long.class },
{ char.class, long.class },
{ short.class, long.class },
{ boolean.class, long.class },
{ void.class, long.class },
{ Object.class, long.class },
};
CmpInstruction(Code owner) {
super(owner);
}
CmpInstruction(Code owner, int opcode) {
super(owner, opcode);
}
public int getLogicalStackChange() {
switch (getOpcode()) {
case Constants.NOP:
return 0;
default:
return -1;
}
}
public int getStackChange() {
switch (getOpcode()) {
case Constants.LCMP:
case Constants.DCMPL:
case Constants.DCMPG:
return -3;
case Constants.NOP:
return 0;
default:
return -1;
}
}
public String getTypeName() {
switch (getOpcode()) {
case Constants.LCMP:
return long.class.getName();
case Constants.FCMPL:
case Constants.FCMPG:
return float.class.getName();
case Constants.DCMPL:
case Constants.DCMPG:
return double.class.getName();
default:
return null;
}
}
public TypedInstruction setType(String type) {
type = mapType(type, _mappings, true);
if (type == null)
return (TypedInstruction) setOpcode(Constants.NOP);
int opcode = getOpcode();
switch (type.charAt(0)) {
case 'l':
return (TypedInstruction) setOpcode(Constants.LCMP);
case 'f':
if ((opcode == Constants.FCMPL) || (opcode == Constants.DCMPL))
return (TypedInstruction) setOpcode(Constants.FCMPL);
return (TypedInstruction) setOpcode(Constants.FCMPG);
case 'd':
if ((opcode == Constants.FCMPL) || (opcode == Constants.DCMPL))
return (TypedInstruction) setOpcode(Constants.DCMPL);
return (TypedInstruction) setOpcode(Constants.DCMPG);
default:
throw new IllegalStateException();
}
}
/**
* Return the number that will be placed on the stack if this instruction
* is of type float or double and one of the operands is NaN. For
* FCMPG or DCMPG, this value will be 1; for FCMPL or DCMPL this value
* will be -1. For LCMP or if the type is unset, this value will be 0.
*/
public int getNaNValue() {
switch (getOpcode()) {
case Constants.FCMPL:
case Constants.DCMPL:
return -1;
case Constants.FCMPG:
case Constants.DCMPG:
return 1;
default:
return 0;
}
}
/**
* Set the number that will be placed on the stack if this instruction
* is of type float or double and one of the operands is NaN. For
* FCMPG or DCMPG, this value should be 1; for FCMPL or DCMPL this value
* should be -1. For LCMP, this value should be 0.
*
* @return this instruction, for method chaining
*/
public CmpInstruction setNaNValue(int nan) {
switch (getOpcode()) {
case Constants.FCMPL:
case Constants.FCMPG:
if (nan == 1)
setOpcode(Constants.FCMPG);
else if (nan == -1)
setOpcode(Constants.FCMPL);
else
throw new IllegalArgumentException("Invalid nan for type");
case Constants.DCMPL:
case Constants.DCMPG:
if (nan == 1)
setOpcode(Constants.DCMPG);
else if (nan == -1)
setOpcode(Constants.DCMPL);
else
throw new IllegalArgumentException("Invalid nan for type");
default:
if (nan != 0)
throw new IllegalArgumentException("Invalid nan for type");
}
return this;
}
public void acceptVisit(BCVisitor visit) {
visit.enterCmpInstruction(this);
visit.exitCmpInstruction(this);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy