opu.lljvm-python.0.2.0-EXPERIMENTAL.source-code.Insn Maven / Gradle / Ivy
The newest version!
/**
* An Insn is a generic instruction that is added to a
* CodeAttr to build up the code for a method.
* @see CodeAttr
* @see RuntimeConstants
* @author $Author: jonmeyerny $
* @version $Revision: 1.1 $
*/
package jas;
import java.io.*;
import java.util.*;
public class Insn implements RuntimeConstants
{
int opc;
InsnOperand operand;
// private constructor, for the
// "strange" opcodes
Insn() { return; }
/**
* Instructions with no arguments are built with
* this constructor.
*/
public Insn(int opc)
throws jasError
{
if (opcLengths[opc] == 1)
{ operand = null; this.opc = opc; return; }
throw new jasError
(opcNames[opc] + " cannot be used without more parameters");
}
private void check_short(int val, int opc) throws jasError
{
if (val > 32767 || val < -32768)
throw new jasError
(opcNames[opc] + " numeric value exceed size for short");
}
/**
* Instructions that take a single numeric argument. These are
* opc_bipush,
* opc_sipush,
* opc_ret,
* opc_iload,
* opc_lload,
* opc_fload,
* opc_dload,
* opc_aload,
* opc_istore,
* opc_lstore,
* opc_fstore,
* opc_dstore,
* opc_astore,
* opc_newarray
*
* Note that an extra wide prefix is automatically added
* for the following instructions if the numeric argument
* is larger than 256. Also note that while the spec makes
* no mention of opc_ret as being a "wideable" opcode, thats
* how the VM is implemented.
*
* opc_ret:
* opc_iload:
* opc_lload:
* opc_fload:
* opc_dload:
* opc_aload:
* opc_istore:
* opc_lstore:
* opc_fstore:
* opc_dstore:
* opc_astore:
*
*/
/**
* Added branch instructions
*/
public Insn(int opc, int val, boolean Wide)
throws jasError
{
this.opc = opc;
switch (opc)
{
case opc_bipush:
if(val > 127 || val < -128)
throw new jasError("bipush value exceed size of byte", true);
operand = new ByteOperand(val);
break;
case opc_sipush:
case opc_goto:
case opc_if_acmpeq:
case opc_if_acmpne:
case opc_if_icmpeq:
case opc_if_icmpge:
case opc_if_icmpgt:
case opc_if_icmple:
case opc_if_icmplt:
case opc_if_icmpne:
case opc_ifeq:
case opc_ifge:
case opc_ifgt:
case opc_ifle:
case opc_iflt:
case opc_ifne:
case opc_ifnonnull:
case opc_ifnull:
case opc_jsr:
check_short(val, opc);
operand = new OffsetOperand(this, val); break;
case opc_goto_w:
case opc_jsr_w:
operand = new OffsetOperand(this, val, true); break;
case opc_newarray:
if(val < 0 || val > 255)
throw new jasError("newarray counter is illegal", true);
operand = new UnsignedByteOperand(val);
break;
case opc_ret:
case opc_iload:
case opc_lload:
case opc_fload:
case opc_dload:
case opc_aload:
case opc_istore:
case opc_lstore:
case opc_fstore:
case opc_dstore:
case opc_astore:
operand = new UnsignedByteWideOperand(val, Wide);
break;
default:
throw new jasError
(opcNames[opc] + " does not take a numeric argument");
}
}
// used for relative offsets (ex : goto $+5)
public Insn(int opc, int val, char relative)
throws jasError
{
this.opc = opc;
switch (opc)
{
case opc_goto:
case opc_if_acmpeq:
case opc_if_acmpne:
case opc_if_icmpeq:
case opc_if_icmpge:
case opc_if_icmpgt:
case opc_if_icmple:
case opc_if_icmplt:
case opc_if_icmpne:
case opc_ifeq:
case opc_ifge:
case opc_ifgt:
case opc_ifle:
case opc_iflt:
case opc_ifne:
case opc_ifnonnull:
case opc_ifnull:
case opc_jsr:
check_short(val, opc);
operand = new RelativeOffsetOperand(this, val); break;
case opc_goto_w:
case opc_jsr_w:
operand = new RelativeOffsetOperand(this, val, true); break;
default:
throw new jasError
(opcNames[opc] + " does not take a relative numeric argument");
}
}
/**
* Instructions that take a Label as an argument. These are
* opc_jsr,
* opc_goto,
* opc_if_acmpne,
* opc_if_acmpeq,
* opc_if_icmpge,
* opc_if_icmple,
* opc_if_icmpgt,
* opc_if_icmplt,
* opc_if_icmpne,
* opc_if_icmpeq,
* opc_ifge,
* opc_ifgt,
* opc_ifne,
* opc_ifle,
* opc_iflt,
* opc_ifeq,
* opc_ifnull,
* opc_ifnonnull,
* opc_goto_w,
* opc_jsr_w
*/
public Insn(int opc, Label target, int line)
throws jasError
{
this.opc = opc;
switch(opc)
{
case opc_jsr:
case opc_goto:
case opc_if_acmpne:
case opc_if_acmpeq:
case opc_if_icmpge:
case opc_if_icmple:
case opc_if_icmpgt:
case opc_if_icmplt:
case opc_if_icmpne:
case opc_if_icmpeq:
case opc_ifge:
case opc_ifgt:
case opc_ifne:
case opc_ifle:
case opc_iflt:
case opc_ifeq:
case opc_ifnull:
case opc_ifnonnull:
operand = new LabelOperand(target, this, line);
break;
case opc_goto_w:
case opc_jsr_w:
operand = new LabelOperand(target, this, true, line);
break;
default:
throw new jasError
(opcNames[opc] + " does not take a label as its argument");
}
}
/**
* This constructor is used for instructions that take a CP item
* as their argument. These are
* opc_anewarray,
* opc_ldc_w,
* opc_ldc2_w,
* opc_invokedynamic,
* opc_invokenonvirtual,
* opc_invokestatic,
* opc_invokevirtual,
* opc_new,
* opc_checkcast,
* opc_instanceof,
* opc_getstatic,
* opc_putstatic,
* opc_getfield,
* opc_putfield,
* opc_ldc
*/
public Insn(int opc, CP arg)
throws jasError
{
this.opc = opc;
switch(opc)
{
case opc_anewarray:
case opc_invokedynamic:
case opc_invokenonvirtual:
case opc_invokestatic:
case opc_invokevirtual:
case opc_new:
case opc_checkcast:
case opc_instanceof:
case opc_getstatic:
case opc_putstatic:
case opc_getfield:
case opc_putfield:
operand = new CPOperand(arg);
break;
case opc_ldc2_w:
case opc_ldc_w:
operand = new LdcOperand(this, arg);
break;
case opc_ldc:
operand = new LdcOperand(this, arg, false);
break;
default:
throw new jasError
(opcNames[opc] + " does not take a CP item as an argument");
}
}
// This allows the Insn a chance to
// add things to the global env if
// necessary. The CPInsnOperands
// use this to add the CP to the
// classEnv
void resolve(ClassEnv e)
{ if (operand != null) { operand.resolve(e); } }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
if (operand != null)
operand.writePrefix(e, ce, out);
out.writeByte((byte) opc);
if (operand != null)
operand.write(e, ce, out);
}
int size(ClassEnv e, CodeAttr ce)
throws jasError
{
if (operand == null) return 1;
return (1 + operand.size(e, ce));
}
public String toString() {
return "instruction "+opc+" "+((operand!=null)?operand.toString():"");
}
}
/* --- Revision History ---------------------------------------------------
--- Iouri Kharon, Aug 10 2006
Added 'wide' prefix to some instructions
*/