jas.InsnOperand Maven / Gradle / Ivy
// 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;
LabelOperand(Label l, Insn source)
{ target = l; this.source = source; this.wide = false; }
LabelOperand(Label l, Insn source, boolean wide)
{ target = l; this.source = source; this.wide = wide; }
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 { 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;
UnsignedByteWideOperand(int n) { val = n; }
int size(ClassEnv ce, CodeAttr code)
{
if (val >= 256) return 3;
return 1;
}
void writePrefix(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{
if (val > 255)
out.writeByte((byte)(opc_wide));
}
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{
if (val > 255)
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)));
}
}
}
class PaddedCPOperand extends CPOperand {
PaddedCPOperand(CP cpe) {
super(cpe);
}
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError {
super.write(e, ce, out);
//add padding ("reserved for future use")
out.writeShort(0);
}
int size(ClassEnv ce, CodeAttr code) {
return super.size(ce, code) + 2 /*2 bytes padding*/;
}
}
// 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);
// LJH
// System.out.println("getting idx in size: " + idx);
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);
if (cpe instanceof ClassCP){
// If the constant is a Type (for .class constants),
// the class major version must be 49.0 (Java5) or more.
e.requireJava5();
}
}
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException, jasError
{
int idx = e.getCPIndex(cpe);
// LJH
// System.out.println("Writing " + idx + " which as a short is " +
// ((short) idx) + " and is " + wide);
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;
IincOperand(int vindex, int constt)
{ this.vindex = vindex; this.constt = constt; }
int size(ClassEnv ce, CodeAttr code)
{
if ((vindex > 255) ||
(constt > 127) ||
(constt < -128))
return 5;
else
return 2;
}
void resolve(ClassEnv e) { return; }
void writePrefix(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{
if ((vindex > 255) ||
(constt > 127) ||
(constt < -128))
out.writeByte((byte)opc_wide);
}
void write(ClassEnv e, CodeAttr ce, DataOutputStream out)
throws IOException
{
if ((vindex > 255) ||
(constt > 127) ||
(constt < -128))
{
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
{
Label dflt;
Insn source;
int match[];
Label jmp[];
LookupswitchOperand(Insn s, Label def, int m[], Label 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
© 2015 - 2025 Weber Informatics LLC | Privacy Policy