From cb0bae954e7dd0067e77c436c78ee19ace52d9e3 Mon Sep 17 00:00:00 2001 From: brian Date: Tue, 25 May 2004 05:06:42 +0000 Subject: [PATCH 1/1] sort of working darcs-hash:20040525050642-24bed-f2b55804b1d69c571869d7ca34ee3d474264a468.gz --- Makefile | 22 +++ src/org/ibex/classgen/AttrGen.java | 32 ++++ src/org/ibex/classgen/CGConst.java | 230 ++++++++++++++++++++++++ src/org/ibex/classgen/CPGen.java | 183 +++++++++++++++++++ src/org/ibex/classgen/ClassGen.java | 105 +++++++++++ src/org/ibex/classgen/FieldGen.java | 9 + src/org/ibex/classgen/MethodGen.java | 327 ++++++++++++++++++++++++++++++++++ src/org/ibex/classgen/Type.java | 49 +++++ src/org/ibex/classgen/util/Sort.java | 48 +++++ 9 files changed, 1005 insertions(+) create mode 100644 Makefile create mode 100644 src/org/ibex/classgen/AttrGen.java create mode 100644 src/org/ibex/classgen/CGConst.java create mode 100644 src/org/ibex/classgen/CPGen.java create mode 100644 src/org/ibex/classgen/ClassGen.java create mode 100644 src/org/ibex/classgen/FieldGen.java create mode 100644 src/org/ibex/classgen/MethodGen.java create mode 100644 src/org/ibex/classgen/Type.java create mode 100644 src/org/ibex/classgen/util/Sort.java diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2c9e9b5 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +JAVAC = javac +sources = $(shell find src -name '*.java') +classes = $(sources:src/%.java=build/%.class) +jar_classes = $(classes) + +all: $(classes) + +$(classes): $(sources) + @mkdir -p build + $(JAVAC) -d build $(sources) + +test: $(classes) + java -cp build org.ibex.classgen.ClassGen + +clean: + rm -rf build/* + +sizecheck: + @for c in $(jar_classes); do \ + for f in `echo $$c|sed 's,\.class$$,,;'`*.class; do gzip -c $$f; done | wc -c | tr -d '\n'; \ + echo -e "\t`echo $$c | sed 's,build/org/ibex,,;s,\.class$$,,;s,/,.,g;'`"; \ + done | sort -rn | awk '{ sum += $$1; print } END { print sum,"Total"; }' diff --git a/src/org/ibex/classgen/AttrGen.java b/src/org/ibex/classgen/AttrGen.java new file mode 100644 index 0000000..81d94b3 --- /dev/null +++ b/src/org/ibex/classgen/AttrGen.java @@ -0,0 +1,32 @@ +package org.ibex.classgen; + +import java.io.*; +import java.util.*; + +public class AttrGen { + private final CPGen cp; + private final Hashtable ht = new Hashtable(); + + public AttrGen(CPGen cp) { + this.cp = cp; + } + + public void add(String s, byte[] data) { + cp.addUtf8(s); + ht.put(s,data); + } + + public boolean contains(String s) { return ht.get(s) != null; } + + public int size() { return ht.size(); } + + public void dump(DataOutput o) throws IOException { + for(Enumeration e = ht.keys(); e.hasMoreElements();) { + String name = (String) e.nextElement(); + byte[] val = (byte[]) ht.get(name); + o.writeShort(cp.getUtf8(name).index); + o.writeInt(val.length); + o.write(val); + } + } +} diff --git a/src/org/ibex/classgen/CGConst.java b/src/org/ibex/classgen/CGConst.java new file mode 100644 index 0000000..0dde25c --- /dev/null +++ b/src/org/ibex/classgen/CGConst.java @@ -0,0 +1,230 @@ +package org.ibex.classgen; + +public interface CGConst { + public static final int ACC_PUBLIC = (byte) 0x0001; + public static final int ACC_FINAL = (byte) 0x0010; + + // Class only + public static final int ACC_INTERFACE = (byte) 0x0200; + public static final int ACC_SUPER = (byte) 0x0020; + + // Field/Method only + public static final int ACC_PRIVATE = (byte) 0x0002; + public static final int ACC_PROTECTED = (byte) 0x0004; + public static final int ACC_STATIC = (byte) 0x0008; + + // Class/Method only + public static final int ACC_ABSTRACT = (byte) 0x0400; + + // Method Only + public static final int ACC_SYNCHRONIZED = (byte) 0x0020; + public static final int ACC_NATIVE = (byte) 0x0100; + public static final int ACC_STRICT = (byte) 0x0800; + + // Field only + public static final int ACC_VOLATILE = (byte) 0x0040; + public static final int ACC_TRANSIENT = (byte) 0x0080; + + // Instructions + public static final byte NOP = (byte) 0x0; + public static final byte ACONST_NULL = (byte) 0x01; + public static final byte ICONST_M1 = (byte) 0x02; + public static final byte ICONST_0 = (byte) 0x03; + public static final byte ICONST_1 = (byte) 0x04; + public static final byte ICONST_2 = (byte) 0x05; + public static final byte ICONST_3 = (byte) 0x06; + public static final byte ICONST_4 = (byte) 0x07; + public static final byte ICONST_5 = (byte) 0x08; + public static final byte LCONST_0 = (byte) 0x09; + public static final byte LCONST_1 = (byte) 0x0A; + public static final byte FCONST_0 = (byte) 0x0B; + public static final byte FCONST_1 = (byte) 0x0C; + public static final byte FCONST_2 = (byte) 0x0D; + public static final byte DCONST_0 = (byte) 0x0E; + public static final byte DCONST_1 = (byte) 0x0F; + public static final byte BIPUSH = (byte) 0x10; + public static final byte SIPUSH = (byte) 0x11; + public static final byte LDC = (byte) 0x12; + public static final byte LDC_W = (byte) 0x13; + public static final byte LDC2_W = (byte) 0x14; + public static final byte ILOAD = (byte) 0x15; + public static final byte LLOAD = (byte) 0x16; + public static final byte FLOAD = (byte) 0x17; + public static final byte DLOAD = (byte) 0x18; + public static final byte ALOAD = (byte) 0x19; + public static final byte ILOAD_0 = (byte) 0x1A; + public static final byte ILOAD_1 = (byte) 0x1B; + public static final byte ILOAD_2 = (byte) 0x1C; + public static final byte ILOAD_3 = (byte) 0x1D; + public static final byte LLOAD_0 = (byte) 0x1E; + public static final byte LLOAD_1 = (byte) 0x1F; + public static final byte LLOAD_2 = (byte) 0x20; + public static final byte LLOAD_3 = (byte) 0x21; + public static final byte FLOAD_0 = (byte) 0x22; + public static final byte FLOAD_1 = (byte) 0x23; + public static final byte FLOAD_2 = (byte) 0x24; + public static final byte FLOAD_3 = (byte) 0x25; + public static final byte DLOAD_0 = (byte) 0x26; + public static final byte DLOAD_1 = (byte) 0x27; + public static final byte DLOAD_2 = (byte) 0x28; + public static final byte DLOAD_3 = (byte) 0x29; + public static final byte ALOAD_0 = (byte) 0x2A; + public static final byte ALOAD_1 = (byte) 0x2B; + public static final byte ALOAD_2 = (byte) 0x2C; + public static final byte ALOAD_3 = (byte) 0x2D; + public static final byte IALOAD = (byte) 0x2E; + public static final byte LALOAD = (byte) 0x2F; + public static final byte FALOAD = (byte) 0x30; + public static final byte DALOAD = (byte) 0x31; + public static final byte AALOAD = (byte) 0x32; + public static final byte BALOAD = (byte) 0x33; + public static final byte CALOAD = (byte) 0x34; + public static final byte SALOAD = (byte) 0x35; + public static final byte ISTORE = (byte) 0x36; + public static final byte LSTORE = (byte) 0x37; + public static final byte FSTORE = (byte) 0x38; + public static final byte DSTORE = (byte) 0x39; + public static final byte ASTORE = (byte) 0x3A; + public static final byte ISTORE_0 = (byte) 0x3B; + public static final byte ISTORE_1 = (byte) 0x3C; + public static final byte ISTORE_2 = (byte) 0x3D; + public static final byte ISTORE_3 = (byte) 0x3E; + public static final byte LSTORE_0 = (byte) 0x3F; + public static final byte LSTORE_1 = (byte) 0x40; + public static final byte LSTORE_2 = (byte) 0x41; + public static final byte LSTORE_3 = (byte) 0x42; + public static final byte FSTORE_0 = (byte) 0x43; + public static final byte FSTORE_1 = (byte) 0x44; + public static final byte FSTORE_2 = (byte) 0x45; + public static final byte FSTORE_3 = (byte) 0x46; + public static final byte DSTORE_0 = (byte) 0x47; + public static final byte DSTORE_1 = (byte) 0x48; + public static final byte DSTORE_2 = (byte) 0x49; + public static final byte DSTORE_3 = (byte) 0x4A; + public static final byte ASTORE_0 = (byte) 0x4B; + public static final byte ASTORE_1 = (byte) 0x4C; + public static final byte ASTORE_2 = (byte) 0x4D; + public static final byte ASTORE_3 = (byte) 0x4E; + public static final byte IASTORE = (byte) 0x4F; + public static final byte LASTORE = (byte) 0x50; + public static final byte FASTORE = (byte) 0x51; + public static final byte DASTORE = (byte) 0x52; + public static final byte AASTORE = (byte) 0x53; + public static final byte BASTORE = (byte) 0x54; + public static final byte CASTORE = (byte) 0x55; + public static final byte SASTORE = (byte) 0x56; + public static final byte POP = (byte) 0x57; + public static final byte POP2 = (byte) 0x58; + public static final byte DUP = (byte) 0x59; + public static final byte DUP_X1 = (byte) 0x5A; + public static final byte DUP_X2 = (byte) 0x5B; + public static final byte DUP2 = (byte) 0x5C; + public static final byte DUP2_X1 = (byte) 0x5D; + public static final byte DUP2_X2 = (byte) 0x5E; + public static final byte SWAP = (byte) 0x5F; + public static final byte IADD = (byte) 0x60; + public static final byte LADD = (byte) 0x61; + public static final byte FADD = (byte) 0x62; + public static final byte DADD = (byte) 0x63; + public static final byte ISUB = (byte) 0x64; + public static final byte LSUB = (byte) 0x65; + public static final byte FSUB = (byte) 0x66; + public static final byte DSUB = (byte) 0x67; + public static final byte IMUL = (byte) 0x68; + public static final byte LMUL = (byte) 0x69; + public static final byte FMUL = (byte) 0x6A; + public static final byte DMUL = (byte) 0x6B; + public static final byte IDIV = (byte) 0x6C; + public static final byte LDIV = (byte) 0x6D; + public static final byte FDIV = (byte) 0x6E; + public static final byte DDIV = (byte) 0x6F; + public static final byte IREM = (byte) 0x70; + public static final byte LREM = (byte) 0x71; + public static final byte FREM = (byte) 0x72; + public static final byte DREM = (byte) 0x73; + public static final byte INET = (byte) 0x74; + public static final byte LNEG = (byte) 0x75; + public static final byte FNEG = (byte) 0x76; + public static final byte DNEG = (byte) 0x77; + public static final byte ISHL = (byte) 0x78; + public static final byte LSHL = (byte) 0x79; + public static final byte ISHR = (byte) 0x7A; + public static final byte LSHR = (byte) 0x7B; + public static final byte IUSHR = (byte) 0x7C; + public static final byte LUSHR = (byte) 0x7D; + public static final byte IAND = (byte) 0x7E; + public static final byte LAND = (byte) 0x7F; + public static final byte IOR = (byte) 0x80; + public static final byte LOR = (byte) 0x81; + public static final byte IXOR = (byte) 0x82; + public static final byte LXOR = (byte) 0x83; + public static final byte IINC = (byte) 0x84; + public static final byte I2L = (byte) 0x85; + public static final byte I2F = (byte) 0x86; + public static final byte I2D = (byte) 0x87; + public static final byte L2I = (byte) 0x88; + public static final byte L2F = (byte) 0x89; + public static final byte L2D = (byte) 0x8A; + public static final byte F2I = (byte) 0x8B; + public static final byte F2L = (byte) 0x8C; + public static final byte F2D = (byte) 0x8D; + public static final byte D2I = (byte) 0x8E; + public static final byte D2L = (byte) 0x8F; + public static final byte D2F = (byte) 0x90; + public static final byte I2B = (byte) 0x91; + public static final byte I2C = (byte) 0x92; + public static final byte I2S = (byte) 0x93; + public static final byte LCMP = (byte) 0x94; + public static final byte FCMPL = (byte) 0x95; + public static final byte FCMPG = (byte) 0x96; + public static final byte DCMPL = (byte) 0x97; + public static final byte DCMPG = (byte) 0x98; + public static final byte IFEQ = (byte) 0x99; + public static final byte IFNE = (byte) 0x9A; + public static final byte IFLT = (byte) 0x9B; + public static final byte IFGE = (byte) 0x9C; + public static final byte IFGT = (byte) 0x9D; + public static final byte IFLE = (byte) 0x9E; + public static final byte IF_ICMPEQ = (byte) 0x9F; + public static final byte IF_ICMPNE = (byte) 0xA0; + public static final byte IF_ICMPLT = (byte) 0xA1; + public static final byte IF_ICMPGE = (byte) 0xA2; + public static final byte IF_ICMPGT = (byte) 0xA3; + public static final byte IF_ICMPLE = (byte) 0xA4; + public static final byte IF_ACMPEQ = (byte) 0xA5; + public static final byte IF_ACMPNE = (byte) 0xA6; + public static final byte GOTO = (byte) 0xA7; + public static final byte JSR = (byte) 0xA8; + public static final byte RET = (byte) 0xA9; + public static final byte TABLESWITCH = (byte) 0xAA; + public static final byte LOOKUPSWITCH = (byte) 0xAB; + public static final byte IRETURN = (byte) 0xAC; + public static final byte LRETURN = (byte) 0xAD; + public static final byte FRETURN = (byte) 0xAE; + public static final byte DRETURN = (byte) 0xAF; + public static final byte ARETURN = (byte) 0xB0; + public static final byte RETURN = (byte) 0xB1; + public static final byte GETSTATIC = (byte) 0xB2; + public static final byte PUTSTATIC = (byte) 0xB3; + public static final byte GETFIELD = (byte) 0xB4; + public static final byte PUTFIELD = (byte) 0xB5; + public static final byte INVOKEVIRTUAL = (byte) 0xB6; + public static final byte INVOKESPECIAL = (byte) 0xB7; + public static final byte INVOKESTATIC = (byte) 0xB8; + public static final byte INVOKEINTERFACE = (byte) 0xB9; + public static final byte NEW = (byte) 0xBB; + public static final byte NEWARRAY = (byte) 0xBC; + public static final byte ANEWARRAY = (byte) 0xBD; + public static final byte ARRAYLENGTH = (byte) 0xBE; + public static final byte ATHROW = (byte) 0xBF; + public static final byte CHECKCAST = (byte) 0xC0; + public static final byte INSTANCEOF = (byte) 0xC1; + public static final byte MONITORENTER = (byte) 0xC2; + public static final byte MONITOREXIT = (byte) 0xC3; + public static final byte WIDE = (byte) 0xC4; + public static final byte MULTIANEWARRAY = (byte) 0xC5; + public static final byte IFNULL = (byte) 0xC6; + public static final byte IFNONNULL = (byte) 0xC7; + public static final byte GOTO_W = (byte) 0xC8; + public static final byte JSR_W = (byte) 0xC9; +} diff --git a/src/org/ibex/classgen/CPGen.java b/src/org/ibex/classgen/CPGen.java new file mode 100644 index 0000000..91b002e --- /dev/null +++ b/src/org/ibex/classgen/CPGen.java @@ -0,0 +1,183 @@ +package org.ibex.classgen; + +import java.util.*; +import java.io.*; + +import org.ibex.classgen.util.*; + +public class CPGen { + private Hashtable entries = new Hashtable(); + private int nextIndex = 1; // 0 is reserved + private boolean sealed; + + CPGen() { } + + /* + * Entries + */ + abstract static class Ent implements Sort.Comparable { + int index; + public abstract int tag(); + public void dump(DataOutput o) throws IOException { o.writeByte(tag()); } + public int compareTo(Object o) { + if(!(o instanceof Ent)) return 1; + int oi = ((Ent)o).index; + if(index < oi) return -1; + if(index > oi) return 1; + return 0; + } + } + + abstract static class OneU2Ent extends Ent { int i; public void dump(DataOutput o) throws IOException { super.dump(o); o.writeShort(i); } } + abstract static class OneU4Ent extends Ent { int i; public void dump(DataOutput o) throws IOException { super.dump(o); o.writeInt(i); } } + abstract static class TwoU2Ent extends OneU2Ent { int i2; public void dump(DataOutput o) throws IOException { super.dump(o); o.writeShort(i2); } } + abstract static class TwoU4Ent extends OneU4Ent { int i2; public void dump(DataOutput o) throws IOException { super.dump(o); o.writeInt(i2); } } + + static class IntEnt extends OneU4Ent { public int tag() { return 3; } } // word1: bytes + static class FloatEnt extends OneU4Ent { public int tag() { return 4; } } // word1: bytes + static class LongEnt extends TwoU4Ent { public int tag() { return 5; } } // word1/2: bytes + static class DoubleEnt extends TwoU4Ent { public int tag() { return 6; } } // word1/2: bytes + static class ClassEnt extends OneU2Ent { public int tag() { return 7; } } // word1: name_index + static class StringEnt extends OneU2Ent { public int tag() { return 8; } } // word1: string_index + static class FieldRefEnt extends TwoU2Ent { public int tag() { return 9; } } // word1: class_index word2: name_and_type_index + static class MethodRefEnt extends TwoU2Ent { public int tag() { return 10; } } // word1: class_index word2: name_and_type_index + static class IMethodRefEnt extends TwoU2Ent { public int tag() { return 11; } } // word1: class_index word2: name_and_type_index + static class NameAndTypeEnt extends TwoU2Ent { public int tag() { return 12; } } // word1: name_index word2: descriptor_index + + static class Utf8Ent extends Ent { + String s; + public int tag() { return 1; } + public void dump(DataOutput o) throws IOException { + super.dump(o); + o.writeUTF(s); + } + public String toString() { return "Utf8: " + s; } + } + + /* + * Cache Keys + */ + static class Utf8Key { + String s; + public Utf8Key(String s) { this.s = s; } + public boolean equals(Object o) { return o instanceof Utf8Key && ((Utf8Key)o).s.equals(s); } + public int hashCode() { return ~s.hashCode(); } + } + + public static class NameAndType { + String name; + String type; + public NameAndType(String name, String type) { this.name = name; this.type = type; } + public boolean equals(Object o_) { + if(!(o_ instanceof NameAndType)) return false; + NameAndType o = (NameAndType) o_; + return o.name.equals(name) && o.type.equals(type); + } + public int hashCode() { return name.hashCode() ^ type.hashCode(); } + } + + static abstract class FieldMethodRef { + Type.Object klass; + NameAndType nameAndType; + public FieldMethodRef(Type.Object klass, NameAndType nameAndType) { this.klass = klass; this.nameAndType = nameAndType; } + public boolean equals(Object o_) { + if(!(o_ instanceof FieldMethodRef)) return false; + FieldMethodRef o = (FieldMethodRef) o_; + return o.klass.equals(klass) && o.nameAndType.equals(nameAndType); + } + } + + public static class FieldRef extends FieldMethodRef { public FieldRef (Type.Object c, NameAndType t) { super(c,t); } } + public static class MethodRef extends FieldMethodRef { public MethodRef (Type.Object c, NameAndType t) { super(c,t); } } + public static class IMethodRef extends FieldMethodRef { public IMethodRef(Type.Object c, NameAndType t) { super(c,t); } } + + /* + * Methods + */ + public void seal() { sealed = true; } + + public final Ent get(Object o) { return (Ent) entries.get(o); } + public final Ent getUtf8(String s) { return get(new Utf8Key(s)); } + + public final Ent addNameAndType(String name, String descriptor) { return add(new NameAndType(name,descriptor)); } + public final Ent addUtf8(String s) { return add(new Utf8Key(s)); } + + public final Ent add(Object o) { + if(sealed) throw new IllegalStateException("constant pool is sealed"); + + Ent ent = get(o); + if(ent != null) return ent; + + if(nextIndex == 65536) throw new ClassGen.Exn("constant pool full"); + + if(o instanceof Type.Object) { + ClassEnt ce = new ClassEnt(); + ce.i = addUtf8(((Type.Object)o).internalForm()).index; + ent = ce; + } else if(o instanceof String) { + StringEnt se = new StringEnt(); + se.i = addUtf8((String)o).index; + ent = se; + } else if(o instanceof Integer) { + IntEnt ie = new IntEnt(); + ie.i = ((Integer)o).intValue(); + ent = ie; + } else if(o instanceof Float) { + FloatEnt fe = new FloatEnt(); + fe.i = Float.floatToIntBits(((Float)o).floatValue()); + ent = fe; + } else if(o instanceof Long) { + LongEnt le = new LongEnt(); + long l = ((Long)o).longValue(); + le.i = (int)(l>>>32); + le.i2 = (int)l; + ent = le; + } else if(o instanceof Double) { + DoubleEnt de = new DoubleEnt(); + long l = Double.doubleToLongBits(((Double)o).doubleValue()); + de.i = (int)(l>>>32); + de.i2 = (int)l; + ent = de; + } else if(o instanceof Utf8Key) { + Utf8Ent ue = new Utf8Ent(); + ue.s = ((Utf8Key)o).s; + ent = ue; + } else if(o instanceof NameAndType) { + NameAndTypeEnt ne = new NameAndTypeEnt(); + NameAndType key = (NameAndType) o; + ne.i = addUtf8(key.name).index; + ne.i2 = addUtf8(key.type).index; + ent = ne; + } else if(o instanceof FieldMethodRef) { + FieldMethodRef key = (FieldMethodRef) o; + TwoU2Ent fme; + if(o instanceof MethodRef) fme = new MethodRefEnt(); + else if(o instanceof IMethodRef) fme = new IMethodRefEnt(); + else if(o instanceof FieldRef) fme = new FieldRefEnt(); + else throw new Error("should never happen"); + fme.i = add(key.klass).index; + fme.i2 = add(key.nameAndType).index; + ent = fme; + } else { + throw new IllegalArgumentException("Unknown type passed to add"); + } + + ent.index = nextIndex++; + entries.put(o,ent); + return ent; + } + + public int size() { return nextIndex; } + + public void dump(DataOutput o) throws IOException { + Ent[] ents = new Ent[nextIndex-1]; + int i=0; + Enumeration e = entries.keys(); + while(e.hasMoreElements()) ents[i++] = (Ent) entries.get(e.nextElement()); + Sort.sort(ents); + for(i=0;i= 256) op = LDC_W; break; + } + this.op[pos] = op; + this.arg[pos] = arg; + } + + public final void setPushConst(int pos, int n) { + switch(n) { + case -1: set(pos,ICONST_M1); break; + case 0: set(pos,ICONST_0); break; + case 1: set(pos,ICONST_1); break; + case 2: set(pos,ICONST_2); break; + case 3: set(pos,ICONST_3); break; + case 4: set(pos,ICONST_4); break; + case 5: set(pos,ICONST_5); break; + default: + if(n >= -128 && n <= 127) set(pos,BIPUSH,n); + if(n >= -32767 && n <= 32767) set(pos,SIPUSH,n); + setLDC(pos,N(n)); + break; + } + } + public final void setPushConst(int pos, long l) { + if(l==0) set(pos,LCONST_0); + else if(l==1) set(pos,LCONST_1); + else setLDC(pos,N(l)); + } + + public final void setPushConst(int pos, float f) { + if(f == 1.0f) set(pos,FCONST_0); + else if(f == 1.0f) set(pos,FCONST_1); + else if(f == 2.0f) set(pos,FCONST_2); + else setLDC(pos,N(f)); + } + public final void setPushConst(int pos, double d) { + if(d == 1.0) set(pos,DCONST_0); + else if(d == 2.0) set(pos,DCONST_1); + else setLDC(pos,N(d)); + } + public final void setPushConst(int pos, Object o) { + if(o instanceof Integer) setPushConst(pos,((Integer)o).intValue()); + else if(o instanceof Long) setPushConst(pos,((Long)o).longValue()); + else if(o instanceof Float) setPushConst(pos,((Float)o).floatValue()); + else if(o instanceof Double) setPushConst(pos,((Double)o).doubleValue()); + else setLDC(pos,o); + } + + private void setLDC(int pos, Object o) { set(pos,LDC,cp.add(o)); } + + public final CPGen.Ent methodRef(Type.Object c, String name, Type ret, Type[] args) { + return methodRef(c,name,MethodGen.descriptor(ret,args)); + } + public final CPGen.Ent methodRef(Type.Object c, String name, String descriptor) { + return cp.add(new CPGen.MethodRef(c,new CPGen.NameAndType(name,descriptor))); + } + public final CPGen.Ent fieldRef(Type.Object c, String name, Type type) { + return fieldRef(c,name,type.getDescriptor()); + } + public final CPGen.Ent fieldRef(Type.Object c, String name, String descriptor) { + return cp.add(new CPGen.FieldRef(c,new CPGen.NameAndType(name,descriptor))); + } + + public void setMaxLocals(int maxLocals) { this.maxLocals = maxLocals; } + public void setMaxStack(int maxStack) { this.maxStack = maxStack; } + + public void finish() { + try { + _finish(); + } catch(IOException e) { + throw new Error("should never happen"); + } + } + + private void _finish() throws IOException { + if(size == -1) return; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutput o = new DataOutputStream(baos); + + int[] pc = new int[size]; + int[] maxpc = pc; + int p,i; + + // Pass1 - Calculate maximum pc of each bytecode + for(i=0,p=0;i 32767) + op[i] = op[i] == GOTO ? GOTO_W : JSR_W; + } + } + } + // Pass3 - Calculate actual pc + for(i=0,p=0;i 255 || pair[1] < -128 || pair[1] > 127) throw new ClassGen.Exn("overflow of iinc arg"); + o.writeByte(pair[0]); + o.writeByte(pair[1]); + continue; + } + case IF_ICMPLT: + case GOTO: + case GOTO_W: + case JSR: + case JSR_W: + outArg = pc[iarg] - pc[i]; + if(outArg < -32768 || outArg > 32767) throw new ClassGen.Exn("overflow of s2 offset"); + break; + case INVOKESTATIC: + case INVOKESPECIAL: + case INVOKEVIRTUAL: + case GETSTATIC: + case PUTSTATIC: + case GETFIELD: + case PUTFIELD: + case LDC_W: + case LDC: + outArg = ((CPGen.Ent)arg).index; + break; + } + + if(argLength == 1) o.writeByte(outArg); + else if(argLength == 2) o.writeShort(outArg); + else throw new Error("should never happen"); + } + + o.writeShort(0); // FIXME: Exception table + o.writeShort(codeAttrs.size()); + codeAttrs.dump(o); + + baos.close(); + + byte[] codeAttribute = baos.toByteArray(); + attrs.add("Code",codeAttribute); + size = -1; + } + + public void dump(DataOutput o) throws IOException { + o.writeShort(flags); + o.writeShort(nameIndex); + o.writeShort(descriptorIndex); + o.writeShort(attrs.size()); + attrs.dump(o); + } + + private static int opArgLength(byte op) { + switch(op) { + case NOP: + case ICONST_M1: + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + case LCONST_0: + case LCONST_1: + case FCONST_0: + case FCONST_1: + case FCONST_2: + case DCONST_0: + case DCONST_1: + case ILOAD_0: + case ILOAD_1: + case ILOAD_2: + case ILOAD_3: + case ISTORE_0: + case ISTORE_1: + case ISTORE_2: + case ISTORE_3: + case RETURN: + return 0; + case LDC: + case BIPUSH: + case ILOAD: + case ISTORE: + return 1; + case LDC_W: + case SIPUSH: + case GETSTATIC: + case PUTSTATIC: + case GETFIELD: + case PUTFIELD: + case INVOKESTATIC: + case INVOKEVIRTUAL: + case INVOKESPECIAL: + case IINC: + case GOTO: + case JSR: + case IF_ICMPLT: + return 2; + default: + throw new ClassGen.Exn("unknown bytecode " + Integer.toHexString(op&0xff)); + } + } + + private static Integer N(int n) { return new Integer(n); } + private static Long N(long n) { return new Long(n); } + private static Float N(float f) { return new Float(f); } + private static Double N(double d) { return new Double(d); } + private static int max(int a, int b) { return a > b ? a : b; } +} diff --git a/src/org/ibex/classgen/Type.java b/src/org/ibex/classgen/Type.java new file mode 100644 index 0000000..87705b4 --- /dev/null +++ b/src/org/ibex/classgen/Type.java @@ -0,0 +1,49 @@ +package org.ibex.classgen; + +import java.util.StringTokenizer; + +public class Type { + public static final Type VOID = new Type("V"); + public static final Type INT = new Type("I"); + public static final Type STRING = new Type.Object("java.lang.String"); + public static final Type[] NO_ARGS = new Type[0]; + + String descriptor; + + Type() { } + Type(String descriptor) { this.descriptor = descriptor; } + + public final String getDescriptor() { return descriptor; } + public int hashCode() { return descriptor.hashCode(); } + public boolean equals(Object o) { return o instanceof Type && ((Type)o).descriptor.equals(descriptor); } + + public static Type arrayType(Type base) { return arrayType(base,1); } + public static Type arrayType(Type base, int dim) { + StringBuffer sb = new StringBuffer(base.descriptor.length() + dim); + for(int i=0;i= end) return; + if(end-start <= 6) { + for(int i=start+1;i<=end;i++) { + tmp = a[i]; + int j; + for(j=i-1;j>=start;j--) { + if(c.compare(a[j],tmp) <= 0) break; + a[j+1] = a[j]; + } + a[j+1] = tmp; + } + return; + } + + Object pivot = a[end]; + int lo = start - 1; + int hi = end; + + do { + while((lo < hi) && c.compare(a[++lo],pivot) < 0) { } + while((hi > lo) && c.compare(a[--hi],pivot) > 0) { } + tmp = a[lo]; a[lo] = a[hi]; a[hi] = tmp; + } while(lo < hi); + + tmp = a[lo]; a[lo] = a[end]; a[end] = tmp; + + sort(a, c, start, lo-1); + sort(a, c, lo+1, end); + } +} -- 1.7.10.4