opu.lljvm-python.0.2.0-EXPERIMENTAL.source-code.CodeAttr Maven / Gradle / Ivy
The newest version!
/**
* CodeAttr's are used as a bag to hold lists of instructions
* until it is time to put them into a Class.
* @see ClassEnv#addMethod
* @author $Author: jonmeyerny $
* @version $Revision: 1.1 $
*/
package jas;
import java.io.*;
import java.util.*;
public class CodeAttr
{
static final CP attr = new AsciiCP("Code");
short stack_size, num_locals;
int code_size;
Vector insns;
Hashtable insn_pc;
Catchtable ctb;
LineTableAttr ltab;
LocalVarTableAttr lvar;
LocalVarTypeTableAttr lvtyp;
StackMap stackmap;
Vector generic;
/**
* Create a new bag. Add instructions with the addInsn() method,
* set the catch table with the setCatchTable() method.
* @see Insn
* @see Catchtable
* @see ClassEnv#addMethod
*/
public CodeAttr()
{
this.stack_size = 1;
this.num_locals = 1;
this.ctb = null;
this.insns = new Vector();
generic = new Vector();
}
/**
* Set the catchtable for this code
*/
public void setCatchtable(Catchtable ctb)
{ this.ctb = ctb; }
/**
* Set the line number table for this method
*/
public void setLineTable(LineTableAttr ltab)
{ this.ltab = ltab; }
/**
* Set the local variable information for this method
*/
public void setLocalVarTable(LocalVarTableAttr lvar)
{ this.lvar = lvar; }
/**
* Set the local variable type information for this method
*/
public void setLocalVarTypeTable(LocalVarTypeTableAttr lvtyp)
{ this.lvtyp = lvtyp; }
/**
* Set the StackMap attribute for this method
*/
public void setStackMap(StackMap s)
{ stackmap = s; }
/**
* Add a generic attribute to the method. A generic attribute
* contains a stream of uninterpreted bytes which is ignored by
* the VM (as long as its name doesn't conflict with other names
* for attributes that are understood by the VM)
*/
public void addGenericAttr(GenericAttr g)
{ generic.addElement(g); }
/**
* Append a new Insn to this code. Insn's are sequentially
* stored, in the order in which this method is called. You
* can't reorder code fragments after you've added it here.
*/
public void addInsn(Insn insn)
{ insns.addElement(insn); }
public void setStackSize(short stack_size)
{ this.stack_size = stack_size; }
public void setVarSize(short num_vars)
{ num_locals = num_vars; }
void resolve(ClassEnv e)
{
// propagate this resolution to
// the insns and catch table, so
// that any CP's referenced by them
// also get added.
e.addCPItem(attr);
for (Enumeration en = insns.elements(); en.hasMoreElements();)
{
Insn i = (Insn)(en.nextElement());
i.resolve(e);
}
if (ctb != null) ctb.resolve(e);
if (ltab != null) ltab.resolve(e);
if (lvar != null) lvar.resolve(e);
if (lvtyp != null) lvtyp.resolve(e);
if (stackmap != null) stackmap.resolve(e);
for (Enumeration gen = generic.elements(); gen.hasMoreElements();)
{
GenericAttr gattr = (GenericAttr)gen.nextElement();
gattr.resolve(e);
}
}
int getPc(Insn i) throws jasError
{
if (insn_pc == null)
throw new jasError("Internal error, insn_pc has not been initialized");
Integer tmp;
if (i instanceof Label)
{
tmp = (Integer)(insn_pc.get(((Label)i).id));
}
else
{
tmp = (Integer)(insn_pc.get(i));
}
if (tmp == null)
throw new jasError(i + " has not been added to the code");
return tmp.intValue();
}
void write(ClassEnv e, DataOutputStream out)
throws IOException, jasError
{
// First, resolve all labels and
// compute total size
int code_size = 0;
insn_pc = new Hashtable();
for (Enumeration en = insns.elements(); en.hasMoreElements();)
{
Insn now = (Insn)(en.nextElement());
if (now instanceof Label)
{
insn_pc.put(((Label)now).id, new Integer(code_size));
}
else
{ insn_pc.put(now, new Integer(code_size)); }
code_size += now.size(e, this);
}
int total_size = code_size;
if (ctb != null) total_size += ctb.size();
if (ltab != null) total_size += ltab.size();
if (lvar != null) total_size += lvar.size();
if (lvtyp != null) total_size += lvtyp.size();
if (stackmap != null) total_size += stackmap.size(e, this);
for (Enumeration gen = generic.elements(); gen.hasMoreElements();)
{
GenericAttr gattr = (GenericAttr)(gen.nextElement());
total_size += gattr.size();
}
// extra headers
total_size += 12;
out.writeShort(e.getCPIndex(attr));
out.writeInt(total_size);
out.writeShort(stack_size);
out.writeShort(num_locals);
out.writeInt(code_size);
for (Enumeration en = insns.elements(); en.hasMoreElements();)
{
Insn now = (Insn)(en.nextElement());
now.write(e, this, out);
}
if (ctb != null)
{ ctb.write(e, this, out); }
else
{ out.writeShort(0); }
short extra = 0;
if (ltab != null) extra++;
if (lvar != null) extra++;
if (lvtyp != null) extra++;
if (stackmap != null) extra++;
extra += generic.size();
out.writeShort(extra);
if (ltab != null)
{ ltab.write(e, this, out); }
if (lvar != null)
{ lvar.write(e, this, out); }
if (lvtyp != null)
{ lvtyp.write(e, this, out); }
if (stackmap != null)
{ stackmap.write(e, this, out); }
for (Enumeration gen = generic.elements(); gen.hasMoreElements();)
{
GenericAttr gattr = (GenericAttr)gen.nextElement();
gattr.write(e, out);
}
}
public String toString()
{ return ("<#code-attr>"); }
}