opu.lljvm-python.0.2.0-EXPERIMENTAL.source-code.InsnOperand Maven / Gradle / Ivy
The newest version!
// This is not visible outside the
// package. It is used to
// handle the various types
// of operands used by Insns.
package jas;
import java.io.*;
abstract class InsnOperand
{
abstract void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError;
abstract int size(ClassEnv e, CodeAttr code) throws jasError;
abstract void resolve(ClassEnv e);
void writePrefix(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{ return; }
}
// Used to implement targets of Insns
class LabelOperand extends InsnOperand
{
Label target;
Insn source;
boolean wide;
int ref;
LabelOperand(Label l, Insn source, int line)
{ target = l; this.source = source; this.wide = false; this.ref = line; }
LabelOperand(Label l, Insn source, boolean wide, int line)
{ target = l; this.source = source; this.wide = wide; this.ref = line; }
int size(ClassEnv ce, CodeAttr code) { if (wide) return 4; else return 2; }
void resolve(ClassEnv e) { return; }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
if (wide) { target.writeWideOffset(ce, source, out); }
else {
int offset = ce.getPc(target);
if (source != null)
offset -= ce.getPc(source);
if (offset > 32767 || offset < -32768)
throw new jasError
("reference from line " +ref+ " exceed size for short");
target.writeOffset(ce, source, out); }
}
}
class UnsignedByteOperand extends InsnOperand
{
int val;
UnsignedByteOperand(int n) { val = n; }
int size(ClassEnv ce, CodeAttr code) { return 1; }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
if (val >= 256)
throw
new jasError("Operand is too large (" +val+ ") for this instruction");
out.writeByte((byte)(0xff & val));
}
void resolve(ClassEnv e) { return; }
}
// This (conditionally) adds a wide
// prefix if the value is larger than
// 256
class UnsignedByteWideOperand extends InsnOperand
implements RuntimeConstants
{
int val;
boolean Wide;
UnsignedByteWideOperand(int n, boolean Wide)
{
val = n;
this.Wide = (Wide || val > 255);
}
int size(ClassEnv ce, CodeAttr code)
{ return Wide ? 3: 1; }
void writePrefix(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{
if (Wide)
out.writeByte((byte)(opc_wide));
}
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{
if (Wide)
out.writeShort((short)(0xffff & val));
else
out.writeByte((byte)(val & 0xff));
}
void resolve(ClassEnv e) { return; }
}
class ByteOperand extends InsnOperand
{
int val;
ByteOperand(int n) { val = n; }
int size(ClassEnv ce, CodeAttr code) { return 1; }
void resolve(ClassEnv e) { return; }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{ out.writeByte((byte)val); }
}
class IntegerOperand extends InsnOperand
{
int val;
IntegerOperand(int n) { val = n; }
int size(ClassEnv ce, CodeAttr code) { return 4; }
void resolve(ClassEnv e) { return; }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{ out.writeInt(val); }
}
class ShortOperand extends InsnOperand
{
int offset;
ShortOperand(int n) { offset = n; }
void resolve(ClassEnv e) { return; }
int size(ClassEnv ce, CodeAttr code) { return 2; }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{ out.writeShort((short)offset); }
}
class CPOperand extends InsnOperand
{
CP cpe;
boolean wide;
int size(ClassEnv ce, CodeAttr code) { if (wide) return 2; else return 1; }
CPOperand(CP cpe) { this.cpe = cpe; wide = true; }
CPOperand(CP cpe, boolean wide)
{ this.cpe = cpe; this.wide = wide; }
void resolve(ClassEnv e)
{ e.addCPItem(cpe); }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
int idx = e.getCPIndex(cpe);
if (wide)
{ out.writeShort((short) idx); }
else
{
if (idx > 255)
{ throw new jasError("exceeded size for small cpidx" + cpe); }
out.writeByte((byte) (0xff & (idx)));
}
}
}
// these are unique enough that
// they need a separate handler for their
// args
class LdcOperand extends InsnOperand implements RuntimeConstants
{
CP cpe;
Insn source;
boolean wide;
int size(ClassEnv ce, CodeAttr code) throws jasError
{
if (wide)
{ return 2; }
else
{
// Should we promote it?
int idx = ce.getCPIndex(cpe);
if (idx > 255)
{
wide = true;
source.opc = opc_ldc_w;
return 2;
}
return 1;
}
}
LdcOperand(Insn s, CP cpe) { source = s; this.cpe = cpe; wide = true; }
LdcOperand(Insn s, CP cpe, boolean wide)
{ source = s; this.cpe = cpe; this.wide = wide; }
void resolve(ClassEnv e)
{ e.addCPItem(cpe); }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
int idx = e.getCPIndex(cpe);
if (wide)
{ out.writeShort((short) idx); }
else
{
if (idx > 255)
{ throw new jasError("exceeded size for small cpidx" + cpe); }
out.writeByte((byte) (0xff & (idx)));
}
}
}
class InvokeinterfaceOperand extends InsnOperand
{
CP cpe;
int nargs;
InvokeinterfaceOperand(CP cpe, int nargs)
{ this.cpe = cpe; this.nargs = nargs; }
int size(ClassEnv ce, CodeAttr code) { return 4; }
void resolve(ClassEnv e)
{ e.addCPItem(cpe); }
void write (ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
out.writeShort(e.getCPIndex(cpe));
out.writeByte((byte) (0xff & nargs));
out.writeByte(0);
}
}
class IincOperand extends InsnOperand
implements RuntimeConstants
{
int vindex, constt;
boolean Wide;
IincOperand(int vindex, int constt, boolean Wide)
{
this.vindex = vindex;
this.constt = constt;
this.Wide = (Wide ||
vindex > 255 ||
constt > 127 ||
constt < 127);
}
int size(ClassEnv ce, CodeAttr code)
{
return Wide ? 5 : 2;
}
void resolve(ClassEnv e) { return; }
void writePrefix(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{
if (Wide)
out.writeByte((byte)opc_wide);
}
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{
if (Wide)
{
out.writeShort((short)(0xffff & vindex));
out.writeShort((short)(0xffff & constt));
}
else
{
out.writeByte((byte) (0xff & vindex));
out.writeByte((byte) (0xff & constt));
}
}
}
class MultiarrayOperand extends InsnOperand
{
CP cpe;
int sz;
MultiarrayOperand(CP cpe, int sz)
{ this.cpe = cpe; this.sz = sz; }
void resolve(ClassEnv e) { e.addCPItem(cpe); }
int size(ClassEnv ce, CodeAttr code) { return 3; }
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
out.writeShort(e.getCPIndex(cpe));
out.writeByte((byte)(0xff & sz));
}
}
class LookupswitchOperand extends InsnOperand
{
LabelOrOffset dflt;
Insn source;
int match[];
LabelOrOffset jmp[];
LookupswitchOperand(Insn s, LabelOrOffset def, int m[], LabelOrOffset j[])
{ dflt = def; jmp = j; match = m; source = s; }
void resolve (ClassEnv e) { return; }
int size(ClassEnv ce, CodeAttr code) throws jasError
{
int sz = 8; // 4 + 4 + padding + jumptable
int source_pc = code.getPc(source);
if (((source_pc+1) % 4) != 0)
{
// need padding
sz += (4 - ((source_pc+1) % 4));
}
if (jmp != null)
{ sz += 8*(jmp.length); }
return sz;
}
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
int pad;
int source_pc = ce.getPc(source);
if (((source_pc+1) % 4) != 0)
{ // need padding
pad = (4 - ((source_pc+1) % 4));
for (int x=0; x