summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2009-05-06 13:44:21 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2009-05-06 13:44:21 +0000
commit4304b157308ef9511f63abc66e8da44291bf7c41 (patch)
tree6b93bc80411995b991a648d91ac2d7d40305c424
parentba42c086e128d4d4991b517ebbfe2136c1301911 (diff)
downloadscala-4304b157308ef9511f63abc66e8da44291bf7c41.tar.gz
scala-4304b157308ef9511f63abc66e8da44291bf7c41.tar.bz2
scala-4304b157308ef9511f63abc66e8da44291bf7c41.zip
MSIL is built as part of Sabbus, take 2.
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Assembly.java254
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/AssemblyName.java97
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Attribute.java558
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/BindingFlags.java170
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/CallingConventions.java76
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java55
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/CustomAttributeProvider.java83
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/EventAttributes.java33
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/EventInfo.java59
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/FieldAttributes.java120
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java113
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/ICustomAttributeProvider.java58
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/MemberInfo.java48
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/MemberTypes.java82
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/MethodAttributes.java159
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java145
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/MethodImplAttributes.java117
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java57
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Module.java156
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEAssembly.java70
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEFile.java870
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEModule.java327
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEType.java399
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/ParameterAttributes.java73
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/ParameterInfo.java77
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PropertyAttributes.java46
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PropertyInfo.java105
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Type.java1042
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/TypeAttributes.java191
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Version.java72
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala125
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ConstructorBuilder.scala65
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/EmitUtils.scala55
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/EmitUtils.scala255
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/EmptyVisitor.scala83
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/EmptyVisitor.scala283
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala58
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ICustomAttributeSetter.scala19
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala538
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala735
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala149
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/LocalBuilder.scala45
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/MethodBuilder.scala71
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala134
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala139
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala1935
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala1196
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ParameterBuilder.scala45
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala94
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala230
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/Visitable.scala25
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/Visitor.scala59
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/tests/CustomAttributesTest.java32
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/tests/JavaTypeTest.java19
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/tests/MembersTest.java101
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/tests/TableDump.java312
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/tests/Test.java93
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/util/PESection.java58
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/util/PEStream.java200
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/util/Signature.java119
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/util/Table.java1600
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/util/VJSAssembly.java294
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/util/VJSAssembly.java2294
63 files changed, 14772 insertions, 0 deletions
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java b/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java
new file mode 100644
index 0000000000..509575b26e
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Assembly.java
@@ -0,0 +1,254 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import ch.epfl.lamp.compiler.msil.util.Table;
+import ch.epfl.lamp.compiler.msil.util.Table.AssemblyDef;
+import ch.epfl.lamp.compiler.msil.util.Table.ModuleDef;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Defines an Assembly, which is a reusable, versionable, and self-describing
+ * building block of a common language runtime application.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class Assembly extends CustomAttributeProvider {
+
+ //##########################################################################
+ // static members
+
+ // all the assemblies
+ public static final HashMap assemblies = new HashMap();
+
+ /** Loads an assembly from the specified path. */
+ public static Assembly LoadFrom(String assemblyFileName) {
+ File afile = new File(assemblyFileName);
+ return LoadFrom(afile.getParentFile(), afile.getName());
+ }
+
+ /** Loads an assembly with the given name from the given directory. */
+ public static Assembly LoadFrom(File dir, String name) {
+ File file = null;
+ PEFile pefile = null;
+// try {
+// if (dir == null)
+// dir = new File(".");
+// dir = dir.getCanonicalFile();
+// } catch (java.io.IOException e) {}
+
+ if (name.endsWith(".exe") || name.endsWith(".EXE") ||
+ name.endsWith(".dll") || name.endsWith(".DLL"))
+ {
+ file = new File(dir, name);
+ pefile = getPEFile(file);
+ name = name.substring(0, name.length() - 4);
+ }
+
+ File adir = pefile == null ? new File(dir, name) : null;
+
+ if (pefile == null) {
+ file = new File(dir, name + ".dll");
+ pefile = getPEFile(file);
+ }
+ if (pefile == null) {
+ file = new File(dir, name + ".DLL");
+ pefile = getPEFile(file);
+ }
+ if (pefile == null && adir.exists()) {
+ file = new File(adir, name + ".dll");
+ pefile = getPEFile(file);
+ }
+ if (pefile == null && adir.exists()) {
+ file = new File(adir, name + ".DLL");
+ pefile = getPEFile(file);
+ }
+
+ if (pefile == null) {
+ file = new File(dir, name + ".exe");
+ pefile = getPEFile(file);
+ }
+ if (pefile == null) {
+ file = new File(dir, name + ".EXE");
+ pefile = getPEFile(file);
+ }
+ if (pefile == null && adir.exists()) {
+ file = new File(adir, name + ".exe");
+ pefile = getPEFile(file);
+ }
+ if (pefile == null && adir.exists()) {
+ file = new File(adir, name + ".EXE");
+ pefile = getPEFile(file);
+ }
+
+ if (pefile == null)
+ throw new RuntimeException("Cannot find assembly " + new File(dir, name));
+ return getPEAssembly(pefile);
+ }
+
+ private static Assembly getPEAssembly(PEFile pefile) {
+ AssemblyDef assem = pefile.AssemblyDef;
+ if (assem == null)
+ throw new RuntimeException("File " + pefile
+ + " does not contain a manifest");
+ assem.readRow(1);
+ String name = pefile.getString(assem.Name);
+ Assembly a = (Assembly) assemblies.get(name);
+ if (a != null) {
+ return a;
+ }
+
+ AssemblyName an = new AssemblyName();
+ an.Name = pefile.getString(assem.Name);
+ an.Version = new Version(assem.MajorVersion, assem.MinorVersion,
+ assem.BuildNumber, assem.RevisionNumber);
+ an.SetPublicKey(pefile.getBlob(assem.PublicKey));
+ return new PEAssembly(pefile, an);
+ }
+
+ protected static PEFile getPEFile(File f) {
+ PEFile pefile = null;
+ try { pefile = new PEFile(f.getAbsolutePath()); }
+ catch (FileNotFoundException e) {}
+ catch (RuntimeException e) {}
+ return pefile;
+ }
+
+ //##########################################################################
+ // public fields
+
+ /** The entry point of this assembly. */
+ public MethodInfo EntryPoint;
+
+ /** the display name of the assembly. */
+ public final String FullName;
+
+ //##########################################################################
+ // constructor
+
+ protected Assembly(AssemblyName an, boolean external) {
+ assemblyName = an;
+ FullName = an.toString();
+ if(external) {
+ assemblies.put(an.Name, this);
+ }
+ //System.out.println("assemblies after adding the current one: " + assemblies);
+ }
+
+ protected Assembly(AssemblyName an) {
+ this(an, false);
+ }
+
+ protected static Assembly getAssembly(String name) {
+ return (Assembly) assemblies.get(name);
+ }
+
+ //##########################################################################
+ // instrumental methods
+
+ /** @return the file from which this assembly was loaded. */
+ public File getFile() {
+ throw new RuntimeException("Not supported");
+ }
+
+ /** Gets the specified module in this assembly. Works on filenames. */
+ public Module GetModule(String name) {
+ initModules();
+ return (Module)modulesMap.get(name);
+ }
+
+ /** Get all the modules of the assembly. */
+ public Module[] GetModules() {
+ initModules();
+ return (Module[])modulesMap.values().
+ toArray(new Module[modulesMap.size()]);
+ }
+
+ /** Get the corresponding type. */
+ public Type GetType(String name) {
+ initModules();
+ Iterator modules = modulesMap.values().iterator();
+ Type t = null;
+ while (t == null && modules.hasNext()) {
+ t = ((Module)modules.next()).GetType(name);
+ }
+ return t;
+ }
+
+ /** @return an array of all types defined in the assembly. */
+ public synchronized Type[] GetTypes() {
+ if (types != null)
+ return (Type[])types.clone();
+ initModules();
+
+ Iterator modules = modulesMap.values().iterator();
+ Type[] newTypes = ((Module)modules.next()).GetTypes();
+ while (modules.hasNext()) {
+ Module module = (Module)modules.next();
+ Type[] mtypes = module.GetTypes();
+ Type[] oldTypes = newTypes;
+ newTypes = new Type[oldTypes.length + mtypes.length];
+ System.arraycopy(oldTypes, 0, newTypes, 0, oldTypes.length);
+ System.arraycopy(mtypes, 0, newTypes, oldTypes.length, mtypes.length);
+ }
+ types = newTypes;
+ return (Type[]) types.clone();
+ }
+
+ public AssemblyName GetName() {
+ return assemblyName;
+ }
+
+ public String toString() {
+ return FullName;
+ }
+
+ //##########################################################################
+ // protected members
+
+ // the assembly name
+ protected final AssemblyName assemblyName;
+
+ // all the types exported by the assembly
+ protected Type[] types = null;
+
+ // the module defined in this assembly (only one right now)
+ private final HashMap/*<String, Module>*/ modulesMap = new HashMap();
+
+ protected void addType(Type type) {
+ Type.addType(type);
+ }
+
+ protected void addModule(String name, Module module) {
+ modulesMap.put(name, module);
+ }
+
+ private boolean initModules = true;
+ protected final void initModules() {
+ if (initModules) {
+ loadModules();
+ initModules = false;
+ }
+ }
+
+ /** used for lazy construction of the Assembly. */
+ protected abstract void loadModules();
+
+ void dumpTypes() {
+ Type[] types = GetTypes();
+ for (int i = 0; i < types.length; i++)
+ System.out.println(types[i]);
+ }
+
+ //##########################################################################
+
+} // class Assembly
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/AssemblyName.java b/src/msil/ch/epfl/lamp/compiler/msil/AssemblyName.java
new file mode 100644
index 0000000000..3e1b6a6f57
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/AssemblyName.java
@@ -0,0 +1,97 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import javax.crypto.Mac;
+
+import java.security.MessageDigest;
+
+import ch.epfl.lamp.compiler.msil.util.Table;
+
+/**
+ * Fully describes an assembly's unique identity.
+ * Right now it's only the name
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public class AssemblyName {
+
+ //##########################################################################
+ // public interface
+
+ /** The simple, unencrypted name of the assembly. */
+ public String Name;
+
+ /**
+ * Gets or sets the major, minor, revision, and build numbers
+ * of the assembly.
+ */
+ public Version Version;
+
+ /**
+ * Gets a strong name consisting of a public key, a given name,
+ * and version parts.
+ */
+ public byte[] GetPublicKeyToken() {
+ return publicKeyToken == null ? null : (byte[]) publicKeyToken.clone();
+ }
+
+ /**
+ * Sets a strong name consisting of a public key, a given name,
+ * and version parts.
+ */
+ public void SetPublicKeyToken(byte[] key) {
+ this.publicKeyToken = key.length == 0 ? null : (byte[]) key.clone();
+ }
+
+ /**
+ * Returns the public key identifying the originator of the assembly.
+ */
+ public byte[] GetPublicKey() {
+ return publicKey == null ? null : (byte[]) publicKey.clone();
+ }
+
+ /**
+ * Sets the public key identifying the originator of the assembly.
+ */
+ public void SetPublicKey(byte[] key) {
+ if (key.length > 0) {
+ this.publicKey = (byte[]) key.clone();
+ byte[] hash = sha.digest(key);
+ byte[] keyToken = new byte[8];
+ for (int i = 0; i < keyToken.length; i++)
+ keyToken[i] = hash[hash.length - 1 - i];
+ this.publicKeyToken = keyToken;
+ //System.out.println("Pubic key and key token of assembly " + this + ":");
+ //System.out.println("\tPublic key = " + Table.bytes2hex(key));
+ //System.out.println("\tKey token = " + Table.bytes2hex(keyToken));
+ }
+ }
+
+ public String toString() {
+ return Name + ", Version=" + Version;
+ }
+
+ //##########################################################################
+
+ private byte[] publicKeyToken;
+
+ private byte[] publicKey;
+
+ private static final MessageDigest sha;
+ static {
+ MessageDigest md = null;
+ try {
+ md = MessageDigest.getInstance("SHA");
+ } catch (java.security.NoSuchAlgorithmException e) {}
+ sha = md;
+ }
+
+ //##########################################################################
+
+} // class AssemblyName
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java b/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java
new file mode 100644
index 0000000000..b136f9423e
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Attribute.java
@@ -0,0 +1,558 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import ch.epfl.lamp.compiler.msil.util.Signature;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Iterator;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Describes custom attribute instances.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public class Attribute {
+
+ //##########################################################################
+
+ private final ConstructorInfo constr;
+
+ private final byte[] value;
+
+ Attribute(ConstructorInfo constr, byte[] value) {
+ assert constr != null;
+ this.constr = constr;
+ assert value != null : constr.toString();
+ this.value = value;
+ }
+
+ //##########################################################################
+ // public interface
+
+ /** @return the type (class) of the attribute. */
+ public Type GetType() { return constr.DeclaringType; }
+
+ /** @return the constructor of this attribute. */
+ public ConstructorInfo getConstructor() {
+ return constr;
+ }
+
+ /** @return the Blob with serialized constructor & named arguments. */
+ public byte[] getValue() {
+ byte[] value = new byte[this.value.length];
+ System.arraycopy(this.value, 0, value, 0, value.length);
+ return value;
+ }
+
+ /**@return an array with the arguments to the attribute's contructor. */
+ public Object[] getConstructorArguments() {
+ parseBlob();
+ Object[] cas = new Object[constrArgs.length];
+ System.arraycopy(constrArgs, 0, cas, 0, cas.length);
+ return cas;
+ }
+
+ /** @return the named argument with the given name. */
+ public NamedArgument getNamedArgument(String name) {
+ return (NamedArgument)namedArgs.get(name);
+ }
+
+ /** @return an array of all named arguments for this attribute. */
+ public NamedArgument[] getNamedArguments() {
+ NamedArgument[] nargs =
+ (NamedArgument[])namedArgs.values().toArray(NamedArgument.EMPTY);
+ return nargs;
+ }
+
+ /** @return a string representation of this attribute. */
+ public String toString() {
+ parseBlob();
+ ParameterInfo[] params = constr.GetParameters();
+ assert params.length == constrArgs.length : this.constr;
+ StringBuffer str = new StringBuffer();
+ str.append('[');
+ str.append(constr.DeclaringType.FullName);
+ str.append('(');
+ for (int i = 0; i < constrArgs.length; i++) {
+ if (i > 0)
+ str.append(", ");
+ Type t = params[i].ParameterType;
+ if (t.IsEnum()) {
+ str.append('(');
+ str.append(t.FullName);
+ str.append(')');
+ }
+ formatValue(str, constrArgs[i]);
+ }
+ NamedArgument[] nargs = getNamedArguments();
+ for (int i = 0; i < nargs.length; i++) {
+ str.append(", ").append(nargs[i]);
+ }
+ str.append(")]");
+ return str.toString();
+ }
+
+ //#########################################################################
+
+ private static final Map type2id = new HashMap();
+ private static final Map id2type = new HashMap();
+ static {
+ map("Boolean", Signature.ELEMENT_TYPE_BOOLEAN);
+ map("Char", Signature.ELEMENT_TYPE_CHAR);
+ map("SByte", Signature.ELEMENT_TYPE_I1);
+ map("Byte", Signature.ELEMENT_TYPE_U1);
+ map("Int16", Signature.ELEMENT_TYPE_I2);
+ map("UInt16", Signature.ELEMENT_TYPE_U2);
+ map("Int32", Signature.ELEMENT_TYPE_I4);
+ map("UInt32", Signature.ELEMENT_TYPE_U4);
+ map("Int64", Signature.ELEMENT_TYPE_I8);
+ map("UInt64", Signature.ELEMENT_TYPE_U8);
+ map("Single", Signature.ELEMENT_TYPE_R4);
+ map("Double", Signature.ELEMENT_TYPE_R8);
+ map("String", Signature.ELEMENT_TYPE_STRING);
+ map("Type", Signature.X_ELEMENT_TYPE_TYPE);
+ map("Object", Signature.ELEMENT_TYPE_OBJECT);
+ }
+ private static void map(String type, int id) {
+ Type t = Type.GetType("System." + type);
+ assert type != null : type + " -> " + id;
+ Integer i = new Integer(id);
+ type2id.put(t, i);
+ id2type.put(i, t);
+ }
+ private static int getTypeId(Type type) {
+ Integer id = (Integer)type2id.get(type);
+ assert id != null : type;
+ return id.intValue();
+ }
+
+ private Object[] constrArgs;
+ private Map namedArgs;
+ private ByteBuffer buf;
+
+ private void parseBlob() {
+ try { parseBlob0(); }
+ catch (RuntimeException e) {
+ throw new RuntimeException(PEFile.bytes2hex(value), e);
+ }
+ }
+
+ private void parseBlob0() {
+ if (buf != null)
+ return;
+ buf = ByteBuffer.wrap(value);
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+
+ short sig = buf.getShort();
+ assert sig == 1 : PEFile.bytes2hex(value);
+ ParameterInfo[] params = constr.GetParameters();
+ constrArgs = new Object[params.length];
+ for (int i = 0; i < params.length; i++) {
+ constrArgs[i] = parseElement(params[i].ParameterType);
+ }
+
+ int ncount = buf.getShort();
+ namedArgs = new LinkedHashMap();
+ for (int i = 0; i < ncount; i++) {
+ int designator = buf.get();
+ assert designator == Signature.X_ELEMENT_KIND_FIELD
+ || designator == Signature.X_ELEMENT_KIND_PROPERTY
+ : "0x" + PEFile.byte2hex(designator);
+ Type type = parseType();
+ String name = parseString();
+ Object value = parseElement(type);
+ NamedArgument narg =
+ new NamedArgument(designator, name, type, value);
+ namedArgs.put(name, narg);
+ }
+ }
+
+ private Object parseElement(Type type) {
+ if (type.IsArray())
+ return parseArray(type.GetElementType());
+ if (type.IsEnum())
+ return parseElement(type.getUnderlyingType());
+ return parseElement(getTypeId(type));
+ }
+
+ private Object parseElement(int id) {
+ switch (id) {
+ case Signature.ELEMENT_TYPE_BOOLEAN:
+ return new Boolean(buf.get() == 0 ? false : true);
+ case Signature.ELEMENT_TYPE_CHAR:
+ return new Character(buf.getChar());
+ case Signature.ELEMENT_TYPE_I1:
+ case Signature.ELEMENT_TYPE_U1:
+ return new Byte(buf.get());
+ case Signature.ELEMENT_TYPE_I2:
+ case Signature.ELEMENT_TYPE_U2:
+ return new Short(buf.getShort());
+ case Signature.ELEMENT_TYPE_I4:
+ case Signature.ELEMENT_TYPE_U4:
+ return new Integer(buf.getInt());
+ case Signature.ELEMENT_TYPE_I8:
+ case Signature.ELEMENT_TYPE_U8:
+ return new Long(buf.getLong());
+ case Signature.ELEMENT_TYPE_R4:
+ return new Float(buf.getFloat());
+ case Signature.ELEMENT_TYPE_R8:
+ return new Double(buf.getDouble());
+ case Signature.ELEMENT_TYPE_STRING:
+ return parseString();
+ case Signature.X_ELEMENT_TYPE_TYPE:
+ return getType();
+ case Signature.ELEMENT_TYPE_OBJECT:
+ Type type = parseType();
+ return new BoxedArgument(type, parseElement(type));
+ default:
+ throw new RuntimeException("Unknown type id: " + id);
+ }
+ }
+
+ private Object parseArray(Type type) {
+ if (type.IsEnum())
+ return parseArray(type.getUnderlyingType());
+ return parseArray(getTypeId(type));
+ }
+
+ private Object parseArray(int id) {
+ switch (id) {
+ case Signature.ELEMENT_TYPE_BOOLEAN:
+ return parseBooleanArray();
+ case Signature.ELEMENT_TYPE_CHAR:
+ return parseCharArray();
+ case Signature.ELEMENT_TYPE_I1:
+ case Signature.ELEMENT_TYPE_U1:
+ return parseByteArray();
+ case Signature.ELEMENT_TYPE_I2:
+ case Signature.ELEMENT_TYPE_U2:
+ return parseShortArray();
+ case Signature.ELEMENT_TYPE_I4:
+ case Signature.ELEMENT_TYPE_U4:
+ return parseIntArray();
+ case Signature.ELEMENT_TYPE_I8:
+ case Signature.ELEMENT_TYPE_U8:
+ return parseLongArray();
+ case Signature.ELEMENT_TYPE_R4:
+ return parseFloatArray();
+ case Signature.ELEMENT_TYPE_R8:
+ return parseDoubleArray();
+ case Signature.ELEMENT_TYPE_STRING:
+ return parseStringArray();
+ case Signature.X_ELEMENT_TYPE_ENUM:
+ return parseArray(getType());
+ default:
+ throw new RuntimeException("Unknown type id: " + id);
+ }
+ }
+
+ private Type parseType() {
+ int id = buf.get();
+ switch (id) {
+ case Signature.ELEMENT_TYPE_SZARRAY:
+ return Type.mkArray(parseType(), 1);
+ case Signature.X_ELEMENT_TYPE_ENUM:
+ return getType();
+ default:
+ Type t = (Type)id2type.get(new Integer(id));
+ assert t != null : PEFile.byte2hex(id);
+ return t;
+ }
+ }
+
+ private Type getType() {
+ String typename = parseString();
+ int i = typename.indexOf(',');
+ // fully qualified assembly name follows
+ // just strip it on the assumtion theat the
+ // assembly is referenced in the externs and the
+ // type will be found
+ String name = (i < 0) ? typename : typename.substring(0, i);
+ Type t = Type.GetType(name);
+ if (t == null && i > 0) {
+ int j = typename.indexOf(',', i + 1);
+ if (j > 0) {
+ String assemName = typename.substring(i + 1, j);
+ try {
+ Assembly.LoadFrom(assemName);
+ } catch (Throwable e) {
+ throw new RuntimeException(typename, e);
+ }
+ t = Type.GetType(name);
+ }
+ }
+ assert t != null : typename;
+ return t;
+ }
+
+ private boolean[] parseBooleanArray() {
+ boolean[] arr = new boolean[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = buf.get() == 0 ? false : true;
+ return arr;
+ }
+
+ private char[] parseCharArray() {
+ char[] arr = new char[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = buf.getChar();
+ return arr;
+ }
+
+ private byte[] parseByteArray() {
+ byte[] arr = new byte[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = buf.get();
+ return arr;
+ }
+
+ private short[] parseShortArray() {
+ short[] arr = new short[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = buf.getShort();
+ return arr;
+ }
+
+ private int[] parseIntArray() {
+ int[] arr = new int[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = buf.getInt();
+ return arr;
+ }
+
+ private long[] parseLongArray() {
+ long[] arr = new long[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = buf.getLong();
+ return arr;
+ }
+
+ private float[] parseFloatArray() {
+ float[] arr = new float[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = buf.getFloat();
+ return arr;
+ }
+
+ private double[] parseDoubleArray() {
+ double[] arr = new double[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = buf.getDouble();
+ return arr;
+ }
+
+ private String[] parseStringArray() {
+ String[] arr = new String[buf.getInt()];
+ for (int i = 0; i < arr.length; i++)
+ arr[i] = parseString();
+ return arr;
+ }
+
+ private String parseString() {
+ String str = null;
+ int length = parseLength();
+ if (length < 0)
+ return null;
+ try { str = new String(value, buf.position(), length, "UTF-8" ); }
+ catch (UnsupportedEncodingException e) { throw new Error(e); }
+ buf.position(buf.position() + length);
+ return str;
+ }
+
+ private int getByte() {
+ return (buf.get() + 0x0100) & 0xff;
+ }
+
+ public int parseLength() {
+ int length = getByte();
+ // check for invalid length format: the first, second or third
+ // most significant bits should be 0; if all are 1 the length is invalid.
+ if ((length & 0xe0) == 0xe0)
+ return -1;
+ if ((length & 0x80) != 0) {
+ length = ((length & 0x7f) << 8) | getByte();
+ if ((length & 0x4000) != 0)
+ length = ((length & 0x3fff) << 16) | (getByte()<<8) | getByte();
+ }
+ return length;
+ }
+
+ //##########################################################################
+ private static void formatValue(StringBuffer str, Object o) {
+ Class c = (o == null) ? null : o.getClass();
+ if (c == null) {
+ str.append("<null>");
+ } else if (c == String.class) {
+ str.append('"');
+ str.append(o);
+ str.append('"');
+ } else if (c == Character.class) {
+ str.append('\'');
+ str.append(o);
+ str.append('\'');
+ } else if (c == boolean[].class) {
+ str.append("new boolean[] {");
+ boolean[] arr = (boolean[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(arr[i]);
+ }
+ str.append('}');
+ } else if (c == char[].class) {
+ str.append("new short[] {");
+ short[] arr = (short[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(arr[i]);
+ }
+ str.append('}');
+ } else if (c == byte[].class) {
+ str.append("new byte[] {");
+ byte[] arr = (byte[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(arr[i]);
+ }
+ str.append('}');
+ } else if (c == short[].class) {
+ str.append("new short[] {");
+ short[] arr = (short[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(arr[i]);
+ }
+ str.append('}');
+ } else if (c == int[].class) {
+ str.append("new int[] {");
+ int[] arr = (int[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(arr[i]);
+ }
+ str.append('}');
+ } else if (c == long[].class) {
+ str.append("new long[] {");
+ long[] arr = (long[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(arr[i]);
+ }
+ str.append('}');
+ } else if (c == float[].class) {
+ str.append("new float[] {");
+ float[] arr = (float[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(arr[i]);
+ }
+ str.append('}');
+ } else if (c == double[].class) {
+ str.append("new double[] {");
+ double[] arr = (double[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(arr[i]);
+ }
+ str.append('}');
+ } else if (c == String[].class) {
+ str.append("new String[] {");
+ String[] arr = (String[])o;
+ for (int i = 0; i < arr.length; i++) {
+ if (i > 0) str.append(", ");
+ formatValue(str, arr[i]);
+ }
+ str.append('}');
+ } else if (o instanceof Type) {
+ str.append("typeof(");
+ str.append(o);
+ str.append(")");
+ } else
+ str.append(o);
+ }
+
+ //##########################################################################
+
+ /** Represents named arguments (assigned outside of the constructor)
+ * of a custom attribute
+ */
+ public static class NamedArgument {
+
+ /** Designates if the named argument corresponds to a field or property.
+ * Possible values:
+ * Signature.X_ELEMENT_KIND_FIELD = 0x53
+ * Signature.X_ELEMENT_KIND_PROPERTY = 0x54
+ */
+ public final int designator;
+
+ /** The name of the field/property. */
+ public final String name;
+
+ /** Type of the field/property. */
+ public final Type type;
+
+ /** The value for the field/property. */
+ public final Object value;
+
+ /** An empty array NamedArgument. */
+ public static final NamedArgument[] EMPTY = new NamedArgument[0];
+
+ public NamedArgument(int designator, String name,Type type,Object value)
+ {
+ this.designator = designator;
+ this.name = name;
+ this.type = type;
+ this.value = value;
+ }
+
+ /** @return <b>true</b> if the named argument specifies a field;
+ * <b>false<b> otherwise.
+ */
+ public boolean isField() {
+ return designator == Signature.X_ELEMENT_KIND_FIELD;
+ }
+
+ /** @return <b>true</b> if the named argument specifies a property;
+ * <b>false<b> otherwise.
+ */
+ public boolean isProperty() {
+ return designator == Signature.X_ELEMENT_KIND_PROPERTY;
+ }
+
+ /** @return a string representation of the named argument. */
+ public String toString() {
+ StringBuffer str = new StringBuffer(name);
+ str.append(" = ");
+ if (type.IsEnum())
+ str.append('(').append(type.FullName).append(')');
+ formatValue(str, value);
+ return str.toString();
+ }
+ }
+
+ //##########################################################################
+
+ protected static final class BoxedArgument {
+ public final Type type;
+ public final Object value;
+ public BoxedArgument(Type type, Object value) {
+ this.type = type; this.value = value;
+ }
+ public String toString() {
+ return "(" + type.FullName + ")" + value;
+ }
+ }
+
+ //##########################################################################
+
+} // class Attribute
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/BindingFlags.java b/src/msil/ch/epfl/lamp/compiler/msil/BindingFlags.java
new file mode 100644
index 0000000000..c9a024409c
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/BindingFlags.java
@@ -0,0 +1,170 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Specifies flags that control binding and the way in which
+ * the search for members and types is conducted by reflection.
+ *
+ * Note: You must specify Instance or Static along with Public or NonPublic
+ * or no members will be returned.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class BindingFlags {
+
+ //##########################################################################
+
+ // disallows extending the class;
+ private BindingFlags() {}
+
+ /**
+ * Specifies no binding flag.
+ */
+ public static final int Default = 0x0000;
+
+ /**
+ * Specifies that the case of the member name should not be considered
+ * when binding.
+ */
+ public static final int IgnoreCase = 0x0001;
+
+ /**
+ * Specifies that only members declared at the level of the supplied type's
+ * hierarchy should be considered. Inherited members are not considered.
+ */
+ public static final int DeclaredOnly = 0x0002;
+
+ /**
+ * Specifies that instance members are to be included in the search.
+ */
+ public static final int Instance = 0x0004;
+
+ /**
+ * Specifies that static members are to be included in the search.
+ */
+ public static final int Static = 0x0008;
+
+ /**
+ * Specifies that public members are to be included in the search.
+ */
+ public static final int Public = 0x0010;
+
+ /**
+ * Specifies that non-public members are to be included in the search.
+ */
+ public static final int NonPublic = 0x0020;
+
+ /**
+ * Specifies that static members up the hierarchy should be returned.
+ * Static members include fields, methods, events, and properties.
+ * Nested types are not returned.
+ */
+ public static final int FlattenHierarchy = 0x0040;
+
+ /**
+ * Specifies that a method is to be invoked. This may not be a constructor
+ * or a type initializer.
+ */
+ public static final int InvokeMethod = 0x0100;
+
+ /**
+ * Specifies that Reflection should create an instance of
+ * the specified type. Calls the constructor that matches
+ * the given arguments. The supplied member name is ignored.
+ * If the type of lookup is not specified, (Instance | Public)
+ * will apply. It is not possible to call a type initializer.
+ */
+ public static final int CreateInstance = 0x0200;
+
+ /**
+ * Specifies that the value of the specified field should be returned.
+ */
+ public static final int GetField = 0x0400;
+
+ /**
+ * Specifies that the value of the specified field should be set.
+ */
+ public static final int SetField = 0x0800;
+
+ /**
+ * Specifies that the value of the specified property should be returned.
+ */
+ public static final int GetProperty = 0x1000;
+
+ /**
+ * Specifies that the value of the specified property should be set.
+ * For COM properties, specifying this binding flag is equivalent to
+ * specifying PutDispProperty and PutRefDispProperty.
+ */
+ public static final int SetProperty = 0x2000;
+
+ /**
+ * Specifies that the PROPPUT member on a COM object should be invoked.
+ * PROPPUT specifies a property-setting function that uses a value.
+ * Use PutDispProperty if a property has both PROPPUT and PROPPUTREF
+ * and you need to distinguish which one is called.
+ */
+ public static final int PutDispProperty = 0x4000;
+
+
+ /**
+ * Specifies that the PROPPUTREF member on a COM object should be invoked.
+ * PROPPUTREF specifies a property-setting function that uses a reference
+ * instead of a value. Use PutRefDispProperty if a property has both
+ * PROPPUT and PROPPUTREF and you need to distinguish which one is called.
+ */
+ public static final int PutRefDispProperty = 0x8000;
+
+ /**
+ * Specifies that types of the supplied arguments must exactly match
+ * the types of the corresponding formal parameters. Reflection
+ * throws an exception if the caller supplies a non-null Binder object,
+ * since that implies that the caller is supplying BindToXXX
+ * implementations that will pick the appropriate method.
+ * Reflection models the accessibility rules of the common type system.
+ * For example, if the caller is in the same assembly, the caller
+ * does not need special permissions for internal members. Otherwise,
+ * the caller needs ReflectionPermission. This is consistent with
+ * lookup of members that are protected, private, and so on.
+ * The general principle is that ChangeType should perform only
+ * widening coercions, which never lose data. An example of a
+ * widening coercion is coercing a value that is a 32-bit signed integer
+ * to a value that is a 64-bit signed integer. This is distinguished
+ * from a narrowing coercion, which may lose data. An example of
+ * a narrowing coercion is coercing a 64-bit signed integer to
+ * a 32-bit signed integer.
+ * The default binder ignores this flag, while custom binders can
+ * implement the semantics of this flag.
+ */
+ public static final int ExactBinding = 0x10000;
+
+ /**
+ * Used in COM interop to specify that the return value of the member
+ * can be ignored.
+ */
+ public static final int IgnoreReturn = 0x100000 ;
+
+ /**
+ * Returns the set of members whose parameter count matches the number
+ * of supplied arguments. This binding flag is used for methods with
+ * parameters that have default values and methods with variable arguments
+ * (varargs). This flag should only be used with Type.InvokeMember.
+ * Parameters with default values are used only in calls where trailing
+ * arguments are omitted. They must be the last arguments.
+ */
+ public static final int OptionalParamBinding = 0x40000;
+
+ /**
+ * Not implemented.
+ */
+ public static final int SuppressChangeType = 0x20000;
+
+ //##########################################################################
+
+} // class BindingFlags
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/CallingConventions.java b/src/msil/ch/epfl/lamp/compiler/msil/CallingConventions.java
new file mode 100644
index 0000000000..925c5b8693
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/CallingConventions.java
@@ -0,0 +1,76 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+
+/**
+ * Calling conventions
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class CallingConventions {
+
+ //########################################################################
+
+ /**
+ * Specifies the default calling convention as determined by the
+ * common language runtime.
+ */
+ public static final short Standard = (short) 0x0001;
+
+ /**
+ * Specifies the calling convention for methods with variable arguments.
+ */
+ public static final short VarArgs = (short) 0x0002;
+
+ /**
+ * Specifies that either the Standard or the VarArgs calling
+ * convention may be used.
+ */
+ public static final short Any = Standard | VarArgs;
+
+ /**
+ * Specifies an instance or virtual method (not a static method).
+ * At run-time, the called method is passed a pointer to the target
+ * object as its first argument (the this pointer). The signature
+ * stored in metadata does not include the type of this first argument,
+ * because the method is known and its owner class can be discovered
+ * from metadata.
+ */
+ public static final short HasThis = (short) 0x0020;
+
+ /**
+ * Specifies that the signature is a function-pointer signature,
+ * representing a call to an instance or virtual method (not a static
+ * method). If ExplicitThis is set, HasThis must also be set. The first
+ * argument passed to the called method is still a this pointer, but the
+ * type of the first argument is now unknown. Therefore, a token that
+ * describes the type (or class) of the this pointer is explicitly stored
+ * into its metadata signature.
+ */
+ public static final short ExplicitThis = (short) 0x0040;
+
+ //########################################################################
+
+ private CallingConventions() {}
+
+ public static String toString(int callConv) {
+ StringBuffer s = new StringBuffer();
+
+ if ((callConv & HasThis) != 0) {
+ s.append("instance");
+ if ((callConv & ExplicitThis) != 0)
+ s.append(" explicit");
+ }
+
+ return s.toString();
+ }
+
+ //##########################################################################
+
+} // class CallingConventions
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java
new file mode 100644
index 0000000000..3dea39c2cf
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/ConstructorInfo.java
@@ -0,0 +1,55 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Discovers the attributes of a class constructor and provides
+ * access to constructor metadata.
+ * ConstructorInfo is used to discover the attributes of a constructor
+ * as well as to invoke a constructor. Objects are created by invoking
+ * either the GetConstructors or GetConstructor method of a Type object.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public class ConstructorInfo extends MethodBase {
+ //##########################################################################
+
+ public final int MemberType() { return MemberTypes.Constructor; }
+
+ public final boolean IsConstructor() { return true; }
+
+ protected static final String CTOR = ".ctor";
+ protected static final String CCTOR = ".cctor";
+ protected static final ConstructorInfo[] EMPTY_ARRAY =
+ new ConstructorInfo[0];
+
+ protected static String getName(int attrs) {
+ return (attrs & MethodAttributes.Static) == 0 ? CTOR : CCTOR;
+ }
+
+ /** Protected constructor */
+ protected ConstructorInfo(Type declType, int attrs, Type[] paramTypes) {
+ super(getName(attrs), declType, attrs, paramTypes);
+ assert declType != null : "Owner can't be 'null' for a constructor!";
+ }
+
+ protected ConstructorInfo(Type declType, int attrs, ParameterInfo[] params)
+ {
+ super(getName(attrs), declType, attrs, params);
+ assert declType != null : "Owner can't be 'null' for a constructor!";
+ }
+
+
+ public String toString() {
+ return MethodAttributes.toString(Attributes) + " " + Type.VOID() +
+ " " + DeclaringType.FullName + "::" + Name + params2String();
+ }
+
+ //##########################################################################
+
+} // class ConstructorInfo
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/CustomAttributeProvider.java b/src/msil/ch/epfl/lamp/compiler/msil/CustomAttributeProvider.java
new file mode 100644
index 0000000000..32a50fdf9b
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/CustomAttributeProvider.java
@@ -0,0 +1,83 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Iterator;
+
+/**
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class CustomAttributeProvider implements ICustomAttributeProvider {
+
+ //##########################################################################
+
+ protected List/*<Attribute>*/ custAttrs;
+ private static final Object[] EMPTY = new Object[0];
+
+ //TODO: take inherit into account
+ public Object[] GetCustomAttributes(boolean inherit) {
+ initAttributes(null);
+ return custAttrs.size() == 0 ? EMPTY
+ : custAttrs.toArray(new Attribute[custAttrs.size()]);
+ }
+
+ //TODO: take inherit into account
+ public Object[] GetCustomAttributes(Type attributeType, boolean inherit) {
+ initAttributes(attributeType);
+ List tAttrs = null;
+ if (constrType == attributeType)
+ tAttrs = custAttrs;
+ else {
+ tAttrs = new LinkedList();
+ for (Iterator attrs = custAttrs.iterator(); attrs.hasNext(); ) {
+ Attribute a = (Attribute) attrs.next();
+ if (a.GetType() == attributeType) tAttrs.add(a);
+ }
+ }
+ return tAttrs.size() == 0 ? EMPTY
+ : tAttrs.toArray(new Attribute[tAttrs.size()]);
+ }
+
+ //TODO: take inherit into account
+ public boolean IsDefined(Type attributeType, boolean inherit) {
+ initAttributes(attributeType);
+ if (constrType == attributeType)
+ return custAttrs.size() > 0;
+ Iterator attrs = custAttrs.iterator();
+ while (attrs.hasNext()) {
+ if (((Attribute)attrs.next()).GetType() == attributeType)
+ return true;
+ }
+ return false;
+// return inherit && (DeclaringClass.BaseType != null)
+// && DeclaringClass.BaseType.IsDefined(inherit);
+ }
+
+ protected void addCustomAttribute(ConstructorInfo constr, byte[] value) {
+ Attribute attr = new Attribute(constr, value);
+ assert constrType == null || constrType == attr.GetType();
+ if (custAttrs == null)
+ custAttrs = new LinkedList();
+ custAttrs.add(attr);
+ }
+
+ private void initAttributes(Type atype) {
+ if (custAttrs != null
+ && (constrType == null || constrType == atype))
+ return;
+ custAttrs = new LinkedList();
+ constrType = atype;
+ loadCustomAttributes(atype);
+ }
+
+ protected void loadCustomAttributes(Type atype) {}
+
+ private Type constrType;
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/EventAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/EventAttributes.java
new file mode 100644
index 0000000000..f931f7bad6
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/EventAttributes.java
@@ -0,0 +1,33 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Specifies flags that describe the attributes of a an event.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class EventAttributes {
+
+ //##########################################################################
+
+ /** Specifies that the event has no attributes. */
+ public static final short None = 0x000;
+
+ /** Specifies a reserved flag for CLR use only. */
+ public static final short ReservedMask = 0x0400;
+
+ /** Specifies that the event is special in a way described by the name. */
+ public static final short SpecialName = 0x0200;
+
+ /** Specifies the the CLR should check name encoding. */
+ public static final short RTSpecialName = 0x0400;
+
+ //##########################################################################
+
+} // class EventAttributes
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/EventInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/EventInfo.java
new file mode 100644
index 0000000000..e2bea10f7f
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/EventInfo.java
@@ -0,0 +1,59 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+
+/**
+ * Discovers the attributes of an event
+ * and provides access to event metadata.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public class EventInfo extends MemberInfo {
+
+ //##########################################################################
+
+ public final int MemberType() { return MemberTypes.Event; }
+
+ /** Attributes associated with the event. */
+ public final short Attributes;
+
+ /** The Type object for the underlying event-handler delegate
+ * associated with this event.
+ */
+ public final Type EventHandlerType;
+
+ public MethodInfo GetAddMethod() { return addMethod; }
+
+ public MethodInfo GetRemoveMethod() { return removeMethod; }
+
+ public String toString() {
+ return "" + EventHandlerType + " " + Name;
+ }
+
+ //##########################################################################
+
+ protected static final EventInfo[] EMPTY_ARRAY = new EventInfo[0];
+
+ protected MethodInfo addMethod;
+
+ protected MethodInfo removeMethod;
+
+ protected EventInfo(String name, Type declType, short attr,
+ Type handlerType, MethodInfo add, MethodInfo remove)
+ {
+ super(name, declType);
+ Attributes = attr;
+ EventHandlerType = handlerType;
+ this.addMethod = add;
+ this.removeMethod = remove;
+ }
+
+ //##########################################################################
+
+} // class EventInfo
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/FieldAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/FieldAttributes.java
new file mode 100644
index 0000000000..5e6cc84f1e
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/FieldAttributes.java
@@ -0,0 +1,120 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Specifies flags that describe the attributes of a field.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class FieldAttributes {
+
+ //##########################################################################
+
+ /** Specifies the access level of a given field. */
+ public static final short FieldAccessMask = 0x0007;
+
+ /** Member not refereneceable. */
+ public static final short CompilerControlled = 0x0000;
+
+ /** Field is accessible only by the parent type. */
+ public static final short Private = 0x0001;
+
+ /** Field is accessible only by subtypes in this assembly. */
+ public static final short FamANDAssem = 0x0002;
+
+ /** Field is accessible throughout the assembly. */
+ public static final short Assembly = 0x0003;
+
+ /** Field is accessible only by type and subtypes. */
+ public static final short Family = 0x0004;
+
+ /** Field is accessible by subtypes anywhere,
+ * as well as throughout this assembly. */
+ public static final short FamORAssem = 0x0005;
+
+ /** Specifies that the field is accessible by any member
+ * for whom this scope is visible. */
+ public static final short Public = 0x0006;
+
+ //##########################################################################
+ //
+
+ /** Field represents the defined type, or else it is per-instance. */
+ public static final short Static = 0x0010;
+
+ /** Field is initialized only and cannot be written after initialization. */
+ public static final short InitOnly = 0x0020;
+
+ /** Value is compile-time constant. */
+ public static final short Literal = 0x0040;
+
+ /** Field does not have to be serialized when the type is remoted. */
+ public static final short NotSerialized = 0x0080;
+
+ /** Field is special. */
+ public static final short SpecialName = 0x0200;
+
+ //##########################################################################
+ // Interop attributes
+
+ /** Implementation is forwarded through PInvoke */
+ public static final short PinvokeImpl = 0x2000;
+
+
+ //##########################################################################
+ // Additional flags
+
+ /** CLI provides 'special' behavior depending upon the name of the field */
+ public static final short RTSpecialName = 0x0400;
+
+ /** Field has marshalling information. */
+ public static final short HasFieldMarshal = 0x1000;
+
+ /** Field has a default value. */
+ public static final short HasDefault = (short)0x8000;
+
+ /** Field has a Relative Virtual Address (RVA). The RVA is the location
+ * of the method body in the current image, as an address relative
+ * to the start of the image file in which it is located. */
+ public static final short HasFieldRVA = 0x0100;
+
+ //##########################################################################
+ //
+
+ public static String toString(short attrs) {
+ StringBuffer str = new StringBuffer();
+ switch (attrs & FieldAccessMask) {
+ case CompilerControlled: str.append("compilercontrolled"); break;
+ case Private: str.append("private"); break;
+ case FamANDAssem: str.append("famandassem"); break;
+ case Assembly: str.append("assembly"); break;
+ case Family: str.append("family"); break;
+ case FamORAssem: str.append("famorassem"); break;
+ case Public: str.append("public"); break;
+ }
+ if ((attrs & Static) != 0) str.append(" static");
+ if ((attrs & InitOnly) != 0) str.append(" initonly");
+ if ((attrs & Literal) != 0) str.append(" literal");
+ if ((attrs & NotSerialized) != 0) str.append(" notserialized");
+ if ((attrs & SpecialName) != 0) str.append(" specialname");
+ if ((attrs & PinvokeImpl) != 0) str.append("");
+ if ((attrs & RTSpecialName) != 0) str.append(" rtspecialname");
+ if ((attrs & HasFieldMarshal) != 0) str.append(" marshal(<native type>)");
+ //if ((attrs & HasDefault) != 0) str.append(" default(???)");
+ return str.toString();
+ }
+
+ //##########################################################################
+
+ // makes the class uninstantiable
+ private FieldAttributes() {}
+
+ //##########################################################################
+
+} // class FieldAttributes
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java
new file mode 100644
index 0000000000..bd08e4a3e1
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/FieldInfo.java
@@ -0,0 +1,113 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Discovers the attributes of a field and provides access to field metadata.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public class FieldInfo extends MemberInfo {
+
+ //##########################################################################
+ // public interface
+
+ public final int MemberType() { return MemberTypes.Field; }
+
+ /** Attributes associated with this field. */
+ public final short Attributes;
+
+ /** Type of the field represented by this FieldInfo object. */
+ public final Type FieldType;
+
+ protected final Object value;
+
+ public final boolean IsStatic() {
+ return (Attributes & FieldAttributes.Static) != 0;
+ }
+
+ public final boolean IsInitOnly() {
+ return (Attributes & FieldAttributes.InitOnly) != 0;
+ }
+
+ public final boolean IsLiteral() {
+ return (Attributes & FieldAttributes.Literal) != 0;
+
+ }
+
+ public final boolean IsPublic() {
+ return (Attributes & FieldAttributes.FieldAccessMask)
+ == FieldAttributes.Public;
+ }
+
+ public final boolean IsPrivate() {
+ return (Attributes & FieldAttributes.FieldAccessMask)
+ == FieldAttributes.Private;
+ }
+
+ public final boolean IsFamily() {
+ return (Attributes & FieldAttributes.FieldAccessMask)
+ == FieldAttributes.Family;
+ }
+
+ public final boolean IsAssembly() {
+ return (Attributes & FieldAttributes.FieldAccessMask)
+ == FieldAttributes.Assembly;
+ }
+
+ public final boolean IsFamilyOrAssembly() {
+ return (Attributes & FieldAttributes.FieldAccessMask)
+ == FieldAttributes.FamORAssem;
+ }
+
+ public final boolean IsFamilyAndAssembly() {
+ return (Attributes & FieldAttributes.FieldAccessMask)
+ == FieldAttributes.FamANDAssem;
+ }
+ public final boolean IsSpecialName() {
+ return (Attributes & FieldAttributes.SpecialName) != 0;
+ }
+
+ public final boolean IsPinvokeImpl() {
+ return (Attributes & FieldAttributes.PinvokeImpl) != 0;
+ }
+
+ public final boolean IsNotSerialized() {
+ return (Attributes & FieldAttributes.NotSerialized) != 0;
+ }
+
+ public String toString() {
+ return FieldAttributes.toString(Attributes) + " " +
+ FieldType + " " + DeclaringType.FullName + "::" + Name;
+ }
+
+ //##########################################################################
+
+ protected static final FieldInfo[] EMPTY_ARRAY = new FieldInfo[0];
+
+ /** Initializes a new instance of the FieldInfo class. */
+ protected FieldInfo(String name, Type declType, int attrs, Type fieldType) {
+ this(name, declType, attrs, fieldType, null);
+ }
+
+ protected FieldInfo(String name, Type declType,
+ int attrs, Type fieldType, Object value)
+ {
+ super(name, declType);
+ FieldType = fieldType;
+ Attributes = (short) attrs;
+ this.value = value;
+ }
+
+ /**
+ */
+ public Object getValue() { return value; }
+
+ //##########################################################################
+
+} // class FieldInfo
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ICustomAttributeProvider.java b/src/msil/ch/epfl/lamp/compiler/msil/ICustomAttributeProvider.java
new file mode 100644
index 0000000000..4eafc37ef3
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/ICustomAttributeProvider.java
@@ -0,0 +1,58 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Provides custom attributes for reflection objects that support them.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public interface ICustomAttributeProvider {
+
+ //##########################################################################
+ // interface method definitions
+
+ /** Returns an array of all of the custom attributes
+ * defined on this member, excluding named attributes,
+ * or an empty array if there are no custom attributes.
+ *
+ * @param inherit - When true, look up the hierarchy chain
+ * for the inherited custom attribute.
+ * @return - An array of Objects representing custom attributes,
+ * or an empty array.
+ */
+ public Object[] GetCustomAttributes(boolean inherit);
+
+
+ /** Returns an array of custom attributes defined on this member,
+ * identified by type, or an empty array
+ * if there are no custom attributes of that type.
+ *
+ * @param attributeType - The type of the custom attributes.
+ * @param inherit - When true, look up the hierarchy chain
+ * for the inherited custom attribute.
+ * @return - An array of Objects representing custom attributes,
+ * or an empty array.
+ */
+ public Object[] GetCustomAttributes(Type attributeType, boolean inherit);
+
+
+ /** Indicates whether one or more instance of attributeType
+ * is defined on this member
+ *
+ * @param attributeType - The type of the custom attributes
+ * @param inherit - When true, look up the hierarchy chain
+ * for the inherited custom attribute.
+ * @return - true if the attributeType is defined on this member;
+ * false otherwise.
+ */
+ public boolean IsDefined(Type attributeType, boolean inherit);
+
+ //##########################################################################
+
+} // interface ICustomAttributeProvider
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MemberInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/MemberInfo.java
new file mode 100644
index 0000000000..14aac59e84
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/MemberInfo.java
@@ -0,0 +1,48 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * The root class of the Reflection hierarchy.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class MemberInfo extends CustomAttributeProvider {
+
+ //##########################################################################
+
+ /** The name of this member. */
+ public final String Name;
+
+ /**
+ * The class that declares this member.
+ * Note: if the MemberInfo object is a global member,
+ * (that is, it was obtained from Module.GetMethods,
+ * which returns global methods on a module), then DeclaringType
+ * will be a null reference.
+ */
+ public final Type DeclaringType;
+
+ /** An enumerated value from the MemberTypes class,
+ * specifying a constructor, event, field, method,
+ * property, type information, all, or custom. */
+ public abstract int MemberType();
+
+ //##########################################################################
+ // protected members
+
+ protected static final MemberInfo[] EMPTY_ARRAY = new MemberInfo[0];
+
+ protected MemberInfo(String name, Type declType) {
+ Name = name;
+ DeclaringType = declType;
+ }
+
+ //########################################################################
+
+} // class MemberInfo
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MemberTypes.java b/src/msil/ch/epfl/lamp/compiler/msil/MemberTypes.java
new file mode 100644
index 0000000000..4536dc997f
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/MemberTypes.java
@@ -0,0 +1,82 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Marks each type of member that is defined as a derived class of MemberInfo.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class MemberTypes {
+
+ //##########################################################################
+
+ /** Specifies that the member is a constructor,
+ * representing a ConstructorInfo member. */
+ public static final int Constructor = 0x01;
+
+
+ /** Specifies that the member is an event,
+ * representing an EventInfo member. */
+ public static final int Event = 0x02;
+
+
+ /** Specifies that the member is a field,
+ * representing a FieldInfo member. */
+ public static final int Field = 0x04;
+
+
+ /** Specifies that the member is a method,
+ * representing a MethodInfo member. */
+ public static final int Method = 0x08;
+
+
+ /** Specifies that the member is a property,
+ * representing a PropertyInfo member.
+ */
+ public static final int Property = 0x10;
+
+ /** Specifies that the member is a type,
+ * representing a TypeInfo member. */
+ public static final int TypeInfo = 0x20;
+
+
+ /** Specifies that the member is a custom member type. */
+ public static final int Custom = 0x40;
+
+
+ /** Specifies that the member is a nested type,
+ * extending MemberInfo. */
+ public static final int NestedType = 0x80;
+
+
+ /** Specifies all member types. */
+ public static final int All =
+ Constructor | Event | Field | Method | Property | TypeInfo | NestedType;
+
+
+ public static String toString(int memberType) {
+ if ((memberType & Constructor) != 0) return "Constructor";
+ if ((memberType & Event) != 0) return "Event";
+ if ((memberType & Field) != 0) return "Field";
+ if ((memberType & Method) != 0) return "Method";
+ if ((memberType & Property) != 0) return "Property";
+ if ((memberType & TypeInfo) != 0) return "TypeInfo";
+ if ((memberType & Custom) != 0) return "Custom";
+ if ((memberType & NestedType) != 0) return "NestedType";
+ return "Unknown MemberType: " + memberType;
+ }
+
+ //##########################################################################
+
+ // makes the class uninstantiable
+ private MemberTypes() {}
+
+ //##########################################################################
+
+} // class MemberTypes
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodAttributes.java
new file mode 100644
index 0000000000..3e8b658d49
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/MethodAttributes.java
@@ -0,0 +1,159 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/** Specifies flags for method attributes.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class MethodAttributes {
+
+ //##########################################################################
+ // Method access attributes
+
+ /** Bitmask used to retrieve accessibility information. */
+ public static final short MemberAccessMask = 0x0007;
+
+ ///** Member not referenceable*/
+ //public static final short CompilerConstrolled = 0x0000;
+
+ /** Indicates that the member cannot be referenced. */
+ public static final short PrivateScope = 0x0000;
+
+ /** Method is accessible only by the current class. */
+ public static final short Private = 0x0001;
+
+ /** Method is accessible to members of this type
+ * and its derived types that are in this assembly only. */
+ public static final short FamANDAssem = 0x0002;
+
+ /** Method is accessible to any class of this assembly. */
+ public static final short Assembly = 0x0003;
+
+ /** Method is accessible only to members of this class
+ * and its derived classes. */
+ public static final short Family = 0x0004;
+
+ /** Method is accessible to derived classes anywhere,
+ * as well as to any class in the assembly. */
+ public static final short FamORAssem = 0x0005;
+
+ /** Method is accessible to any object for which this object is in scope. */
+ public static final short Public = 0x0006;
+
+
+ //##########################################################################
+ // Flags
+
+ /** Method is defined on the type; otherwise, it is defined per instance. */
+ public static final short Static = 0x0010;
+
+ /** Method cannot be overridden. */
+ public static final short Final = 0x0020;
+
+ /** Method is virtual. */
+ public static final short Virtual = 0x0040;
+
+ /** Method hides by name and signature; otherwise, by name only. */
+ public static final short HideBySig = 0x0080;
+
+
+ //##########################################################################
+ // vtable attributes
+
+ /** Bitmask used to retrieve vtable attributes. */
+ public static final short VtableLayoutMask = 0x0100;
+
+ /** Method reuses existing slot in the vtable. */
+ public static final short ReuseSlot = 0x0000;
+
+
+ /** Method always gets a new slot in the vtable. */
+ public static final short NewSlot = 0x0100;
+
+
+ //##########################################################################
+ // Flags
+
+ /** Method does not provide implementation. */
+ public static final short Abstract = 0x0400;
+
+ /** Method is special. */
+ public static final short SpecialName = 0x0800;
+
+
+ //##########################################################################
+ // Interop attributes
+
+ /** Method implementation is forwarded through PInvoke. */
+ public static final short PInvokeImpl = 0x2000;
+
+ /** Reserved: shall be zero for conforming implementations.
+ * Managed method is exported by thunk to unmanaged code. */
+ public static final short UnmanagedExport = 0x0008;
+
+
+ //##########################################################################
+ // Additional flags
+
+ /** CLI provides special behavior, depending on the name of the method. */
+ public static final short RTSpecialName = 0x1000;
+
+ /** Method has security associated with it.
+ * Reserved flag for runtime use only.
+ */
+ public static final short HasSecurity = 0x00000040;
+
+ /**
+ * Indicates that the method calls another method containing security code.
+ * Reserved flag for runtime use only.
+ */
+ public static final short RequireSecObject = 0x00004000;
+
+ /** Indicates a reserved flag for runtime use only. */
+ public static final short ReservedMask = 0x0000;
+
+
+ //##########################################################################
+
+ public static String toString(short attrs) {
+ StringBuffer str = new StringBuffer(accessFlagsToString(attrs));
+ if ((attrs & Static) != 0) str.append(" static");
+ if ((attrs & Final) != 0) str.append(" final");
+ if ((attrs & Virtual) != 0) str.append(" virtual");
+ if ((attrs & Abstract) != 0) str.append(" abstract");
+ if ((attrs & HideBySig) != 0) str.append(" hidebysig");
+ if ((attrs & NewSlot) != 0) str.append(" newslot");
+ if ((attrs & SpecialName) != 0) str.append(" specialname");
+ if ((attrs & PInvokeImpl) != 0) str.append(" pinvokeimpl(?!?)");
+ if ((attrs & RTSpecialName) != 0) str.append(" rtspecialname");
+ return str.toString();
+
+ }
+
+ public static String accessFlagsToString(short attrs) {
+ switch (attrs & MemberAccessMask) {
+ case PrivateScope: return "compilercontrolled";
+ case Private: return "private";
+ case FamANDAssem: return "famandassem";
+ case Assembly: return "assembly";
+ case Family: return "family";
+ case FamORAssem: return "famorassem";
+ case Public: return "public";
+ default: return "xxx";
+ }
+ }
+
+ //##########################################################################
+
+ // makes the class uninstantiable
+ private MethodAttributes() {}
+
+ //##########################################################################
+
+} // class Method Attributes
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java
new file mode 100644
index 0000000000..699edab6e3
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/MethodBase.java
@@ -0,0 +1,145 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * The common superclass of MemberInfo and ConstructorInfo
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class MethodBase extends MemberInfo {
+
+ //##########################################################################
+ // public interface
+
+ /** The attributes associated with this method/constructor. */
+ public final short Attributes;
+
+ /***/
+ public final short CallingConvention;
+
+ public abstract boolean IsConstructor();
+
+ public final boolean IsAbstract() {
+ return (Attributes & MethodAttributes.Abstract) != 0;
+ }
+
+ public final boolean IsFinal() {
+ return (Attributes& MethodAttributes.Final) != 0;
+ }
+
+ public final boolean IsVirtual() {
+ return (Attributes& MethodAttributes.Virtual) != 0;
+ }
+
+ public final boolean IsStatic() {
+ return (Attributes & MethodAttributes.Static) != 0;
+ }
+
+ public final boolean IsHideBySig() {
+ return (Attributes & MethodAttributes.HideBySig) != 0;
+ }
+
+ public final boolean IsSpecialName() {
+ return (Attributes & MethodAttributes.SpecialName) != 0;
+ }
+
+
+ public final boolean IsPublic() {
+ return (Attributes & MethodAttributes.MemberAccessMask)
+ == MethodAttributes.Public;
+ }
+
+ public final boolean IsPrivate() {
+ return (Attributes & MethodAttributes.MemberAccessMask)
+ == MethodAttributes.Private;
+ }
+
+ public final boolean IsFamily() {
+ return (Attributes & MethodAttributes.MemberAccessMask)
+ == MethodAttributes.Family;
+ }
+
+ public final boolean IsAssembly() {
+ return (Attributes & MethodAttributes.MemberAccessMask)
+ == MethodAttributes.Assembly;
+ }
+
+ public final boolean IsFamilyOrAssembly() {
+ return (Attributes & MethodAttributes.MemberAccessMask)
+ == MethodAttributes.FamORAssem;
+ }
+
+ public final boolean IsFamilyAndAssembly() {
+ return (Attributes & MethodAttributes.MemberAccessMask)
+ == MethodAttributes.FamANDAssem;
+ }
+
+
+ /** Returns the parameters of the method/constructor. */
+ public ParameterInfo[] GetParameters() {
+ return (ParameterInfo[]) params.clone();
+ }
+
+ public int GetMethodImplementationFlags() { return implAttributes; }
+
+ //##########################################################################
+
+ /** Method parameters. */
+ protected ParameterInfo[] params;
+
+ protected short implAttributes;
+
+ protected MethodBase(String name, Type declType, int attrs, Type[] paramTypes)
+ {
+ this(name, declType, attrs);
+ assert paramTypes != null;
+ params = new ParameterInfo[paramTypes.length];
+ for (int i = 0; i < params.length; i++)
+ params[i] = new ParameterInfo(null, paramTypes[i], 0, i);
+ }
+
+ protected MethodBase(String name, Type declType, int attrs,
+ ParameterInfo[] params)
+ {
+ this(name, declType, attrs);
+ this.params = params;
+ }
+
+ /**
+ */
+ private MethodBase(String name, Type declType, int attrs) {
+ super(name, declType);
+
+ Attributes = (short) attrs;
+
+ if (IsConstructor()) {
+ attrs |= MethodAttributes.SpecialName;
+ attrs |= MethodAttributes.RTSpecialName;
+ }
+
+ CallingConvention = (short) (CallingConventions.Standard
+ | (IsStatic() ? (short)0 : CallingConventions.HasThis));
+ }
+
+ //##########################################################################
+ // internal methods
+
+ protected String params2String() {
+ StringBuffer s = new StringBuffer("(");
+ for (int i = 0; i < params.length; i++) {
+ if (i > 0) s.append(", ");
+ s.append(params[i].ParameterType);
+ }
+ s.append(")");
+ return s.toString();
+ }
+
+ //##########################################################################
+
+} // class MethodBase
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodImplAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodImplAttributes.java
new file mode 100644
index 0000000000..1ad3f2a133
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/MethodImplAttributes.java
@@ -0,0 +1,117 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Method implementation attributes
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class MethodImplAttributes {
+
+ //##########################################################################
+
+ /**
+ * Specifies flags about code type. 3
+ */
+ public static final short CodeTypeMask = (short) 0x0003;
+
+ /**
+ * Specifies that the method implementation is in MSIL. 0
+ */
+ public static final short IL = (short) 0x0000;
+
+ /**
+ * Specifies that the method implementation is native. 1
+ */
+ public static final short Native = (short) 0x0001;
+
+ /**
+ * This member supports the .NET Framework infrastructure and
+ * is not intended to be used directly from your code. 2
+ */
+ public static final short OPTIL = (short) 0x0002;
+
+ /**
+ * Specifies that the method implementation is provided by the runtime. 3
+ */
+ public static final short Runtime = (short) 0x0003;
+
+
+
+ /**
+ * Specifies whether the code is managed or unmanaged. 4
+ */
+ public static final short ManagedMask = (short) 0x0004;
+
+ /**
+ * Specifies that the method implementation is managed, otherwise unmanaged.
+ */
+ public static final short Managed = (short) 0x0000;
+
+ /**
+ * Specifies that the method implementation is unmanaged, otherwise managed.
+ */
+ public static final short Unmanaged = (short) 0x0004;
+
+
+
+ /**
+ * Specifies that the method cannot be inlined. 8
+ */
+ public static final short NoInlining = (short) 0x0008;
+
+ /**
+ * Specifies that the method is not defined. 16
+ */
+ public static final short ForwardRef = (short) 0x0010;
+
+ /**
+ * Specifies that the method is single-threaded through the body.
+ * You can also use the C# lock statement or the Visual Basic
+ * Lock function for this purpose. 32
+ */
+ public static final short Synchronized = (short) 0x0020;
+
+ /**
+ * Specifies that the method signature is exported exactly as declared. 128
+ */
+ public static final short PreserveSig = (short) 0x0080;
+
+ /**
+ * Specifies an internal call. 4096
+ */
+ public static final short InternalCall = (short) 0x1000;
+
+ /**
+ * Specifies a range check value. 65535
+ */
+ public static final short MaxMethodImplVal = (short) 0xffff;
+
+ //##########################################################################
+
+ public static String toString(int implAttr) {
+ StringBuffer s = new StringBuffer();
+ switch (implAttr & CodeTypeMask) {
+ case IL: s.append("cil"); break;
+ case Native: s.append("native"); break;
+ case Runtime: s.append("runtime"); break;
+ }
+ switch (implAttr & ManagedMask) {
+ case Managed: s.append(" managed"); break;
+ case Unmanaged: s.append(" unmanaged"); break;
+ }
+ if ((implAttr & NoInlining) != 0) s.append(" noinlining");
+ if ((implAttr & ForwardRef) != 0) s.append(" forwardref");
+ if ((implAttr & Synchronized) != 0) s.append(" synchronized");
+ if ((implAttr & InternalCall) != 0) s.append(" internalcall");
+ return s.toString();
+ }
+
+ //##########################################################################
+
+} // class MethodImplAttributes
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java
new file mode 100644
index 0000000000..22b174d77b
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/MethodInfo.java
@@ -0,0 +1,57 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Discovers the attributes of a method and provides access to method metadata.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public class MethodInfo extends MethodBase {
+
+ //##########################################################################
+ // public members
+
+ public final int MemberType() { return MemberTypes.Method; }
+
+ public final boolean IsConstructor() { return false; }
+
+ /** The return type of this method.
+ */
+ public final Type ReturnType;
+
+ //##########################################################################
+ // protected members
+
+ protected static final MethodInfo[] EMPTY_ARRAY = new MethodInfo[0];
+
+ /**
+ * Constructor Initializes a new instance of the MethodInfo class.
+ */
+ protected MethodInfo(String name, Type declType,
+ int attrs, Type returnType, Type[] paramTypes )
+ {
+ super(name, declType, attrs, paramTypes);
+ ReturnType = returnType;
+ }
+
+ protected MethodInfo(String name, Type declType,
+ int attrs, Type returnType, ParameterInfo[] params )
+ {
+ super(name, declType, attrs, params);
+ ReturnType = returnType;
+ }
+
+ public String toString() {
+ return MethodAttributes.toString(Attributes) + " " + ReturnType +
+ " " + DeclaringType + "::" + Name + params2String();
+ }
+
+ //##########################################################################
+
+} // class MethodInfo
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Module.java b/src/msil/ch/epfl/lamp/compiler/msil/Module.java
new file mode 100644
index 0000000000..bd06c32223
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Module.java
@@ -0,0 +1,156 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Defines and represents a module. Get an instance of ModuleBuilder
+ * by calling DefineDynamicModule
+ * A module is a portable executable file of type .dll or .exe consisting
+ * of one or more classes and interfaces. There may be multiple namespaces
+ * contained in a single module, and a namespace may span multiple modules.
+ * One or more modules deployed as a unit compose an assembly.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class Module extends CustomAttributeProvider {
+
+ //##########################################################################
+ // public fields
+
+ /** String representing the name of the module with the path removed. */
+ public final String Name;
+
+ /** String representing the fully qualified name and path to this module. */
+ public final String FullyQualifiedName;
+
+ /** String representing the name of the module. */
+ public String ScopeName;
+
+ /** The Assembly the Module belongs to. */
+ public final Assembly Assembly;
+
+ //##########################################################################
+ // constructor
+
+ protected Module(String name, String filename,
+ String scopeName, Assembly assembly)
+ {
+ this.Name = name;
+ this.FullyQualifiedName = filename;
+ this.ScopeName = scopeName;
+ this.Assembly = assembly;
+ }
+
+ //##########################################################################
+ // public methods
+
+ /** Returns the specified class, performing a case-sensitive search. */
+ public Type GetType(String name) {
+ initTypes();
+ return (Type) typesMap.get(name);
+ }
+
+ /**
+ * @return all the classes defined within this module.
+ */
+ public Type[] GetTypes() {
+ initTypes();
+ return (Type[]) types.clone();
+ }
+
+ /**
+ * @return the global field with the specified name.
+ */
+ public FieldInfo GetField(String name) {
+ for (int i = 0; i < fields.length; i++)
+ if (fields[i].Name.equals(name))
+ return fields[i];
+ return null;
+ }
+
+ /**
+ * @return an array of the global fields of the module
+ */
+ public FieldInfo[] GetFields() {
+ return (FieldInfo[]) fields.clone();
+ }
+
+ /**
+ * @return - the global method with the specified name
+ */
+ public MethodInfo GetMethod(String name) {
+ for (int i = 0; i < methods.length; i++)
+ if (methods[i].Name.equals(name))
+ return methods[i];
+ return null;
+ }
+
+ /**
+ * @return - an array of all the global methods defined in this modules.
+ */
+ public MethodInfo[] GetMethods() {
+ return (MethodInfo[]) methods.clone();
+ }
+
+ /**
+ */
+ public String toString() { return Name; }
+
+ //########################################################################
+ // protected members
+
+ // all the types defined in this module
+ protected final Map typesMap = new HashMap();
+
+ // all the types defined in this module
+ protected Type[] types;
+
+ // the global fields of the module
+ protected FieldInfo[] fields = FieldInfo.EMPTY_ARRAY;
+
+ // the global methods of the module
+ protected MethodInfo[] methods = MethodInfo.EMPTY_ARRAY;
+
+ protected Type addType(Type type) {
+ addType(type.FullName, type);
+ Assembly.addType(type);
+ return type;
+ }
+
+ protected Type addType(String name, Type type) {
+ assert type!= null;
+ typesMap.put(name, type);
+ return type;
+ }
+
+ private boolean initTypes = true;
+ protected final void initTypes() {
+ if (initTypes) {
+ loadTypes();
+ initTypes = false;
+ }
+ }
+
+ protected void loadTypes() {}
+
+ private boolean initGlobals = true;
+ protected final void initGlobals() {
+ if (initGlobals) {
+ loadGlobals();
+ initGlobals = false;
+ }
+ }
+
+ protected void loadGlobals() {}
+
+ //##########################################################################
+
+} // class Module
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEAssembly.java b/src/msil/ch/epfl/lamp/compiler/msil/PEAssembly.java
new file mode 100644
index 0000000000..2d6d498bb0
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEAssembly.java
@@ -0,0 +1,70 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import ch.epfl.lamp.compiler.msil.util.Table;
+import ch.epfl.lamp.compiler.msil.util.Table.*;
+
+import java.io.File;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/** Represents an assembly that resides in a real .NET assembly
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+final class PEAssembly extends Assembly {
+
+ private final PEFile pefile;
+
+ private PEModule mainModule;
+
+ public PEAssembly(PEFile pefile, AssemblyName an) {
+ super(an, true);
+ this.pefile = pefile;
+ String name = pefile.ModuleDef(1).getName();
+ mainModule = new PEModule(pefile, 1, name, this);
+ addModule(name, mainModule);
+ //initModules();
+ }
+
+ protected void loadModules() {
+ File parentDir = pefile.getParentFile();
+ FileDef fd = pefile.FileDef;
+ for (int row = 1; row <= fd.rows; row++) {
+ fd.readRow(row);
+ String filename = fd.getName();
+ File f = new File(parentDir, filename);
+ PEFile pe = Assembly.getPEFile(f);
+ if (pe == null) {
+ f = new File(filename);
+ pe = Assembly.getPEFile(f);
+ if (pe == null)
+ continue;
+// throw new RuntimeException("Cannot find file " + filename +
+// " referenced by assembly " + this);
+ }
+ String name = pe.ModuleDef(1).getName();
+ PEModule module = new PEModule(pe, 1, name, this);
+ addModule(name, module);
+ }
+ }
+
+ public File getFile() {
+ return pefile.getUnderlyingFile();
+ }
+
+ protected void loadCustomAttributes(Type attributeType) {
+ initModules();
+ mainModule.initAttributes(this, 1, Table.AssemblyDef.ID, attributeType);
+ }
+
+ //##########################################################################
+
+} // class PEAssembly
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
new file mode 100644
index 0000000000..459bb39a20
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
@@ -0,0 +1,870 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import ch.epfl.lamp.compiler.msil.util.*;
+import ch.epfl.lamp.compiler.msil.util.Table.*;
+
+import ch.epfl.lamp.compiler.msil.Type;
+import ch.epfl.lamp.compiler.msil.Module;
+
+import java.io.File;
+import java.io.RandomAccessFile;
+import java.io.PrintStream;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.MappedByteBuffer;
+
+import java.util.Date;
+
+/**
+ * A class that represents a .NET PE/COFF image.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ * @see <a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm">Standard ECMA-335: Common Language Infrastructure (CLI), 4th edition (June 2006)</a>
+ */
+public class PEFile {
+
+ //##########################################################################
+
+ public static final int INT_SIZE = 4;
+
+ protected final int PE_SIGNATURE_OFFSET;
+ protected final int COFF_HEADER_OFFSET;
+ protected final int PE_HEADER_OFFSET;
+
+ protected final int numOfSections;
+ protected final int CLI_RVA;
+ protected final int CLI_Length;
+ public final int rvaMetadata;
+ public final int posMetadata;
+ protected final int numOfStreams;
+ protected final int optHeaderSize;
+
+ protected final File underlyingFile;
+ protected final RandomAccessFile file;
+ protected final MappedByteBuffer buf;
+
+ protected final PESection [] sections;
+
+ public PEStream Meta, Strings, US, Blob, GUID;
+
+ private final Table [] tables = new Table[Table.MAX_NUMBER];
+
+ public final boolean isDLL;
+
+ protected final int heapSizes;
+ public final boolean StringIsShort, BlobIsShort, GUIDIsShort;
+
+ protected PEModule pemodule = null;
+
+ //##########################################################################
+ // PEFile constructor
+
+ private static void fileFormatCheck(boolean cond, String s) {
+ if (cond)
+ throw new RuntimeException(s);
+ }
+
+ /**
+ */
+ public PEFile(String filename) throws FileNotFoundException {
+ this.underlyingFile = new File(filename);
+ this.file = new RandomAccessFile(underlyingFile, "r");
+ FileChannel fc = file.getChannel();
+ MappedByteBuffer bb = null;
+ try {
+ bb = fc.map(FileChannel.MapMode.READ_ONLY, 0L, fc.size());
+ } catch (IOException e) { throw new RuntimeException(e); }
+
+ /** Ecma 335, 25 File format extensions to PE:
+ *
+ * "Unless stated otherwise, all binary values are stored in little-endian format."
+ */
+
+ bb.order(java.nio.ByteOrder.LITTLE_ENDIAN);
+ this.buf = bb;
+
+ /** Ecma 335, 25.2.1 MS-DOS header:
+ *
+ * "The PE format starts with an MS-DOS stub of exactly the following 128 bytes to
+ * be placed at the front of the module."
+ *
+ * We are only checking for MZ (Mark Zbikowski)
+ */
+
+ seek(0);
+ fileFormatCheck(readByte() != 0x4d, "Invalid PE file format: " + filename); // 'M'
+ fileFormatCheck(readByte() != 0x5a, "Invalid PE file format: " + filename); // 'Z'
+
+ /** Ecma 335, 25.2.1 MS-DOS header:
+ *
+ * "At offset 0x3c in the DOS header is a 4-byte unsigned integer offset, lfanew,
+ * to the PE signature (shall be “PE\0\0”), immediately followed by the PE file header.
+ */
+
+ seek(0x3c);
+ PE_SIGNATURE_OFFSET = readInt();
+ seek(PE_SIGNATURE_OFFSET);
+
+ fileFormatCheck(readByte() != 0x50, "Invalid PE file format: " + filename); // 'P'
+ fileFormatCheck(readByte() != 0x45, "Invalid PE file format: " + filename); // 'E'
+ fileFormatCheck(readByte() != 0x00, "Invalid PE file format: " + filename); // 0
+ fileFormatCheck(readByte() != 0x00, "Invalid PE file format: " + filename); // 0
+
+ //trace("PE signature offset = 0x" + Table.int2hex(PE_SIGNATURE_OFFSET));
+
+ COFF_HEADER_OFFSET = PE_SIGNATURE_OFFSET + 4;
+ PE_HEADER_OFFSET = COFF_HEADER_OFFSET + 20;
+
+ seek(COFF_HEADER_OFFSET);
+ skip(2);
+ /** Ecma 335, 25.2.2: "Number of sections; indicates size of the Section Table" */
+ numOfSections = readShort();
+ //trace("Number of sections = " + numOfSections);
+
+ /** Ecma 335, 25.2.2: "Time and date the file was created in seconds since
+ * January 1st 1970 00:00:00 or 0."
+ */
+ Date timeStamp = new Date(readInt() * 1000L);
+ //trace("Time stamp = " + timeStamp);
+
+ skip(2 * INT_SIZE);
+ optHeaderSize = readShort();
+ int characteristics = readShort();
+ isDLL = (characteristics & 0x2000) != 0;
+ //trace("Characteristics = " + Integer.toHexString(characteristics));
+
+ seek(PE_HEADER_OFFSET + 208); // p.157, Partition II
+
+ CLI_RVA = readInt();
+ CLI_Length = readInt();
+ //trace("CLI_RVA = 0x" + Table.int2hex(CLI_RVA));
+ //trace("CLI_Length = 0x" + Table.int2hex(CLI_Length));
+
+ sections = new PESection[numOfSections];
+
+ seek(PE_HEADER_OFFSET + optHeaderSize); // go to the sections descriptors
+
+ for (int i = 0; i < numOfSections; i++) {
+ seek(PE_HEADER_OFFSET + optHeaderSize + i * 40);
+ sections[i] = new PESection(this);
+ //sections[i].dump(System.out);
+ }
+
+ seek(fromRVA(CLI_RVA));
+ skip(8);
+ rvaMetadata = readInt();
+ posMetadata = fromRVA(rvaMetadata);
+ //trace("rvaMetadata = 0x" + Table.int2hex(rvaMetadata));
+ //trace("posMetadata = 0x" + Table.int2hex(posMetadata));
+
+ seek(posMetadata);
+ int magic = readInt();
+ //trace("Magic metadata signature = 0x" + Table.int2hex(magic));
+ fileFormatCheck(magic != 0x424a5342, "Invalid metadata signature!");
+ skip(8);
+
+ int strlength = readInt();
+ //trace("version name string length = " + strlength);
+ skip(strlength);
+ align(INT_SIZE, posMetadata);
+ //trace("position of flags = 0x" + Table.int2hex((int)pos()));
+ skip(2); // ignore the flags
+ numOfStreams = readShort();
+ //trace("Number of metadata streams = " + numOfStreams);
+
+ for (int i = 0; i < numOfStreams; i++) {
+ PEStream strm = new PEStream(this);
+ //strm.dump(System.out);
+ if (strm.name.equals("#~")
+ || strm.name.equals("#-")) Meta = strm;
+ if (strm.name.equals("#Strings")) Strings = strm;
+ if (strm.name.equals("#US")) US = strm;
+ if (strm.name.equals("#Blob")) Blob = strm;
+ if (strm.name.equals("#GUID")) GUID = strm;
+ }
+
+ seek(Meta.offset);
+ skip(6);
+ heapSizes = readByte();
+ StringIsShort = (heapSizes & 0x01) == 0;
+ GUIDIsShort = (heapSizes & 0x02) == 0;
+ BlobIsShort = (heapSizes & 0x04) == 0;
+
+ skip(1);
+ long tablesMask = readLong();
+ long nonStandardTables = tablesMask & ~Table.VALID_TABLES_MASK;
+ skip(8); //go to the list of number of rows
+ for (int i = 0; i < tables.length; i++) {
+ tables[i] = Table.newTable
+ (this, i, ((tablesMask >> i) & 0x01) != 0 ? readInt() : 0);
+ }
+
+ initIndexSize();
+ initTableRefs();
+ // populate the tables from the CLI image file
+ long start = pos();
+ for (int i = 0; i < tables.length; i++)
+ start = tables[i].init(start);
+
+ } // PEFile()
+
+
+ public final int[] indexSize = new int[Table.TABLE_SET_LENGTH];
+
+ private void initIndexSize() {
+ for (int i = 0; i < Table.TABLE_SET_LENGTH; i++) {
+ indexSize[i] = 2;
+ int[] tableSet = Table.TableSet[i];
+ int treshold = (65536 >> Table.NoBits[i]);
+ for (int j = 0; j < tableSet.length; j++) {
+ if (tableSet[j] >= 0) {
+ Table t = tables[tableSet[j]];
+ if (t.rows >= treshold) {
+ indexSize[i] = 4;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ protected void initModule(PEModule module) {
+ if (pemodule != null)
+ throw new RuntimeException("File " + this
+ + " has already been assigned module "
+ + pemodule + "; new module is " + module);
+ this.pemodule = module;
+ }
+
+ //##########################################################################
+
+ public ModuleDef ModuleDef;
+ public ModuleDef ModuleDef(int i) {
+ ModuleDef.readRow(i);
+ return ModuleDef;
+ }
+
+ public TypeRef TypeRef;
+
+ public TypeDef TypeDef;
+ public TypeDef TypeDef(int i) {
+ TypeDef.readRow(i);
+ return TypeDef;
+ }
+
+ public FieldTrans FieldTrans;
+ public FieldTrans FieldTrans(int i) {
+ FieldTrans.readRow(i);
+ return FieldTrans;
+ }
+
+ public FieldDef FieldDef;
+ public FieldDef FieldDef(int i) {
+ FieldDef.readRow(i);
+ return FieldDef;
+ }
+
+ public MethodTrans MethodTrans;
+ public MethodTrans MethodTrans(int i) {
+ MethodTrans.readRow(i);
+ return MethodTrans;
+ }
+
+ public MethodDef MethodDef;
+ public MethodDef MethodDef(int i) { MethodDef.readRow(i); return MethodDef; }
+
+
+ public ParamDef ParamDef;
+ public ParamDef ParamDef(int i) { ParamDef.readRow(i); return ParamDef; }
+
+ public InterfaceImpl InterfaceImpl;
+ public MemberRef MemberRef;
+ public Constant Constant;
+ public CustomAttribute CustomAttribute;
+ public FieldMarshal FieldMarshal;
+ public DeclSecurity DeclSecurity;
+ public ClassLayout ClassLayout;
+ public FieldLayout FieldLayout;
+ public StandAloneSig StandAloneSig;
+ public EventMap EventMap;
+ public EventDef EventDef;
+ public PropertyMap PropertyMap;
+ public PropertyDef PropertyDef;
+ public MethodSemantics MethodSemantics;
+ public MethodImpl MethodImpl;
+ public ModuleRef ModuleRef;
+ public TypeSpec TypeSpec;
+ public ImplMap ImplMap;
+ public FieldRVA FieldRVA;
+ public AssemblyDef AssemblyDef;
+ public AssemblyRef AssemblyRef;
+ public FileDef FileDef;
+ public ExportedType ExportedType;
+ public ManifestResource ManifestResource;
+ public NestedClass NestedClass;
+
+
+ private void initTableRefs() {
+ ModuleDef = (ModuleDef) getTable(Table.ModuleDef.ID);
+ TypeRef = (TypeRef) getTable(Table.TypeRef.ID);
+ TypeDef = (TypeDef) getTable(Table.TypeDef.ID);
+ FieldTrans = (FieldTrans) getTable(Table.FieldTrans.ID);
+ FieldDef = (FieldDef) getTable(Table.FieldDef.ID);
+ MethodTrans = (MethodTrans) getTable(Table.MethodTrans.ID);
+ MethodDef = (MethodDef) getTable(Table.MethodDef.ID);
+ ParamDef = (ParamDef) getTable(Table.ParamDef.ID);
+ InterfaceImpl = (InterfaceImpl) getTable(Table.InterfaceImpl.ID);
+ MemberRef = (MemberRef) getTable(Table.MemberRef.ID);
+ Constant = (Constant) getTable(Table.Constant.ID);
+ CustomAttribute = (CustomAttribute) getTable(Table.CustomAttribute.ID);
+ FieldMarshal = (FieldMarshal) getTable(Table.FieldMarshal.ID);
+ DeclSecurity = (DeclSecurity) getTable(Table.DeclSecurity.ID);
+ ClassLayout = (ClassLayout) getTable(Table.ClassLayout.ID);
+ FieldLayout = (FieldLayout) getTable(Table.FieldLayout.ID);
+ StandAloneSig = (StandAloneSig) getTable(Table.StandAloneSig.ID);
+ EventMap = (EventMap) getTable(Table.EventMap.ID);
+ EventDef = (EventDef) getTable(Table.EventDef.ID);
+ PropertyMap = (PropertyMap) getTable(Table.PropertyMap.ID);
+ PropertyDef = (PropertyDef) getTable(Table.PropertyDef.ID);
+ MethodSemantics = (MethodSemantics) getTable(Table.MethodSemantics.ID);
+ MethodImpl = (MethodImpl) getTable(Table.MethodImpl.ID);
+ ModuleRef = (ModuleRef) getTable(Table.ModuleRef.ID);
+ TypeSpec = (TypeSpec) getTable(Table.TypeSpec.ID);
+ ImplMap = (ImplMap) getTable(Table.ImplMap.ID);
+ FieldRVA = (FieldRVA) getTable(Table.FieldRVA.ID);
+ AssemblyDef = (AssemblyDef) getTable(Table.AssemblyDef.ID);
+ AssemblyRef = (AssemblyRef) getTable(Table.AssemblyRef.ID);
+ FileDef = (FileDef) getTable(Table.FileDef.ID);
+ ExportedType = (ExportedType) getTable(Table.ExportedType.ID);
+ NestedClass = (NestedClass) getTable(Table.NestedClass.ID);
+ ManifestResource =
+ (ManifestResource) getTable(Table.ManifestResource.ID);
+ }
+
+ public static String long2hex(long a) {
+ StringBuffer str = new StringBuffer("0000000000000000");
+ str.append(Long.toHexString(a));
+ int l = str.length();
+ return str.substring(l - 16, l);
+ }
+
+ public static String int2hex(int a) {
+ StringBuffer str = new StringBuffer("00000000");
+ str.append(Integer.toHexString(a));
+ int l = str.length();
+ return str.substring(l - 8, l);
+ }
+
+ public static String short2hex(int a) {
+ StringBuffer str = new StringBuffer("0000");
+ str.append(Integer.toHexString(a));
+ int l = str.length();
+ return str.substring(l - 4, l);
+ }
+
+ public static String byte2hex(int a) {
+ StringBuffer str = new StringBuffer("00");
+ str.append(Integer.toHexString(a));
+ int l = str.length();
+ return str.substring(l - 2, l);
+ }
+
+ public static String bytes2hex(byte[] buf) {
+ StringBuffer str = new StringBuffer();
+ for (int i = 0; i < buf.length; i++) {
+ str.append(byte2hex(buf[i]));
+ if (i < buf.length - 1)
+ str.append(" ");
+ }
+ return str.toString();
+ }
+
+ //##########################################################################
+ // filename
+
+ public File getUnderlyingFile() {
+ return underlyingFile;
+ }
+
+ /**
+ * @return the absolute path of the file
+ */
+ public String getAbsolutePath() {
+ return underlyingFile.getAbsolutePath();
+ }
+
+ /**
+ * @return the name of this file
+ */
+ public String getName() {
+ return underlyingFile.getName();
+ }
+
+ /**
+ * @return
+ */
+ public String getParent() {
+ return underlyingFile.getParent();
+ }
+
+ /**
+ * @return the file representing the directory the file belongs to
+ */
+ public File getParentFile() {
+ return underlyingFile.getParentFile();
+ }
+
+ public String toString() {
+ return getAbsolutePath();
+ }
+
+ //##########################################################################
+ // file pointer manipulation methods
+
+ /** Returns the current position in the file. */
+ public int pos() {
+ return buf.position();
+ }
+
+ /** Go to the specified position in the file. */
+ public void seek(int pos) {
+ buf.position(pos);
+ }
+
+
+ /** Align the current position in the file. */
+ public void align(int base) { align(base, 0); }
+
+ /** Align the current position in a section starting at offset. */
+ public void align(int base, int offset) {
+ int p = pos() - offset;
+ seek( offset + ((p % base) == 0 ? p : (p/base + 1) * base));
+ }
+
+ /** Computes the position in the file that corresponds to the given RVA. */
+ public int fromRVA(int rva) {
+ int i;
+ for(i = 0; i < numOfSections; i++)
+ if(sections[i].virtAddr <= rva &&
+ rva <= (sections[i].virtAddr + sections[i].virtSize))
+ return rva - sections[i].virtAddr + sections[i].realAddr;
+ throw new RuntimeException("RVA 0x" + Integer.toHexString(rva) +
+ " is not within this file's sections!");
+ }
+
+ /** Go to the specified RVA (Relative Virtual Address). */
+ public void gotoRVA(int rva) {
+ seek(fromRVA(rva));
+ }
+
+ /** Move the forward in the file by the specified number of bytes. */
+ public void skip(int n) {
+ buf.position(buf.position() + n);
+ }
+
+ /**
+ * Returns a memory mapped little-endian buffer
+ * for the specified region of the file.
+ */
+ public MappedByteBuffer mapBuffer(long offset, int size) {
+ try {
+ MappedByteBuffer b = file.getChannel()
+ .map(FileChannel.MapMode.READ_ONLY, offset, size);
+ b.order(java.nio.ByteOrder.LITTLE_ENDIAN);
+ return b;
+ } catch (IOException e) { throw new RuntimeException(e); }
+ }
+
+ /** Returns a buffer from the given offset to the end of the file. */
+ public ByteBuffer getBuffer(long offset, int size) {
+ buf.mark();
+ buf.position((int)offset);
+ ByteBuffer bb = buf.slice();
+ buf.reset();
+ bb.limit(size);
+ bb.order(java.nio.ByteOrder.LITTLE_ENDIAN);
+ return bb;
+ }
+
+ //##########################################################################
+ // file read methods
+
+ /**
+ * Read bs.length number of bytes
+ */
+ public void read(byte[] bs) {
+ buf.get(bs);
+ }
+
+ /**
+ * Read 1-byte integer from the current position in the file.
+ */
+ public int readByte() {
+ return buf.get();
+ }
+
+ /**
+ * Read 2-byte integer from the current position in the file.
+ */
+ public int readShort() {
+ return buf.getShort();
+ }
+
+ /**
+ * Read 4-byte integer from the current position in the file.
+ */
+ public int readInt() {
+ return buf.getInt();
+ }
+
+ /**
+ * Read 8-byte integer from the current position in the file.
+ */
+ public long readLong() {
+ return buf.getLong();
+ }
+
+ /**
+ * @return the size of string indeces for this file.
+ */
+ public int getStringIndexSize() {
+ return StringIsShort ? 2 : 4;
+ }
+
+ /**
+ * @return the size of GUID indeces for this file.
+ */
+ public int getGUIDIndexSize() {
+ return GUIDIsShort ? 2 : 4;
+ }
+
+ /**
+ * @return the size of Blob indeces for this file.
+ */
+ public int getBlobIndexSize() {
+ return BlobIsShort ? 2 : 4;
+ }
+
+ /**
+ * @return the size of the index to tableID for this file;
+ * @param tableID the ID of the table
+ */
+ public int getTableIndexSize(int tableID) {
+ return tables[tableID].isShort ? 2 : 4;
+ }
+
+ /**
+ * @return the size of the index to a set of tables with the given @param TableSetID
+ * @param tableSetID the ID of the table set
+ */
+ public int getTableSetIndexSize(int tableSetID) {
+ return indexSize[tableSetID];
+ }
+
+ /**
+ * Read a String index from the current position in the file.
+ * @return an index into the String stream
+ */
+ public int readStringIndex() {
+ return StringIsShort ? readShort() : readInt();
+ }
+
+ /**
+ * Read a GUID index from the current position in the file.
+ * @return an index in to the GUID stream
+ */
+ public int readGUIDIndex() {
+ return GUIDIsShort ? readShort() : readInt();
+ }
+
+ /**
+ * Read a Blob index from the current position in the file.
+ * @return an index into the Blob stream
+ */
+ public int readBlobIndex() {
+ return BlobIsShort ? readShort() : readInt();
+ }
+
+ /** Read an entry interpreted as index into table @param tableID. */
+ public int readTableIndex(int tableId) {
+ return tables[tableId].isShort ? readShort() : readInt();
+ }
+
+ /***/
+ public int readTableSetIndex(int tableSetId) {
+ return indexSize[tableSetId] == 2 ? readShort() : readInt();
+ }
+
+ /**
+ * Read a string from the String stream
+ * @return the string at the given position
+ * @param pos the position of the string in the String stream
+ */
+ public String getString(int pos) {
+ String s = Strings.getString(pos);
+ return s;//.length() == 0 ? null : s;
+ }
+
+ /**
+ * Read a string from the US (User Strings) stream
+ * @return the string at the given position
+ * @param pos the position of the string in the US stream
+ */
+ public String getUString(int pos) {
+ return US.getString(pos);
+ }
+
+ /**
+ * Read a blob from the Blob Stream
+ * @return the blob at the given position
+ * @param pos the position of the blob in the Blob stream
+ */
+ public byte[] getBlob(int pos) {
+ return Blob.getBlob(pos);
+ }
+
+ /***/
+ public Sig getSignature(int pos) {
+ //return new Sig(getBlob(pos));
+ return Blob.getSignature(pos);
+ }
+
+ /***/
+ public byte[] getGUID(int pos) {
+ return GUID.getGUID(pos);
+ }
+
+ /**
+ * @return the table with the corresponding ID.
+ */
+ public final Table getTable(int tableID) {
+ return tables[tableID];
+ }
+
+ //##########################################################################
+
+ /***/
+ void trace(String msg) {
+ System.out.println("[trace] " + msg);
+ }
+
+ //##########################################################################
+
+ public Sig newSignature(ByteBuffer buf) {
+ return new Sig(buf);
+ }
+
+ /**
+ */
+ public class Sig implements Signature {
+
+ //######################################################################
+ // instance members
+
+ protected final ByteBuffer buf;
+ protected final int pos;
+ protected final int length;
+
+ public Sig(ByteBuffer buf) {
+ this.buf = buf;
+ //int tmpPos = buf.position();
+ length = decodeInt();
+ this.pos = buf.position();
+ }
+
+ public String toString() {
+ StringBuffer b = new StringBuffer("(");
+ reset();
+ for (int i = 0; i < length; i++) {
+ b.append(byte2hex(readByte()));
+ if (i < length - 1)
+ b.append(" ");
+ }
+ return b.append(")").toString();
+ }
+
+ public Sig reset() { buf.position(pos); return this; }
+
+ public int pos() { return buf.position() - pos; }
+
+ /** @return the byte at the current position in the signature Blob.
+ * Stay at the same position
+ */
+ public int getByte() {
+ return (buf.get(buf.position()) + 0x100) & 0xff;
+ }
+
+ /** @return the byte at the current position in the signature Blob.
+ * Move to the next byte.
+ */
+ public int readByte() { return (buf.get() + 0x100) & 0xff; }
+
+ /** Skip the current byte if equal to the given value. */
+ public void skipByte(int b) { if (b == getByte()) buf.get(); }
+
+ /** Decodes an integer from the signature Blob.
+ * @return the decoded integer
+ */
+ public int decodeInt() {
+ int res = readByte();
+ if ((res & 0x80) != 0) {
+ res = ((res & 0x7f) << 8) | readByte();
+ if ((res & 0x4000) != 0)
+ res = ((res & 0x3fff)<<16) | (readByte()<<8) | readByte();
+ }
+ return res;
+ }
+
+ /** @return - the type encoded at the current position in the signature
+ * according to 22.2.12
+ */
+ public Type decodeType() {
+ try { return decodeType0(); }
+ catch (RuntimeException e) {
+ System.out.println("" + pos() + "@" + this);
+ throw e;
+ }
+ }
+
+ public Type decodeType0() {
+ Type type = null;
+ int desc = readByte();
+ switch (desc) {
+ case ELEMENT_TYPE_BOOLEAN:type = Type.GetType("System.Boolean"); break;
+ case ELEMENT_TYPE_CHAR: type = Type.GetType("System.Char"); break;
+ case ELEMENT_TYPE_I1: type = Type.GetType("System.SByte"); break;
+ case ELEMENT_TYPE_U1: type = Type.GetType("System.Byte"); break;
+ case ELEMENT_TYPE_I2: type = Type.GetType("System.Int16"); break;
+ case ELEMENT_TYPE_U2: type = Type.GetType("System.UInt16"); break;
+ case ELEMENT_TYPE_I4: type = Type.GetType("System.Int32"); break;
+ case ELEMENT_TYPE_U4: type = Type.GetType("System.UInt32"); break;
+ case ELEMENT_TYPE_I8: type = Type.GetType("System.Int64"); break;
+ case ELEMENT_TYPE_U8: type = Type.GetType("System.UInt64"); break;
+ case ELEMENT_TYPE_R4: type = Type.GetType("System.Single"); break;
+ case ELEMENT_TYPE_R8: type = Type.GetType("System.Double"); break;
+ case ELEMENT_TYPE_OBJECT: type = Type.GetType("System.Object"); break;
+ case ELEMENT_TYPE_STRING: type = Type.GetType("System.String"); break;
+ case ELEMENT_TYPE_I: type = Type.GetType("System.IntPtr"); break;
+ case ELEMENT_TYPE_U: type = Type.GetType("System.UIntPtr"); break;
+ case ELEMENT_TYPE_PTR: // Followed by <type> token.
+ if (getByte() == ELEMENT_TYPE_VOID) {
+ readByte();
+ type = Type.mkPtr(Type.GetType("System.Void"));
+ } else type = Type.mkPtr(decodeType());
+ break;
+ case ELEMENT_TYPE_BYREF: // Followed by <type> token.
+ case ELEMENT_TYPE_VALUETYPE: // Followed by <type> token
+ //System.out.println("Signature.getType(): valuetype");
+ //type = pemodule.getTypeDefOrRef(decodeInt());
+ case ELEMENT_TYPE_CLASS:
+ // Followed by <type> token
+ type = pemodule.getTypeDefOrRef(decodeInt());
+ if (type == null) throw new RuntimeException();
+ break;
+
+ case ELEMENT_TYPE_SZARRAY: // Single-dim array with 0 lower bound.
+ skipCustomMods();
+ type = Type.mkArray(decodeType(), 1);
+ break;
+ case ELEMENT_TYPE_ARRAY:
+ // <type> <rank> <boundsCount> <bound1> ... <loCount> <lo1> ...
+ Type elem = decodeType();
+ int rank = decodeInt();
+ int numSizes = decodeInt();
+ for (int i = 0; i < numSizes; i++)
+ decodeInt();
+ int numLoBounds = decodeInt();
+ for (int i = 0; i < numLoBounds; i++)
+ decodeInt();
+ type = Type.mkArray(elem, rank);
+ break;
+
+ case ELEMENT_TYPE_FNPTR:
+ // Followed by full method signature.
+ case ELEMENT_TYPE_END:
+ // Marks end of a list
+ case ELEMENT_TYPE_CMOD_REQD:
+ // Required modifier : followed by a TypeDef or TypeRef token.
+ case ELEMENT_TYPE_CMOD_OPT:
+ // Optional modifier : followed by a TypeDef or TypeRef token.
+ case ELEMENT_TYPE_INTERNAL:
+ // Implemented within the CLI.
+ case ELEMENT_TYPE_MODIFIER:
+ // Or'd with following element types.
+ case ELEMENT_TYPE_SENTINEL:
+ // Sentinel for varargs method signature.
+ case ELEMENT_TYPE_PINNED:
+ // Denotes a local variable that points at a pinned object.
+ default:
+ throw new RuntimeException(byte2hex(desc) +
+ "@" + pos() + " in " + this);
+
+ }
+ if (type == null) throw new RuntimeException();
+ return type;
+ } // getType()
+
+ public Type decodeFieldType() {
+ skipByte(FIELD);
+ skipCustomMods();
+ return decodeType();
+ }
+
+ /** decodes the return type of a method signature (22.2.11). */
+ public Type decodeRetType() {
+ skipCustomMods();
+ switch (getByte()) {
+ case ELEMENT_TYPE_VOID:
+ readByte();
+ return Type.GetType("System.Void");
+ case ELEMENT_TYPE_TYPEDBYREF:
+ return Type.GetType("System.TypedReference");
+ case ELEMENT_TYPE_BYREF:
+ skipByte(ELEMENT_TYPE_BYREF);
+ return decodeType();
+ default:
+ return decodeType();
+ }
+ }
+
+ public Type decodeParamType() {
+ skipCustomMods();
+ switch (getByte()) {
+ case ELEMENT_TYPE_BYREF:
+ skipByte(ELEMENT_TYPE_BYREF);
+ return decodeType();
+ case ELEMENT_TYPE_TYPEDBYREF:
+ return Type.GetType("System.TypedReference");
+ default:
+ return decodeType();
+ }
+ }
+
+ public void skipCustomMods() {
+ while (getByte() == ELEMENT_TYPE_CMOD_OPT
+ || getByte() == ELEMENT_TYPE_CMOD_REQD)
+ {
+ Type t = decodeType();
+ System.err.println("CMOD: " + t);
+ if (getByte() == ELEMENT_TYPE_CMOD_REQD)
+ throw new RuntimeException("Reqired CMOD: " + t);
+ }
+ }
+
+ //######################################################################
+
+ } // class Sig
+
+ //##########################################################################
+
+} // class PEFile
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java b/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java
new file mode 100644
index 0000000000..a6e7bb31b2
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java
@@ -0,0 +1,327 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import ch.epfl.lamp.compiler.msil.PEFile;
+import ch.epfl.lamp.compiler.msil.PEFile.Sig;
+import ch.epfl.lamp.compiler.msil.util.Table;
+import ch.epfl.lamp.compiler.msil.util.Table.*;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/** Represents a module corresponding to a PE/COFF file
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+final class PEModule extends Module {
+
+ //##########################################################################
+
+ protected final PEFile pefile;
+
+ private final int definingRow;
+
+ private Type[] typeRefs = null;
+
+ protected PEModule(PEFile pefile, int definingRow, String scopeName,
+ Assembly assem)
+ {
+ super(pefile.getName(), pefile.getAbsolutePath(), scopeName, assem);
+ this.pefile = pefile;
+ this.definingRow = definingRow;
+ pefile.initModule(this);
+ pefile.TypeDef.load(); // load into memory
+ //loadTypes();
+ //pefile.FieldDef.load();
+ //pefile.MethodDef.load();
+ loadGlobals();
+ }
+
+ //##########################################################################
+
+ public Type GetType(String typeName) {
+ initTypes();
+ Object o = typesMap.get(typeName);
+ if (o == null) {
+ //System.out.println("PEModule.GetType(): Unable to find type "
+ // + typeName + " int module " + this);
+ return null;
+ }
+ return o instanceof Type ? (Type)o
+ : getTypeDef(((Integer)o).intValue());
+ }
+
+
+ /** Load information about the types defined in this module.
+ */
+ protected void loadTypes() {
+ typeRefs = new Type[pefile.TypeRef.rows];
+ final int nbTypes = pefile.TypeDef.rows;
+ for (int row = 2; row <= nbTypes; row++) {
+ String name = pefile.TypeDef(row).getFullName();
+ typesMap.put(name, new Integer(row));
+ }
+ this.types = new Type[nbTypes - 1];
+ for (int row = 2; row <= nbTypes; row++) {
+ getTypeDef(row);
+ }
+ }
+
+ /** Return the type defined at the given row in the TypeDef table.
+ */
+ Type getTypeDef(int row) {
+ if (this.types[row - 2] != null)
+ return this.types[row - 2];
+
+ TypeDef type = pefile.TypeDef(row);
+ int attrs = type.Flags;
+ String name = type.getFullName();
+
+ Type declType = null;
+ if (TypeAttributes.isNested(attrs)) {
+ for (int i = 1; i <= pefile.NestedClass.rows; i++) {
+ pefile.NestedClass.readRow(i);
+ if (pefile.NestedClass.NestedClass == row)
+ declType = getTypeDef
+ (pefile.NestedClass.EnclosingClass);
+ }
+ }
+ Type t = new PEType
+ (this, attrs, name, declType, Type.AuxAttr.None, pefile, row);
+ types[row - 2] = t;
+ addType(t);
+ return t;
+ }
+
+ /**
+ * Load the desription of the module-global fields and methods
+ */
+ protected void loadGlobals() {
+ //TODO:
+ }
+
+ protected void loadCustomAttributes(Type attributeType) {
+ initAttributes(this, 1, Table.ModuleDef.ID, attributeType);
+ }
+
+ /** Return the type referenced by the given row in the TypeRef table.
+ */
+ Type getTypeRef(int row) {
+ return getTypeRef(row, null);
+ }
+
+ /** Return the type referenced by the given row in the TypeRef table
+ * only if it resides in the given assembly.
+ * <i>Used by initCustomAttributes to avoid unnecessary loading
+ * of referenced assemblies.</i>
+ */
+ Type getTypeRef(int row, Assembly inAssembly) {
+ Type type = typeRefs[row - 1];
+ if (type != null)
+ return type;
+
+ Table.TypeRef tr = pefile.TypeRef;
+ tr.readRow(row);
+ int tableId = Table.getTableId(Table._ResolutionScope,
+ tr.ResolutionScope);
+ int refRow = tr.ResolutionScope >> Table.NoBits[Table._ResolutionScope];
+ String typeName = tr.getFullName();
+ pefile.getTable(tableId).readRow(refRow);
+ switch (tableId) {
+ case AssemblyRef.ID:
+ String name = pefile.AssemblyRef.getName();
+ if (inAssembly != null && !inAssembly.GetName().Name.equals(name))
+ return null;
+ Assembly assem = getAssembly(name);
+ type = assem.GetType(typeName);
+ if (type == null) {
+ throw new RuntimeException("Failed to locate type " +
+ typeName + " in assembly " + assem);
+ }
+ break;
+ case ModuleDef.ID:
+ assert refRow == 1;
+ type = this.GetType(typeName);
+ //assert type != null;
+ break;
+ case TypeRef.ID:
+ type = getTypeRef(refRow);
+ break;
+ case ModuleRef.ID:
+ type = getAssembly(pefile.ModuleRef.getName()).GetType(typeName);
+ default:
+ throw new RuntimeException(refRow + "@" + pefile.getTable(tableId).getTableName()/* PEFile.byte2hex(tableId)*/);
+ }
+ if (typeRefs[row - 1] != null)
+ System.out.println("TypeRef[" + PEFile.short2hex(row) + "] " +
+ "changing type " + typeRefs[row - 1] +
+ " for type " + type);
+ typeRefs[row - 1] = type;
+ assert type != null : "Couldn't find type " + typeName;
+ return type;
+ }
+
+ private Assembly getAssembly(String name) {
+ Assembly assem = Assembly.getAssembly(name);
+ if (assem != null)
+ return assem;
+ java.io.File dir = pefile.getParentFile();
+ assem = Assembly.LoadFrom(dir, name);
+ if (assem != null)
+ return assem;
+ try {
+ dir = pefile.getUnderlyingFile().getCanonicalFile().getParentFile();
+ } catch (java.io.IOException e) {
+ throw new RuntimeException(e);
+ }
+ assem = Assembly.LoadFrom(dir, name);
+ if (assem != null)
+ return assem;
+ throw new RuntimeException("Cannot find assembly: " + name);
+
+ }
+
+ /** Return the type corresponding to TypeDefOrRef coded index.
+ * @param index - TypeDefOrRef coded index according to 23.2.6.
+ */
+ public Type getTypeDefOrRef(int index) {
+ int tableId = Table.getTableId(Table._TypeDefOrRef, index);
+ int row = index >> Table.NoBits[Table._TypeDefOrRef];
+ Type type = null;
+ switch (tableId) {
+ case Table.TypeDef.ID:
+ type = getTypeDef(row);
+ break;
+ case Table.TypeRef.ID:
+ return getTypeRef(row);
+ case Table.TypeSpec.ID:
+ throw new RuntimeException("PEModule.getTypeDefOrRef(): TypeSpec");
+ default:
+ throw new RuntimeException("PEModule.getTypeDefOrRef(): oops!");
+ }
+ return type;
+ }
+
+ /** Returns the method defined at the given row of the MethodDef table
+ * by looking up the type that defines the method.
+ */
+ MethodBase getMethod(int row) {
+ for (int i = 0; i < types.length; i++) {
+ PEType type = (PEType)types[i];
+ if ((type.methodListBeg <= row) && (row < type.methodListEnd)) {
+ type.initMethods();
+ return type.methoddefs[row - type.methodListBeg];
+ }
+ }
+ throw new RuntimeException("In module " + this
+ + ": cannot find type defining method 0x"
+ + PEFile.int2hex(row));
+ }
+
+ /** Returns the member referenced by the given row of the MemberRef table.
+ */
+ protected MemberInfo getMemberRef(int row) {
+ return getMemberRef(row, null);
+ }
+
+ /** Returns the member referenced by the given row of the MemberRef table
+ * if defined in the given assembly.
+ * <i>Used by initCustomAttributes to avoid unnecessary loading of
+ * referenced assemblies</i>
+ */
+ protected MemberInfo getMemberRef(int row, Assembly inAssembly) {
+ MemberInfo member = null;
+ MemberRef mref = pefile.MemberRef;
+ mref.readRow(row);
+ int mtbl = Table.getTableId(Table._MemberRefParent, mref.Class);
+ int mind = Table.getTableIndex(Table._MemberRefParent, mref.Class);
+ switch (mtbl) {
+ case TypeRef.ID:
+ Type type = getTypeRef(mind, inAssembly);
+ if (type == null)
+ return null;
+ Sig sig = mref.getSignature();
+ int callconv = sig.readByte(); // should be 0x20
+ int paramCount = sig.decodeInt();
+ //sig.skipByte(Signature.ELEMENT_TYPE_BYREF); //from MethodDef
+ Type retType = sig.decodeRetType();
+ Type[] paramType = new Type[paramCount];
+ for (int i = 0; i < paramCount; i++)
+ paramType[i] = sig.decodeParamType();
+
+ String memberName = mref.getName();
+ if (memberName.equals(ConstructorInfo.CTOR) ||
+ memberName.equals(ConstructorInfo.CCTOR))
+ {
+ member = type.GetConstructor(paramType);
+ } else {
+ member = type.GetMethod(memberName, paramType);
+ }
+ assert member != null : type + "::" + memberName;
+ break;
+ case ModuleRef.ID:
+ case MethodDef.ID:
+ case TypeSpec.ID:
+ throw new RuntimeException("initCustomAttributes: "
+ + pefile.getTable(mtbl).getTableName());
+ }
+ return member;
+ }
+
+ protected void initCustomAttributes(Type attributeType) {
+ initAttributes(this, definingRow, Table.ModuleDef.ID, attributeType);
+ }
+
+ // explicitly only package-visible
+ void initAttributes(CustomAttributeProvider cap, int definingRow,
+ int sourceTableId, Type attributeType)
+ {
+ int parentIndex = Table.encodeIndex(definingRow,
+ Table._HasCustomAttribute,
+ sourceTableId);
+ Table.CustomAttribute attrs = pefile.CustomAttribute;
+ for (int row = 1; row <= attrs.rows; row++) {
+ ConstructorInfo attrConstr = null;
+ attrs.readRow(row);
+ if (attrs.Parent == parentIndex) {
+ int tableId = Table.getTableId(Table._CustomAttributeType,
+ attrs.Type);
+ int ind = Table.getTableIndex(Table._CustomAttributeType,
+ attrs.Type);
+ switch (tableId) {
+ case MethodDef.ID:
+ attrConstr = (ConstructorInfo)this.getMethod(ind);
+ break;
+ case MemberRef.ID:
+ //System.out.println(PEFile.short2hex(ind) + "@MemberRef");
+ Assembly attrAssem =
+ attributeType == null ? null : attributeType.Assembly();
+ MemberInfo mi = this.getMemberRef(ind, attrAssem);
+ if (mi != null) {
+ assert mi instanceof ConstructorInfo
+ : "Expected ConstructorInfo; found " + mi;
+ attrConstr = (ConstructorInfo)mi;
+ }
+ break;
+ default:
+ throw new RuntimeException();
+ }
+ if (attrConstr != null
+ && (attrConstr.DeclaringType == attributeType
+ || attributeType == null))
+ cap.addCustomAttribute(attrConstr, attrs.getValue());
+ }
+ }
+ }
+
+ //##########################################################################
+
+} // class PEModule
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEType.java b/src/msil/ch/epfl/lamp/compiler/msil/PEType.java
new file mode 100644
index 0000000000..67686baad2
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEType.java
@@ -0,0 +1,399 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import ch.epfl.lamp.compiler.msil.PEFile.Sig;
+
+import ch.epfl.lamp.compiler.msil.util.Table;
+import ch.epfl.lamp.compiler.msil.util.Table.*;
+import ch.epfl.lamp.compiler.msil.util.Signature;
+
+import java.util.ArrayList;
+
+/**
+ * Represents a type from a .NET assembly
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+final class PEType extends Type implements Signature {
+
+ //##########################################################################
+
+ /** The PEFile that holds the description of the type. */
+ final PEFile file;
+
+ /** The number of the row in the TypeDef table defining the type. */
+ final int definingRow;
+
+ /** The row of the first method in the MethodDef table. */
+ final int methodListBeg;
+
+ /** The row of the last method in the MethodDef table + 1. */
+ final int methodListEnd;
+
+ /** @param definingRow - the index in the TypeDef table where
+ * the type description is.
+ */
+ PEType(PEModule module,
+ int attributes,
+ String fullName,
+ Type declType,
+ int auxAttr,
+ PEFile file,
+ int definingRow)
+ {
+ super(module, attributes, fullName, null, null, declType, auxAttr);
+ this.file = file;
+ this.definingRow = definingRow;
+ methodListBeg = file.TypeDef(definingRow).MethodList;
+ methodListEnd = definingRow < file.TypeDef.rows
+ ? file.TypeDef(definingRow + 1).MethodList
+ : file.MethodDef.rows + 1;
+ }
+
+ //##########################################################################
+ // lazy type construction methods
+
+ protected void loadBaseType() {
+ TypeDef type = file.TypeDef(definingRow);
+ baseType = type.Extends == 0 ? null
+ : ((PEModule)Module).getTypeDefOrRef(type.Extends);
+ }
+
+ protected void loadFields() {
+ // the list of the declared fields starts from the
+ // FieldList index in the TypeDef table up to the smaller of the:
+ // - the last row of the FieldDef table
+ // - the start of the next list of fields determined by the
+ // FieldList index of the next row in the TypeDef table
+ final ArrayList fields = new ArrayList();
+ int fieldListBeg = file.TypeDef(definingRow).FieldList;
+ int fieldListEnd = file.FieldDef.rows + 1;
+ if (definingRow < file.TypeDef.rows)
+ fieldListEnd = file.TypeDef(definingRow + 1).FieldList;
+
+ for (int row = fieldListBeg; row < fieldListEnd; row++) {
+ int frow = file.FieldTrans.rows == 0
+ ? row : file.FieldTrans(row).Field;
+ int attrs = file.FieldDef(frow).Flags;
+ String name = file.FieldDef.getName();
+ //System.out.println("\t-->Loading field: " + name);
+ Sig sig = file.FieldDef.getSignature();
+ Type fieldType = sig.decodeFieldType();
+ Object val = null;
+ Table.Constant consts = file.Constant;
+ for (int i = 1; i <= consts.rows; i++) {
+ consts.readRow(i);
+ int tableId = Table.getTableId(Table._HasConstant,consts.Parent);
+ int refRow = consts.Parent >> Table.NoBits[Table._HasConstant];
+ if (tableId == Table.FieldDef.ID && refRow == frow)
+ val = consts.getValue();
+ }
+ FieldInfo field =
+ new PEFieldInfo(row, name, attrs, fieldType, val);
+ if (field.Name.equals("value__") && field.IsSpecialName())
+ {
+ assert underlyingType == null : underlyingType.toString();
+ underlyingType = field.FieldType;
+ }
+ fields.add(field);
+ }
+ this.fields = (FieldInfo[])
+ fields.toArray(FieldInfo.EMPTY_ARRAY);
+ fields.clear();
+ }
+
+ protected MethodBase[] methoddefs;
+ protected MethodInfo getMethod(int n) {
+ return (MethodInfo)methoddefs[n - methodListBeg];
+ }
+ protected void loadMethods() {
+ methoddefs = new MethodBase[methodListEnd - methodListBeg];
+
+ final ArrayList methods = new ArrayList();
+ final ArrayList constrs = new ArrayList();
+ PEModule pemodule = (PEModule) Module;
+ for (int row = methodListBeg; row < methodListEnd; row++) {
+ int mrow = file.MethodTrans.rows == 0
+ ? row : file.MethodTrans(row).Method;
+ int attrs = file.MethodDef(mrow).Flags;
+ String name = file.MethodDef.getName();
+ Sig sig = file.MethodDef.getSignature();
+ int callConv = sig.readByte();
+ int paramCount = sig.decodeInt();
+ sig.skipByte(Signature.ELEMENT_TYPE_BYREF);
+ Type retType = sig.decodeRetType();
+ Type[] paramType = new Type[paramCount];
+ for (int i = 0; i < paramCount; i++)
+ paramType[i] = sig.decodeParamType();
+
+ ParameterInfo[] params = new ParameterInfo[paramCount];
+ int paramListBeg = file.MethodDef.ParamList;
+ int paramListEnd = file.ParamDef.rows + 1;
+ // if not the last method
+ if (file.MethodDef.currentRow() < file.MethodDef.rows) {
+ paramListEnd = file.MethodDef(mrow + 1).ParamList;
+ }
+ for (int i = paramListBeg; i < paramListEnd; i++) {
+ int pattr = file.ParamDef(i).Flags;
+ String paramName = file.ParamDef.getName();
+ int seq = file.ParamDef.Sequence;
+ if (seq == 0) {
+ //System.out.println("Retval attributes 0x" +
+ // PEFile.short2hex(pattr));
+ } else {
+ params[seq - 1] = new ParameterInfo
+ (paramName, paramType[seq - 1], pattr, seq - 1);
+ }
+ }
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] == null)
+ params[i] = new ParameterInfo(null, paramType[i], 0, 0);
+ }
+ MethodBase method = null;
+ if ((attrs & MethodAttributes.SpecialName) != 0
+ && (attrs & MethodAttributes.RTSpecialName) != 0
+ && (name.equals(ConstructorInfo.CTOR)
+ || name.equals(ConstructorInfo.CCTOR)))
+ method = new PEConstructorInfo(row, attrs, params);
+ else
+ method = new PEMethodInfo(row, name, attrs, retType, params);
+ (method.IsConstructor() ? constrs : methods).add(method);
+ methoddefs[row - methodListBeg] = method;
+ }
+
+ this.constructors = (ConstructorInfo[])
+ constrs.toArray(ConstructorInfo.EMPTY_ARRAY);
+ this.methods = (MethodInfo[])
+ methods.toArray(MethodInfo.EMPTY_ARRAY);
+ constrs.clear(); methods.clear();
+ }
+
+ protected void loadProperties() {
+ final PropertyMap pmap = file.PropertyMap;
+ if (pmap == null) {
+ properties = PropertyInfo.EMPTY_ARRAY;
+ return;
+ }
+
+ final PropertyDef pdef = file.PropertyDef;
+ int propListBeg = -1;
+ int propListEnd = pdef.rows + 1;
+ for (int i = 1; i <= pmap.rows; i++) {
+ pmap.readRow(i);
+ if (pmap.Parent == this.definingRow) {
+ propListBeg = pmap.PropertyList;
+ if (i < pmap.rows) {
+ pmap.readRow(i + 1);
+ propListEnd = pmap.PropertyList;
+ }
+ break;
+ }
+ }
+ if (propListBeg < 0) {
+ properties = PropertyInfo.EMPTY_ARRAY;
+ return;
+ }
+
+ final ArrayList properties = new ArrayList();
+ for (int i = propListBeg; i < propListEnd; i++) {
+ pdef.readRow(i);
+ Sig sig = pdef.getSignature();
+ int b = sig.readByte();
+ b &= ~HASTHIS;
+ int paramCount = sig.readByte();
+ assert b == PROPERTY;
+ Type propType = sig.decodeType();
+ int index = Table.encodeIndex(i, Table._HasSemantics,
+ Table.PropertyDef.ID);
+ MethodSemantics msem = file.MethodSemantics;
+ MethodInfo getter = null, setter = null;
+ for (int j = 1; j <= msem.rows; j++) {
+ msem.readRow(j);
+ if (msem.Association != index)
+ continue;
+ if (msem.isGetter())
+ getter = getMethod(msem.Method);
+ else if (msem.isSetter())
+ setter = getMethod(msem.Method);
+ else
+ System.err.println("PEType.loadProperties(): !?!");
+ }
+ properties.add
+ (new PEPropertyInfo(i, pdef.getName(), (short)pdef.Flags,
+ propType, getter, setter));
+ }
+ this.properties = (PropertyInfo[]) properties
+ .toArray(PropertyInfo.EMPTY_ARRAY);
+ }
+
+ protected void loadEvents() {
+ EventMap emap = file.EventMap;
+ if (emap == null) {
+ this.events = EventInfo.EMPTY_ARRAY;
+ return;
+ }
+
+ final EventDef edef = file.EventDef;
+ int eventListBeg = -1;
+ int eventListEnd = edef.rows + 1;
+ for (int i = 1; i <= emap.rows; i++) {
+ emap.readRow(i);
+ if (emap.Parent == this.definingRow) {
+ eventListBeg = emap.EventList;
+ if (i < emap.rows) {
+ emap.readRow(i + 1);
+ eventListEnd = emap.EventList;
+ }
+ break;
+ }
+ }
+ if (eventListBeg < 0) {
+ this.events = EventInfo.EMPTY_ARRAY;
+ return;
+ }
+
+ final ArrayList events = new ArrayList();
+ final MethodSemantics msem = file.MethodSemantics;
+ for (int i = eventListBeg; i < eventListEnd; i++) {
+ edef.readRow(i);
+ final Type handler =
+ ((PEModule)Module).getTypeDefOrRef(edef.EventType);
+ int index =
+ Table.encodeIndex(i, Table._HasSemantics, Table.EventDef.ID);
+ MethodInfo add = null, remove = null;
+ for (int j = 1; j <= msem.rows; j++) {
+ msem.readRow(j);
+ if (msem.Association != index)
+ continue;
+ if (msem.isAddOn())
+ add = getMethod(msem.Method);
+ else if (msem.isRemoveOn())
+ remove = getMethod(msem.Method);
+ else {}
+ }
+ events.add(new PEEventInfo(i, edef.getName(),
+ (short)edef.EventFlags,
+ handler, add, remove));
+ }
+ this.events = (EventInfo[]) events
+ .toArray(EventInfo.EMPTY_ARRAY);
+ }
+
+ protected void loadNestedTypes() {
+ final ArrayList nested = new ArrayList();
+ for (int i = 1; i <= file.NestedClass.rows; i++) {
+ file.NestedClass.readRow(i);
+ if (file.NestedClass.EnclosingClass == this.definingRow)
+ nested.add(((PEModule)Module)
+ .getTypeDef(file.NestedClass.NestedClass));
+ }
+ this.nestedTypes = (Type[]) nested.toArray(Type.EmptyTypes);
+ }
+
+ protected void loadInterfaces() {
+ // get the interfaces implemented by this class
+ interfaces = Type.EmptyTypes;
+ int index = file.InterfaceImpl.findType(definingRow);
+ if (index > 0) {
+ ArrayList ifaces = new ArrayList();
+ for (int i = index; i <= file.InterfaceImpl.rows; i++) {
+ file.InterfaceImpl.readRow(i);
+ if (file.InterfaceImpl.Class != definingRow)
+ break;
+ ifaces.add(((PEModule)Module)
+ .getTypeDefOrRef(file.InterfaceImpl.Interface));
+ }
+ interfaces = (Type[]) ifaces.toArray(new Type[ifaces.size()]);
+ }
+ }
+
+ protected void loadCustomAttributes(Type attributeType) {
+ initAttributes(this, definingRow, Table.TypeDef.ID, attributeType);
+ }
+
+ private void initAttributes(CustomAttributeProvider cap, int definingRow,
+ int sourceTableId, Type attributeType)
+ {
+ ((PEModule)this.Module).initAttributes
+ (cap, definingRow, sourceTableId, attributeType);
+ }
+
+ //##########################################################################
+
+ private class PEFieldInfo extends FieldInfo {
+ private final int definingRow;
+ public PEFieldInfo(int definingRow, String name,
+ int attrs, Type fieldType, Object value)
+ {
+ super(name, PEType.this, attrs, fieldType, value);
+ this.definingRow = definingRow;
+ }
+ protected void loadCustomAttributes(Type attributeType) {
+ PEType.this.initAttributes
+ (this, definingRow, Table.FieldDef.ID, attributeType);
+ }
+ }
+
+ private class PEMethodInfo extends MethodInfo {
+ private final int definingRow;
+ public PEMethodInfo(int row, String name,
+ int attrs, Type retType, ParameterInfo[] params)
+ {
+ super(name, PEType.this, attrs, retType, params);
+ this.definingRow = row;
+ }
+ protected void loadCustomAttributes(Type attributeType) {
+ PEType.this.initAttributes
+ (this, definingRow, Table.MethodDef.ID, attributeType);
+ }
+ }
+
+ private class PEConstructorInfo extends ConstructorInfo {
+ private final int definingRow;
+ public PEConstructorInfo(int row, int attrs, ParameterInfo[] params) {
+ super(PEType.this, attrs, params);
+ this.definingRow = row;
+ }
+ protected void loadCustomAttributes(Type attributeType) {
+ PEType.this.initAttributes
+ (this, definingRow, Table.MethodDef.ID, attributeType);
+ }
+ }
+
+ private class PEPropertyInfo extends PropertyInfo {
+ private final int definingRow;
+ public PEPropertyInfo(int row, String name, short attrs, Type propType,
+ MethodInfo getter, MethodInfo setter)
+ {
+ super(name, PEType.this, attrs, propType, getter, setter);
+ this.definingRow = row;
+ }
+ protected void loadCustomAttributes(Type attributeType) {
+ PEType.this.initAttributes
+ (this, definingRow, Table.PropertyDef.ID, attributeType);
+ }
+ }
+
+ private class PEEventInfo extends EventInfo {
+ private final int definingRow;
+ public PEEventInfo(int row, String name, short attrs, Type handler,
+ MethodInfo add, MethodInfo remove)
+ {
+ super(name, PEType.this, attrs, handler, add, remove);
+ this.definingRow = row;
+ }
+ protected void loadCustomAttributes(Type attributeType) {
+ PEType.this.initAttributes
+ (this, definingRow, Table.EventDef.ID, attributeType);
+ }
+ }
+
+ //##########################################################################
+
+} // class PEType
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ParameterAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/ParameterAttributes.java
new file mode 100644
index 0000000000..7c48637d9f
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/ParameterAttributes.java
@@ -0,0 +1,73 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Defines the attributes that may be associated with a parameter.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class ParameterAttributes {
+
+ // just to make the class uninstantiable
+ private ParameterAttributes() {}
+
+ //##########################################################################
+
+ /** Specifies that there is no parameter attribute. */
+ public static final short None = 0x0000;
+
+ /** Specifies that the parameter is an input parameter. */
+ public static final short In = 0x0001;
+
+ /** Specifies that the parameter is an output parameter. */
+ public static final short Out = 0x0002;
+
+ /** Specifies that the parameter is a locale identifier. */
+ public static final short Lcid = 0x0004;
+
+ /** Specifies that the parameter is a return value. */
+ public static final short Retval = 0x0008;
+
+ /** Specifies that the parameter is optional.
+ * Attention: In the specification the value is 0x0004 but
+ * in mscorlib.dll that it Lcid and Optional is 0x0010
+ */
+ public static final short Optional = 0x0010;
+
+ /** Specifies that the parameter has a default value. */
+ public static final short HasDefault = 0x1000;
+
+ /** Specifies that the parameter has field marshaling information. */
+ public static final short HasFieldMarshal = 0x2000;
+
+ /** Reserved. */
+ public static final short Reserved3 = 0x4000;
+
+ /** Reserved. */
+ public static final short Reserved4 = (short)0x8000;
+
+ /** Specifies that the parameter is reserved. */
+ public static final short ReservedMask = (short)0xf000;
+
+ /** Reserved: shall be zero in all conforming implementations. */
+ public static final short Unused = (short) 0xcfe0;
+
+ public static final String toString(int attrs) {
+ StringBuffer s = new StringBuffer();
+ if ((attrs & In) != 0) s.append("in ");
+ if ((attrs & Out) != 0) s.append("out ");
+ if ((attrs & Optional) != 0) s.append("opt ");
+ if ((attrs & HasDefault) != 0) s.append("default(???) ");
+ if ((attrs & HasFieldMarshal) != 0) s.append("marshal(???) ");
+ return s.toString();
+ }
+
+ //##########################################################################
+
+} // class ParameterAttributes
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ParameterInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/ParameterInfo.java
new file mode 100644
index 0000000000..df3b5f96da
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/ParameterInfo.java
@@ -0,0 +1,77 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Discovers the attributes of a parameter and provides access to
+ * parameter metadata.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public class ParameterInfo extends CustomAttributeProvider {
+
+ //##########################################################################
+
+ /** Attributes of the parameter. */
+ public final short Attributes;
+
+ /** Name of the parameter. */
+ public final String Name;
+
+ /** Type of the parameter. */
+ public final Type ParameterType;
+
+ /** Position of the parameter in the parameter list. */
+ public final int Position;
+
+ //##########################################################################
+
+ /** Is this an input parameter? */
+ public final boolean IsIn() {
+ return (Attributes & ParameterAttributes.In) != 0;
+ }
+
+ /** Is this an output parameter? */
+ public final boolean IsOut() {
+ return (Attributes & ParameterAttributes.Out) != 0;
+ }
+
+ /** Is this an Lcid? */
+ public final boolean IsLcid() {
+ return (Attributes & ParameterAttributes.Lcid) != 0;
+ }
+
+ /** Is this a return value? */
+ public final boolean IsRetval() {
+ return (Attributes & ParameterAttributes.Retval) != 0;
+ }
+
+ /** Is this an optional parameter? */
+ public final boolean IsOptional() {
+ return (Attributes & ParameterAttributes.Optional) != 0;
+ }
+
+ //##########################################################################
+ // members not part of the public Reflection.ParameterInfo interface
+
+ /** Initializes a new instance of the ParameterInfo class. */
+ protected ParameterInfo(String name, Type type, int attr, int pos) {
+ Name = name;
+ ParameterType = type;
+ Attributes = (short)attr;
+ Position = pos;
+ }
+
+ public String toString() {
+ return ParameterAttributes.toString(Attributes) + ParameterType + " "
+ + Name;
+ }
+
+ //##########################################################################
+
+} // class ParameterInfo
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PropertyAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/PropertyAttributes.java
new file mode 100644
index 0000000000..ca137ba99f
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PropertyAttributes.java
@@ -0,0 +1,46 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Attributes applcicable to properties
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class PropertyAttributes {
+
+ // makes the class uninstantiable
+ private PropertyAttributes() {}
+
+ //##########################################################################
+
+ /** Specifies that the property is special, with the name describing
+ * how the property is special.
+ */
+ public static final short SpecialName = 0x0200;
+
+ /** Specifies that the metadata internal APIs check the name encoding.
+ */
+ public static final short RTSpecialName = 0x0400;
+
+ /** Specifies that the property has a default value.
+ */
+ public static final short HasDefault = 0x1000;
+
+ //##########################################################################
+
+ public static String toString(short attrs) {
+ StringBuffer str = new StringBuffer();
+ if ((attrs & SpecialName) != 0) str.append("specialname ");
+ if ((attrs & RTSpecialName) != 0) str.append("rtspecialname ");
+ return str.toString();
+ }
+
+ //##########################################################################
+
+} // class PropertyAttributes
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PropertyInfo.java b/src/msil/ch/epfl/lamp/compiler/msil/PropertyInfo.java
new file mode 100644
index 0000000000..ba3d67be2e
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PropertyInfo.java
@@ -0,0 +1,105 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Discovers the attributes of a property
+ * and provides access to property metadata.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public class PropertyInfo extends MemberInfo {
+
+ //##########################################################################
+
+ public final int MemberType() { return MemberTypes.Property; }
+
+ public final short Attributes;
+
+ public final boolean CanRead;
+
+ public final boolean CanWrite;
+
+ public final Type PropertyType;
+
+ /** Returns an array of the public get and set accessors for this property.
+ */
+ public MethodInfo[] GetAccessors() {
+ return GetAccessors(false);
+ }
+
+ /** Returns an array of the public or non-public <b>get</b>
+ * and <b>set</b> accessors for this property.
+ */
+ public MethodInfo[] GetAccessors(boolean nonPublic) {
+ MethodInfo getter = GetGetMethod(nonPublic);
+ MethodInfo setter = GetSetMethod(nonPublic);
+ if (getter == null)
+ if (setter == null) return MethodInfo.EMPTY_ARRAY;
+ else return new MethodInfo[]{setter};
+ else if (setter == null) return new MethodInfo[] {getter};
+ else return new MethodInfo[] {getter, setter};
+ }
+
+ /** Returns the public <b>get</b> accessor for this property.
+ */
+ public MethodInfo GetGetMethod() {
+ return GetGetMethod(false);
+ }
+
+ /** Returns the public or non-public <b>get</b> accessor for this property.
+ */
+ public MethodInfo GetGetMethod(boolean nonPublic) {
+ return nonPublic ? getter
+ : getter == null || getter.IsPublic() ? getter : null;
+ }
+
+ /** Returns the public <b>set</b> accessor for this property.
+ */
+ public MethodInfo GetSetMethod() {
+ return GetSetMethod(false);
+ }
+
+ /** Returns the public or non-public <b>set</b> accessor for this property.
+ */
+ public MethodInfo GetSetMethod(boolean nonPublic) {
+ return nonPublic ? setter
+ : setter == null || setter.IsPublic() ? setter : null;
+ }
+
+ public String toString() {
+ MethodInfo m = getter != null ? getter : setter;
+ return MethodAttributes.accessFlagsToString
+ ((getter != null ? getter : setter).Attributes)
+ + " " + PropertyAttributes.toString(Attributes)
+ + DeclaringType + "::" + Name;
+ }
+
+ //##########################################################################
+ // protected members
+
+ protected static final PropertyInfo[] EMPTY_ARRAY = new PropertyInfo[0];
+
+ protected MethodInfo getter;
+ protected MethodInfo setter;
+
+ protected PropertyInfo(String name, Type declType, short attr,
+ Type propType, MethodInfo getter, MethodInfo setter)
+ {
+ super(name, declType);
+ Attributes = attr;
+ PropertyType = propType;
+ this.getter = getter;
+ this.setter = setter;
+ CanRead = getter != null;
+ CanWrite = setter != null;
+ }
+
+ //##########################################################################
+
+} // class PropertyInfo
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Type.java b/src/msil/ch/epfl/lamp/compiler/msil/Type.java
new file mode 100644
index 0000000000..55125f0d96
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Type.java
@@ -0,0 +1,1042 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Arrays;
+
+/**
+ * Represents type declarations: class types, interface types, array types,
+ * value types, and enumeration types.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class Type extends MemberInfo {
+
+ //##########################################################################
+ // public static members
+
+ /** Empty array of type Type. */
+ public static final Type[] EmptyTypes = new Type[0];
+
+ /** Separates names in the namespace of the Type. */
+ public static final char Delimiter = '.';
+
+ //##########################################################################
+ // public properties
+
+ /** The fully qualified name of the Type. */
+ public final String FullName;
+
+ /** The namespace of the Type. */
+ public final String Namespace;
+
+ /** The type from which the current Type directly inherits. */
+ public final Type BaseType() {
+ initBaseType();
+ return baseType;
+ }
+ protected Type baseType;
+
+ /** The attributes associated with the Type. */
+ public final int Attributes;
+
+ /** The sssembly that the type is declared in. */
+ public final Assembly Assembly() { return Module.Assembly; }
+
+ /** The module (the EXE/DLL) in which the current Type is defined. */
+ public final Module Module;
+
+ public final int MemberType() {
+ return DeclaringType == null
+ ? MemberTypes.TypeInfo : MemberTypes.NestedType;
+ }
+
+ //##########################################################################
+ // internal members
+
+ // Fields declared by this class
+ protected FieldInfo[] fields;
+
+ // Methods declared by this class
+ protected MethodInfo[] methods;
+
+ // Constructors of this class
+ protected ConstructorInfo[] constructors;
+
+ // Properties of the class
+ protected PropertyInfo[] properties;
+
+ // Events of the class
+ protected EventInfo[] events;
+
+ // Interfaces implemented by this class
+ protected Type[] interfaces;
+
+ // Nested types declared by this class
+ protected Type[] nestedTypes;
+
+ // holds the element type of array, pointer and byref types
+ private final Type elemType;
+
+ // the underlying type of an enumeration. null if the type is not enum.
+ protected Type underlyingType;
+
+ private int auxAttr;
+
+ //##########################################################################
+ // Map with all the types known so far and operations on it
+
+ private static final Map types = new HashMap();
+
+ protected static Type getType(String name) {
+ return (Type) types.get(name);
+ }
+
+ protected static Type addType(Type t) {
+ Type oldType = (Type) types.put(t.FullName, t);
+// if (oldType != null)
+// throw new RuntimeException("The type: [" + t.Assembly + "]" + t
+// + " replaces the type: [" +
+// oldType.Assembly + "]" + oldType);
+ return t;
+ }
+
+ //##########################################################################
+
+ /** The main constructor. */
+ protected Type(Module module,
+ int attr,
+ String fullName,
+ Type baseType,
+ Type[] interfaces,
+ Type declType,
+ int auxAttr,
+ Type elemType)
+ {
+ super(fullName.lastIndexOf(Delimiter) < 0 ? fullName :
+ fullName.substring(fullName.lastIndexOf(Delimiter) + 1,
+ fullName.length()),
+ declType);
+
+ Module = module;
+ Attributes = attr;
+ this.baseType = baseType;
+ if (DeclaringType == null) {
+ FullName = fullName;
+ int i = FullName.lastIndexOf(Delimiter);
+ Namespace = (i < 0) ? "" : FullName.substring(0,i);
+ } else {
+ FullName = declType.FullName + "+" + fullName;
+ Namespace = DeclaringType.Namespace;
+ }
+
+ this.interfaces = interfaces;
+ this.elemType = elemType;
+ this.auxAttr = auxAttr;
+ }
+
+ public final boolean IsAbstract() {
+ return (Attributes & TypeAttributes.Abstract) != 0;
+
+ }
+ public final boolean IsPublic() {
+ return (Attributes & TypeAttributes.VisibilityMask)
+ == TypeAttributes.Public;
+ }
+
+ public final boolean IsNotPublic() {
+ return (Attributes & TypeAttributes.VisibilityMask)
+ == TypeAttributes.NotPublic;
+ }
+
+ public final boolean IsNestedPublic() {
+ return (Attributes & TypeAttributes.VisibilityMask)
+ == TypeAttributes.NestedPublic;
+ }
+
+ public final boolean IsNestedPrivate() {
+ return (Attributes & TypeAttributes.VisibilityMask)
+ == TypeAttributes.NestedPrivate;
+ }
+
+ public final boolean IsNestedFamily() {
+ return (Attributes & TypeAttributes.VisibilityMask)
+ == TypeAttributes.NestedFamily;
+ }
+
+ public final boolean IsNestedAssembly() {
+ return (Attributes & TypeAttributes.VisibilityMask)
+ == TypeAttributes.NestedAssembly;
+ }
+
+ public final boolean IsNestedFamORAssem() {
+ return (Attributes & TypeAttributes.VisibilityMask)
+ == TypeAttributes.NestedFamORAssem;
+ }
+
+ public final boolean IsNestedFamANDAssem() {
+ return (Attributes & TypeAttributes.VisibilityMask)
+ == TypeAttributes.NestedFamANDAssem;
+ }
+
+ public final boolean IsSealed() {
+ return (Attributes & TypeAttributes.Sealed) != 0;
+ }
+
+ public final boolean IsSpecialName() {
+ return (Attributes & TypeAttributes.SpecialName) != 0;
+ }
+
+ public final boolean IsClass() {
+ return (Attributes & TypeAttributes.ClassSemanticsMask)
+ == TypeAttributes.Class;
+ }
+
+ public final boolean IsInterface(){
+ return (Attributes & TypeAttributes.ClassSemanticsMask)
+ == TypeAttributes.Interface;
+ }
+
+ public final boolean IsAutoLayout() {
+ return (Attributes & TypeAttributes.LayoutMask)
+ == TypeAttributes.AutoLayout;
+ }
+ public final boolean IsExplictitLayout() {
+ return (Attributes & TypeAttributes.LayoutMask)
+ == TypeAttributes.ExplicitLayout;
+ }
+ public final boolean IsLayoutSequential() {
+ return (Attributes & TypeAttributes.LayoutMask)
+ == TypeAttributes.SequentialLayout;
+ }
+
+ public final boolean IsImport() {
+ return (Attributes & TypeAttributes.Import) != 0;
+ }
+ public final boolean IsSerializable() {
+ return (Attributes & TypeAttributes.Serializable) != 0;
+ }
+
+ public final boolean IsAnsiClass() {
+ return (Attributes & TypeAttributes.StringFormatMask)
+ == TypeAttributes.AnsiClass;
+ }
+
+ public final boolean IsUnicodeClass() {
+ return (Attributes & TypeAttributes.StringFormatMask)
+ == TypeAttributes.UnicodeClass;
+ }
+ public final boolean IsAutoClass() {
+ return (Attributes & TypeAttributes.StringFormatMask)
+ == TypeAttributes.AutoClass;
+ }
+
+ public final boolean IsArray() {
+ return (auxAttr & AuxAttr.Array) != 0;
+ }
+ public final boolean IsByRef() {
+ return (auxAttr & AuxAttr.ByRef) != 0;
+ }
+ public final boolean IsPointer() {
+ return (auxAttr & AuxAttr.Pointer) != 0;
+ }
+ public final boolean IsPrimitive() {
+ return (auxAttr & AuxAttr.Primitive) != 0;
+ }
+ public final boolean IsValueType() {
+ return BaseType() == VALUE_TYPE() || IsEnum();
+ }
+ public final boolean IsEnum() {
+ return BaseType() == ENUM();
+ }
+
+ public final boolean HasElementType() {
+ return IsArray() || IsPointer() || IsByRef();
+ }
+
+ //public final boolean IsCOMObject;
+ //public final boolean IsContextful;
+ //public final boolean IsMarshalByRef;
+
+ protected Type(Module module,
+ int attr,
+ String fullName,
+ Type baseType,
+ Type[] interfaces,
+ Type declType,
+ int auxAttr)
+ {
+ this(module, attr, fullName, baseType, interfaces,
+ declType, auxAttr, null);
+ }
+
+ //##########################################################################
+
+ static final class PrimitiveType extends Type {
+ public PrimitiveType(Module module,
+ int attributes,
+ String fullName,
+ Type baseType,
+ Type[] interfaces,
+ Type declType,
+ int auxAttr,
+ Type elemType)
+ {
+ super(module, attributes, fullName,
+ baseType, interfaces, declType, auxAttr, elemType);
+ }
+ }
+
+ protected static final class AuxAttr {
+ public static final int None = 0x0000;
+ public static final int Array = 0x0001;
+ public static final int ByRef = 0x0002;
+ public static final int Pointer = 0x0008;
+ public static final int Primitive = 0x0010;
+ }
+
+ /***/
+ public static Type mkArray(Type elemType, int rank) {
+ StringBuffer arrSig = new StringBuffer("[");
+ for (int i = 0; i < rank; i++) {
+ if (i > 0) arrSig.append(',');
+ }
+ arrSig.append(']');
+ Type array = getType(elemType.FullName + arrSig);
+ if (array != null)
+ return array;
+ array = new PrimitiveType(elemType.Module,
+ TypeAttributes.Public
+ | TypeAttributes.Sealed
+ | TypeAttributes.Serializable,
+ elemType.FullName + arrSig,
+ ARRAY(), EmptyTypes, null,
+ AuxAttr.Array, elemType);
+ return addType(array);
+ }
+
+ /***/
+ public static Type mkPtr(Type elemType) {
+ String name = elemType.FullName + "*";
+ Type type = getType(name);
+ if (type != null) return type;
+ type = new PrimitiveType(elemType.Module,
+ TypeAttributes.NotPublic,
+ name, null, EmptyTypes, null,
+ AuxAttr.Pointer, elemType);
+ return addType(type);
+ }
+
+ //##########################################################################
+ // public methods
+
+ /**
+ * Return the type with the specified signature parameters.
+ * For example, the fully qualified name for a class might look like this:
+ * TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly
+ */
+ public static Type GetType(String fullName) {
+ Type type = getType(fullName);
+ if (type != null) return type;
+
+ // check if it's an array type; TODO: make array type handling more robust
+ int i = fullName.lastIndexOf('[');
+ int j = fullName.lastIndexOf(']');
+ if (i >= 0)
+ if (j > i && j == (fullName.length() - 1)) {
+ String elementTypeName = fullName.substring(0, i);
+ Type elementType = GetType(elementTypeName);
+ if (elementType == null)
+ throw new RuntimeException
+ ("Unknown element type '" + elementTypeName +
+ "' for the array type: " + fullName);
+ int rank = j - i;
+ for (int k = i + 1; k < j; k++) {
+ if (fullName.charAt(k) != ',')
+ throw new RuntimeException
+ ("Malformed type name: " + fullName);
+ }
+ return mkArray(elementType, rank);
+ } else
+ throw new RuntimeException("Malformed type name: " + fullName);
+
+ // check if it's a pointer type
+ if (fullName.charAt(fullName.length() - 1) == '*')
+ return addType
+ (mkPtr(GetType(fullName.substring(0, fullName.length()-1))));
+
+ // check if it's a nested class
+ i = fullName.lastIndexOf('+');
+ if (i > 0) {
+ if (i == 0 || i == (fullName.length() - 1))
+ throw new RuntimeException("malformedTypeName");
+ Type enclosing = GetType(fullName.substring(0, i));
+ return enclosing == null ? null
+ : enclosing.GetNestedType(fullName.substring(i + 1));
+ }
+
+ //System.out.println("Looking for type: " + fullName + " (" + fullName.length() + ")");
+ // try in the assemblies
+ Iterator assems = ch.epfl.lamp.compiler.msil.Assembly.
+ assemblies.values().iterator();
+ while (type == null && assems.hasNext()) {
+ Assembly assem = ((Assembly) assems.next());
+ type = assem.GetType(fullName);
+ //System.out.println("\tin assemby " + assem + " -> " + type);
+ }
+
+ Type type2 = getType(fullName);
+ if (type == type2) return type;
+ return type == null ? null : addType(type);
+ }
+
+ /**
+ * @return the type of the object encompassed or referenced to
+ * by the current array, pointer or reference type.
+ */
+ public Type GetElementType() {
+ return elemType;
+ }
+
+ /**
+ * @return the type underlying an enumeration type.
+ */
+ public Type getUnderlyingType() {
+ if (!IsEnum()) return null;
+ // this would force the loading of the underlying type from the
+ // the type of the value__ field of the enumeration
+ initFields();
+ return underlyingType;
+ }
+
+ //##########################################################################
+ // GetField/s/
+
+ /** Searches for the field with the specified name. */
+ public FieldInfo GetField(String name) {
+ initFields();
+ for (int i = 0; i < fields.length; i++)
+ if (fields[i].Name.equals(name) && !fields[i].IsPrivate())
+ return fields[i];
+ return null;
+ }
+
+ /**
+ */
+ public FieldInfo GetField(String name, int bindingFlags) {
+ FieldInfo[] fields = this.GetFields(bindingFlags);
+ for (int i = 0; i < fields.length; i++)
+ if (name.equals(fields[i].Name))
+ return fields[i];
+ return null;
+ }
+
+ /** Gets the fields of the current Type. */
+ public FieldInfo[] GetFields() {
+ return GetFields(BindingFlags.Instance | BindingFlags.Public);
+ }
+
+ /**
+ */
+ public FieldInfo[] GetFields(int bindingFlags) {
+ initFields();
+ final FieldInfo[] fields =
+ getAllFields((bindingFlags & BindingFlags.DeclaredOnly) != 0);
+ final boolean getInstance = (bindingFlags & BindingFlags.Instance) != 0;
+ final boolean getStatic = (bindingFlags & BindingFlags.Static) != 0;
+ final boolean getPublic = (bindingFlags & BindingFlags.Public) != 0;
+ final boolean getNonPublic =
+ (bindingFlags & BindingFlags.NonPublic) != 0;
+
+ int cnt = 0;
+ for (int i = 0; i < fields.length; i++) {
+ FieldInfo field = fields[i];
+ boolean accessible = (getPublic && field.IsPublic())
+ || (getNonPublic && !field.IsPublic());
+ if (accessible
+ // strip off the private fields up the hierarchy
+ && ((field.DeclaringType == this)
+ || ((field.DeclaringType != this) && !field.IsPrivate()))
+ && ((getInstance && !field.IsStatic())
+ || ((getStatic && field.IsStatic()) &&
+ (field.DeclaringType == this
+ || (bindingFlags & BindingFlags.FlattenHierarchy) != 0))
+ )
+ )
+ fields[cnt++] = field;
+ }
+ FieldInfo [] resFields = new FieldInfo[cnt];
+ System.arraycopy(fields, 0, resFields, 0, cnt);
+ return resFields;
+ }
+
+ protected FieldInfo[] getAllFields(boolean declaredOnly) {
+ initFields();
+ FieldInfo [] inherited = BaseType() == null || declaredOnly
+ ? FieldInfo.EMPTY_ARRAY
+ : BaseType().getAllFields(declaredOnly);
+ FieldInfo[] allFields =
+ new FieldInfo[inherited.length + this.fields.length];
+ System.arraycopy(inherited, 0, allFields, 0, inherited.length);
+ System.arraycopy(this.fields, 0,
+ allFields, inherited.length, this.fields.length);
+ return allFields;
+ }
+
+ //##########################################################################
+ // GetConstructor/s/
+
+ /** Searches for a public instance constructor whose parameters
+ * match the types in the specified array. */
+ public ConstructorInfo GetConstructor(Type[] paramTypes) {
+ initMethods();
+ for (int i = 0; i < constructors.length; i++) {
+ if (equalParameters(constructors[i].GetParameters(), paramTypes))
+ return constructors[i];
+ }
+ return null;
+ }
+
+ /** Returns all public instance constructors defined for the current Type.*/
+ public ConstructorInfo[] GetConstructors() {
+ return GetConstructors(BindingFlags.Instance | BindingFlags.Public);
+ }
+
+ /***/
+ public ConstructorInfo[] GetConstructors(int bindingFlags) {
+ initMethods();
+ final boolean getInstance = (bindingFlags & BindingFlags.Instance) != 0;
+ final boolean getStatic = (bindingFlags & BindingFlags.Static) != 0;
+ final boolean getPublic = (bindingFlags & BindingFlags.Public) != 0;
+ final boolean getNonPublic =
+ (bindingFlags & BindingFlags.NonPublic) != 0;
+
+ ConstructorInfo[] constrs =
+ new ConstructorInfo[this.constructors.length];
+ int cnt = 0;
+ for (int i = 0; i < this.constructors.length; i++) {
+ ConstructorInfo constr = this.constructors[i];
+ boolean accessible = (getPublic && constr.IsPublic())
+ || (getNonPublic && !constr.IsPublic());
+ if (accessible
+ && ((getInstance && !constr.IsStatic())
+ || (getStatic && constr.IsStatic())))
+ constrs[cnt++] = constr;
+ }
+ ConstructorInfo [] resConstrs = new ConstructorInfo[cnt];
+ System.arraycopy(constrs, 0, resConstrs, 0, cnt);
+ return resConstrs;
+ }
+
+ //##########################################################################
+ // GetMethod/s/
+
+ /** Searches for the specified public method whose parameters
+ * match the specified argument types. */
+ public MethodInfo GetMethod(String name, Type[] paramTypes) {
+ return GetMethod(name, paramTypes, null);
+ }
+
+ public MethodInfo GetMethod(String name, Type[] paramTypes, Type retType) {
+ initMethods();
+ MethodInfo method = findMethod(methods, name, paramTypes, retType);
+ if (method != null)
+ return method;
+ if (BaseType() != null) {
+ method = BaseType().GetMethod(name, paramTypes, retType);
+ if (method != null)
+ return method;
+ }
+// StringBuffer str = new StringBuffer(name);
+// str.append('(');
+// for (int i = 0; i < paramTypes.length; i++) {
+// if (i > 0) str.append(", ");
+// str.append(paramTypes[i]);
+// }
+// str.append(')');
+// System.out.println("Cannot find method " + str + ":");
+// System.out.println("Methods of class " + this);
+// for (int i = 0; i < methods.length; i++)
+// System.out.println("\t" + methods[i]);
+ return null;
+ }
+
+ /**
+ */
+ protected static MethodInfo findMethod(MethodInfo[] methods,
+ String name,
+ Type[] paramTypes,
+ Type retType)
+ {
+ for (int i = 0; i < methods.length; i++)
+ if (name.equals(methods[i].Name)
+ && equalParameters(methods[i].GetParameters(), paramTypes)
+ && (retType == null || methods[i].ReturnType == retType))
+ return methods[i];
+ return null;
+ }
+
+ /**
+ */
+ protected static boolean equalParameters(ParameterInfo[] params,
+ Type[] paramTypes)
+ {
+ if (params.length != paramTypes.length)
+ return false;
+ for (int i = 0; i < params.length; i++) {
+// System.out.println(params[i].ParameterType + " == " + paramTypes[i]
+// + " = " + (params[i].ParameterType == paramTypes[i]));
+ if (params[i].ParameterType != paramTypes[i])
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ */
+ public MethodInfo GetMethod(String name, Type[] paramTypes, int bindingFlags) {
+ MethodInfo[] methods = GetMethods(bindingFlags);
+ MethodInfo method = findMethod(methods, name, paramTypes, null);
+ if (method == null) {
+ StringBuffer str = new StringBuffer(name);
+ str.append('(');
+ for (int i = 0; i < paramTypes.length; i++) {
+ if (i > 0) str.append(", ");
+ str.append(paramTypes[i]);
+ }
+ str.append(')');
+ System.out.println("Cannot find method " + str + ":");
+ System.out.println("Methods of class " + this);
+ for (int i = 0; i < methods.length; i++)
+ System.out.println("\t" + methods[i]);
+ }
+ return method;
+ }
+
+ /** Returns all public methods of the current Type. */
+ public MethodInfo[] GetMethods() {
+ return GetMethods(BindingFlags.Instance | BindingFlags.Public);
+ }
+
+ /**
+ */
+ public MethodInfo[] GetMethods(int bindingFlags) {
+ initMethods();
+ final MethodInfo[] methods =
+ getAllMethods((bindingFlags & BindingFlags.DeclaredOnly) != 0);
+ //System.out.println("" + this + ".GetMethods(int) -> " + methods.length);
+ final boolean getInstance = (bindingFlags & BindingFlags.Instance) != 0;
+ final boolean getStatic = (bindingFlags & BindingFlags.Static) != 0;
+ final boolean getPublic = (bindingFlags & BindingFlags.Public) != 0;
+ final boolean getNonPublic =
+ (bindingFlags & BindingFlags.NonPublic) != 0;
+
+ int cnt = 0;
+ for (int i = 0; i < methods.length; i++) {
+ MethodInfo method = methods[i];
+ boolean accessible = (getPublic && method.IsPublic())
+ || (getNonPublic && !method.IsPublic());
+ if (accessible
+ // strip off the private methods up the hierarchy
+ && ((method.DeclaringType == this)
+ || ((method.DeclaringType != this) && !method.IsPrivate()))
+ && ((getInstance && !method.IsStatic())
+ || ((getStatic && method.IsStatic()) &&
+ (method.DeclaringType == this
+ || (bindingFlags & BindingFlags.FlattenHierarchy) != 0))
+ )
+ )
+ methods[cnt++] = method;
+ }
+ MethodInfo [] resMethods = new MethodInfo[cnt];
+ System.arraycopy(methods, 0, resMethods, 0, cnt);
+ return resMethods;
+ }
+
+ protected MethodInfo[] getAllMethods(boolean declaredOnly) {
+ initMethods();
+ MethodInfo[] inherited = BaseType() == null || declaredOnly
+ ? MethodInfo.EMPTY_ARRAY
+ : BaseType().getAllMethods(declaredOnly);
+ MethodInfo[] allMethods =
+ new MethodInfo[inherited.length + this.methods.length];
+ System.arraycopy(inherited, 0, allMethods, 0, inherited.length);
+ System.arraycopy(this.methods, 0,
+ allMethods, inherited.length, this.methods.length);
+ return allMethods;
+ }
+
+ //##########################################################################
+ // GetProperty/ies/
+
+ /** Returns all public properties of the current Type.
+ */
+ public PropertyInfo[] GetProperties() {
+ initProperties();
+ return (PropertyInfo[]) properties.clone();
+ }
+
+ /** Returns the properties of the current class
+ * that satisfy the binding constrints.
+ */
+ public PropertyInfo[] GetProperties(int bindingFlags) {
+ initProperties();
+ return (PropertyInfo[]) properties.clone();
+ }
+
+ /** Returns the public property with the given name.
+ */
+ public PropertyInfo GetProperty(String name) {
+ initProperties();
+ for (int i = 0; i < properties.length; i++)
+ if (name.equals(properties[i].Name))
+ return properties[i];
+ return null;
+ }
+
+ /** Returns the property with the given name
+ * that satisfies the binding constraints.
+ */
+ public PropertyInfo GetProperty(String name, int bindingFlags) {
+ throw new RuntimeException("Method not implemented yet");
+ }
+
+ //##########################################################################
+ // GetEvent(s)
+
+ public EventInfo[] GetEvents() {
+ initEvents();
+ return (EventInfo[]) events.clone();
+ }
+
+ //##########################################################################
+ // GetNestedType/s/
+
+ /** Searches for nested type with the specified name. */
+ public Type GetNestedType(String name) {
+ initNestedTypes();
+ for (int i = 0; i < nestedTypes.length; i++)
+ if (nestedTypes[i].Name.equals(name))
+ return nestedTypes[i];
+ return null;
+ }
+
+ /** Returns all types nested within the current Type. */
+ public Type[] GetNestedTypes() {
+ initNestedTypes();
+ return (Type[]) nestedTypes.clone();
+ }
+
+ //##########################################################################
+ // GetInterface/s/
+
+ /** Searches for an Interface with the given name implemented by this type
+ */
+ public Type GetInterface(String name) {
+ return GetInterface(name, false);
+ }
+
+ /** Searches for the specified interface,
+ * specifying whether to do a case-sensitive search.
+ * @param name - the name of the interface to get
+ * @param ignoreCase <b>true</b> to perform a case-insensitive search for name
+ * <b>false</b> to perform a case-sensitive search for name
+ * @return A Type object representing the interface with the specified name,
+ * implemented or inherited by the current Type, if found;
+ * otherwise, a null reference
+ */
+ public Type GetInterface(String name, boolean ignoreCase) {
+ initInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ Type iface = interfaces[i];
+ if (ignoreCase) {
+ if (name.equalsIgnoreCase(iface.Name)) return iface;
+ if (name.equalsIgnoreCase(iface.FullName)) return iface;
+ } else {
+ if (name.equals(iface.Name)) return iface;
+ if (name.equals(iface.FullName)) return iface;
+ }
+ }
+ return BaseType() == null ? null
+ : BaseType().GetInterface(name, ignoreCase);
+ }
+
+ /** Returns the interfaces implemented or inherited by the current Type. */
+ public Type[] GetInterfaces() {
+ initInterfaces();
+ if (BaseType() == null) return interfaces;
+
+ Type[] ifaces = interfaces;
+ int count = 0;
+ for (int i = 0; i < interfaces.length; i++) {
+ if (BaseType().GetInterface(interfaces[i].FullName) == null)
+ ifaces[count++] = ifaces[i];
+ }
+ Type[] baseTypeIfaces = BaseType().GetInterfaces();
+
+ Type[] res = new Type[baseTypeIfaces.length + count];
+ System.arraycopy(baseTypeIfaces, 0, res, 0, baseTypeIfaces.length);
+ System.arraycopy(ifaces, 0, res, baseTypeIfaces.length, count);
+
+ return res;
+ }
+
+
+ public boolean isSubtypeOf(Type that) {
+ if (this == that || BaseType() == that || that == OBJECT()) return true;
+ initInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ if (interfaces[i].isSubtypeOf(that))
+ return true;
+ boolean res = BaseType() == null ? false : BaseType().isSubtypeOf(that);
+// if (!res) {
+// System.out.println(dumpType(this) + " not a subtype of " +
+// dumpType(that));
+// }
+ return res;
+ }
+
+ private static String formatType(Type t) {
+ if (t == null) return "<null>";
+ String cname = t.getClass().getName();
+ int k = cname.lastIndexOf(".");
+ if (k >= 0)
+ cname = cname.substring(k + 1);
+ return "[" + t.Assembly().GetName() + "]" + t +
+ "(" + cname + "#" + Integer.toHexString(t.hashCode()) + ")";
+ }
+ private static String dumpType(Type t) {
+ StringBuffer str = new StringBuffer();
+ str.append(formatType(t) + " : ");
+ str.append(formatType(t.BaseType()));
+ Type[] ifaces = t.GetInterfaces();
+ for (int i = 0; i < ifaces.length; i++)
+ str.append(", " + formatType(ifaces[i]));
+ return str.toString();
+ }
+
+ //##########################################################################
+ // GetMember/s/
+
+ protected MemberInfo[] members;
+
+ public MemberInfo[] GetMember(String name) {
+ aggregateMembers();
+ List l = new ArrayList();
+ for (int i = 0; i < members.length; i++) {
+ if (name.equals(members[i].Name))
+ l.add(members[i]);
+ }
+ return (MemberInfo[])l.toArray(MemberInfo.EMPTY_ARRAY);
+ }
+
+ protected void aggregateMembers() {
+ if (members != null)
+ return;
+ initFields();
+ initMethods();
+ initProperties();
+ initNestedTypes();
+ // the List returned by Arrays.asList doesn't support the addAll method
+ // so we have to wrap it in ArrayList
+ List l = new ArrayList(Arrays.asList(fields));
+ l.addAll(Arrays.asList(constructors));
+ l.addAll(Arrays.asList(methods));
+ l.addAll(Arrays.asList(properties));
+ l.addAll(Arrays.asList(nestedTypes));
+ members = (MemberInfo[]) l.toArray(MemberInfo.EMPTY_ARRAY);
+ }
+
+ //##########################################################################
+ // non-standard methods that return only members declared in this type
+
+ /**
+ * Return only the fields declared in this type.
+ */
+ public FieldInfo[] getFields() {
+ initFields();
+ FieldInfo[] fields = new FieldInfo[this.fields.length];
+ System.arraycopy(this.fields, 0, fields, 0, fields.length);
+ return fields;
+ }
+
+ /**
+ * Return only the conrtuctors declared in this type.
+ */
+ public ConstructorInfo[] getConstructors() {
+ initMethods();
+ ConstructorInfo[] ctors = new ConstructorInfo[constructors.length];
+ System.arraycopy(constructors, 0, ctors, 0, ctors.length);
+ return ctors;
+ }
+
+ /**
+ * Return only the methods declared in this type.
+ */
+ public MethodInfo[] getMethods() {
+ initMethods();
+ MethodInfo[] methods = new MethodInfo[this.methods.length];
+ System.arraycopy(this.methods, 0, methods, 0, methods.length);
+ return methods;
+ }
+
+ /**
+ * Return only the properties declared in this type.
+ */
+ public PropertyInfo[] getProperties() {
+ initProperties();
+ PropertyInfo[] props = new PropertyInfo[properties.length];
+ System.arraycopy(properties, 0, props, 0, props.length);
+ return props;
+ }
+
+ /**
+ * Return only the interfaces directly implemented by this type.
+ */
+ public Type[] getInterfaces() {
+ initInterfaces();
+ Type[] ifaces = new Type[interfaces.length];
+ System.arraycopy(interfaces, 0, ifaces, 0, ifaces.length);
+ return ifaces;
+ }
+
+ /**
+ * Return the types declared in this type.
+ */
+ public Type[] getNestedTypes() {
+ initNestedTypes();
+ Type[] nested = new Type[nestedTypes.length];
+ System.arraycopy(nestedTypes, 0, nested, 0, nested.length);
+ return nested;
+ }
+
+ //##########################################################################
+
+ public String toString() {
+ return FullName;
+ }
+
+ //##########################################################################
+ // lazy type construction members
+
+ private boolean initBaseType = true;
+ protected final void initBaseType() {
+ if (initBaseType) {
+ loadBaseType();
+ initBaseType = false;
+ }
+ }
+ protected void loadBaseType() {}
+
+ private boolean initInterfaces = true;
+ protected void initInterfaces() {
+ if (initInterfaces) {
+ loadInterfaces();
+ initInterfaces = false;
+ }
+ assert interfaces != null : "In type " + this;
+ }
+ protected void loadInterfaces() {}
+
+ private boolean initNestedTypes = true;
+ protected void initNestedTypes() {
+ if (initNestedTypes) {
+ loadNestedTypes();
+ initNestedTypes = false;
+ }
+ assert nestedTypes != null : "In type " + this;
+ }
+ protected void loadNestedTypes() {}
+
+ private boolean initFields = true;
+ protected void initFields() {
+ if (initFields) {
+ loadFields();
+ initFields = false;
+ }
+ assert fields != null : "In type " + this;
+ }
+ protected void loadFields() {}
+
+ private boolean initMethods = true;
+ protected void initMethods() {
+ if (initMethods) {
+ loadMethods();
+ initMethods = false;
+ }
+ assert constructors != null : "In type " + this;
+ assert methods != null : "In type " + this;
+ }
+ protected void loadMethods() {}
+
+ private boolean initProperties = true;
+ protected void initProperties() {
+ if (initProperties) {
+ initMethods();
+ loadProperties();
+ initProperties = false;
+ }
+ assert properties != null : "In type " + this;
+ }
+ protected void loadProperties() {}
+
+ private boolean initEvents = true;
+ protected void initEvents() {
+ if (initEvents) {
+ initMethods();
+ loadEvents();
+ initEvents = false;
+ }
+ assert events != null : "In type " + this;
+ }
+ protected void loadEvents() {}
+
+ //##########################################################################
+
+ //##########################################################################
+ // static members
+
+ private static Assembly MSCORLIB;
+ private static Module MSCORLIB_DLL;
+
+ public static Type OBJECT() { return __OBJECT; }
+ public static Type STRING() { return __STRING; }
+ public static Type ARRAY() { return __ARRAY; }
+ public static Type VOID() { return __VOID; }
+ public static Type ENUM() { return __ENUM; }
+ public static Type VALUE_TYPE() { return __VALUE_TYPE; }
+
+ private static Type __OBJECT;
+ private static Type __STRING;
+ private static Type __ARRAY;
+ private static Type __VOID;
+ private static Type __ENUM;
+ private static Type __VALUE_TYPE;
+
+ public static void initMSCORLIB(Assembly mscorlib) {
+ if (MSCORLIB != null)
+ throw new RuntimeException("mscorlib already initialized");
+ MSCORLIB = mscorlib;
+ MSCORLIB_DLL = MSCORLIB.GetModules()[0];
+
+ __OBJECT = mscorlib.GetType("System.Object");
+ __STRING = mscorlib.GetType("System.String");
+ __ARRAY = mscorlib.GetType("System.Array");
+ __VOID = mscorlib.GetType("System.Void");
+ __ENUM = mscorlib.GetType("System.Enum");
+ __VALUE_TYPE = mscorlib.GetType("System.ValueType");
+ }
+
+ //##########################################################################
+
+} // class Type
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/TypeAttributes.java b/src/msil/ch/epfl/lamp/compiler/msil/TypeAttributes.java
new file mode 100644
index 0000000000..45ef487e24
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/TypeAttributes.java
@@ -0,0 +1,191 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+/**
+ * Specifies type attributes.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class TypeAttributes {
+
+ //##########################################################################
+ // Visibilty attributes
+
+ /** Bitmask used to retrieve visibility information. */
+ public static final int VisibilityMask = 0x00000007;
+
+ /** Class has no public scope. */
+ public static final int NotPublic = 0x00000000;
+
+ /** Class has public scope. */
+ public static final int Public = 0x00000001;
+
+ /** Class is nested with public visibility. */
+ public static final int NestedPublic = 0x00000002;
+
+ /** Class is nested with private visibility. */
+ public static final int NestedPrivate = 0x00000003;
+
+ /** Class is nested with family visibility, and is thus accessible
+ * only by methods within its own type and any subtypes. */
+ public static final int NestedFamily = 0x00000004;
+
+ /** Class is nested with assembly visibility, and is thus accessible
+ * only by methods within its assembly. */
+ public static final int NestedAssembly = 0x00000005;
+
+ /** Class is nested with assembly and family visibility, and is thus accessible
+ * only by methods lying in the intersection of its family and assembly. */
+ public static final int NestedFamANDAssem = 0x00000006;
+
+ /** Class is nested with family or assembly visibility, and is thus accessible
+ * only by methods lying in the union of its family and assembly. */
+ public static final int NestedFamORAssem = 0x00000007;
+
+ //##########################################################################
+ // Class layout attributes
+
+ /** Bitmask used to retrieve class layout information. */
+ public static final int LayoutMask = 0x00000018;
+
+ /** Class fields are automatically laid out by the CLR. */
+ public static final int AutoLayout = 0x00000000;
+
+ /** Class fields are laid out sequentially, in the order that the fields
+ * were emitted to the metadata. */
+ public static final int SequentialLayout = 0x00000008;
+
+ /** Class fields are laid out at the specified offsets. */
+ public static final int ExplicitLayout = 0x00000010;
+
+ //##########################################################################
+ // Class semantics attributes
+
+ /** Bitmask used to retrieve class semantics information. */
+ public static final int ClassSemanticsMask = 0x00000020;
+
+ /** Type is a class. */
+ public static final int Class = 0x00000000;
+
+ /** Type is an interface. */
+ public static final int Interface = 0x00000020;
+
+ //##########################################################################
+ // Special semantics in addition to class semantics
+
+ /** Class is abstract. */
+ public static final int Abstract = 0x00000080;
+
+ /** Class is cannot be extended. */
+ public static final int Sealed = 0x00000100;
+
+ /** Class is special in a way denoted by the name. */
+ public static final int SpecialName = 0x00000400;
+
+ //##########################################################################
+ // Implementation attributes
+
+ /** Class/interface is imported from another module. */
+ public static final int Import = 0x00001000;
+
+ /** Class can be serialized. */
+ public static final int Serializable = 0x00002000;
+
+ //##########################################################################
+ // String formatting attributes
+
+ /** Bitmask used to retrieve string information for native interop. */
+ public static final int StringFormatMask = 0x00030000;
+
+ /** LPTSTR is interpreted as ANSI. */
+ public static final int AnsiClass = 0x00000000;
+
+ /** LPTSTR is interpreted as UNICODE. */
+ public static final int UnicodeClass = 0x00010000;
+
+ /** LPTSTR is interpreted automatically. */
+ public static final int AutoClass = 0x00020000;
+
+ //##########################################################################
+ // Class initialization attributes
+
+ /** Initialize the class before first static field access. */
+ public static final int BeforeFieldInit = 0x00100000;
+
+ //##########################################################################
+ // Additional flags
+
+ /** CLI provides 'special' behavior, depending upon the name of the type. */
+ public static final int RTSpecialName = 0x00000800;
+
+ /** Type has security associate with it. */
+ public static final int HasSecurity = 0x00040000;
+
+ //##########################################################################
+
+ public static String accessModsToString(int attrs) {
+ switch (attrs & VisibilityMask) {
+ case NotPublic: return "private";
+ case Public: return "public";
+ case NestedPublic: return "nested public";
+ case NestedPrivate: return "nested private";
+ case NestedFamily: return "nested family";
+ case NestedAssembly: return "nested assembly";
+ case NestedFamANDAssem: return "nested famandassem";
+ case NestedFamORAssem: return "nested famorassem";
+ default:
+ throw new RuntimeException();
+ }
+ }
+
+ /** Returns a string representation of the given attributes. */
+ public static String toString(int attrs) {
+ StringBuffer str = new StringBuffer(accessModsToString(attrs));
+ switch (attrs & LayoutMask) {
+ case AutoLayout: str.append(" auto"); break;
+ case SequentialLayout: str.append(" sequential"); break;
+ case ExplicitLayout: str.append(" explicit"); break;
+ }
+ switch (attrs & StringFormatMask) {
+ case AnsiClass: str.append(" ansi"); break;
+ case UnicodeClass: str.append(" unicode"); break;
+ case AutoClass: str.append(" autochar"); break;
+ }
+ if ((attrs & Interface) != 0) str.append(" interface");
+ if ((attrs & Abstract) != 0) str.append(" abstract");
+ if ((attrs & Sealed) != 0) str.append(" sealed");
+ if ((attrs & BeforeFieldInit) != 0) str.append(" beforefieldinit");
+ if ((attrs & Serializable) != 0) str.append(" serializable");
+ if ((attrs & SpecialName) != 0) str.append(" specialname");
+ if ((attrs & RTSpecialName) != 0) str.append(" rtspecialname");
+ return str.toString();
+ }
+
+ /***/
+ public static final boolean isNested(int attrs) {
+ switch (attrs & VisibilityMask) {
+ case NestedPublic:
+ case NestedPrivate:
+ case NestedFamily:
+ case NestedAssembly:
+ case NestedFamANDAssem:
+ case NestedFamORAssem:
+ return true;
+ default: return false;
+ }
+ }
+
+ //##########################################################################
+
+ // makes the class uninstantiable
+ private TypeAttributes() {}
+
+ //##########################################################################
+
+} // class TypeAttributes
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Version.java b/src/msil/ch/epfl/lamp/compiler/msil/Version.java
new file mode 100644
index 0000000000..7276498258
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Version.java
@@ -0,0 +1,72 @@
+/*
+ * System.Reflection-like API for access to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil;
+
+
+/**
+ * Represents the version number for a common language runtime assembly
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class Version {
+
+ //##########################################################################
+ // public interface
+
+ /**
+ * Gets the value of the major component of the version
+ * number for this instance.
+ */
+ public final int Major;
+
+ /**
+ * Gets the value of the minor component of the version
+ * number for this instance.
+ */
+ public final int Minor;
+
+ /**
+ * Gets the value of the build component of the version
+ * number for this instance.
+ */
+ public final int Build;
+
+ /**
+ * Gets the value of the revision component of the version
+ * number for this instance.
+ */
+ public final int Revision;
+
+ /**
+ * Initializes a new instance of the Version class.
+ */
+ public Version() {
+ this(0,0,0,0);
+ }
+
+ /**
+ * Initializes a new instance of the Version class with
+ * the specified major, minor, build, and revision numbers.
+ */
+ public Version(int major, int minor, int build, int revision) {
+ this.Major = major;
+ this.Minor = minor;
+ this.Build = build;
+ this.Revision = revision;
+ }
+
+ /**
+ * Converts the value of this instance to its equivalent String representation
+ */
+ public String toString() {
+ return "" + Major + "." + Minor + "." + Build + "." + Revision;
+ }
+
+ //##########################################################################
+
+} // class Version
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala
new file mode 100644
index 0000000000..674c52d6df
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala
@@ -0,0 +1,125 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: AssemblyBuilder.java 14755 2008-04-22 08:13:32Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil._
+import java.util.HashMap
+import java.util.HashSet
+import java.util.ArrayList
+import java.io.IOException
+
+/**
+ * Defines and represents a dynamic assembly.
+ * A dynamic assembly is an assembly that is created using the compiler.msil
+ * emit APIs. The dynamic modules in the assembly are saved when the dynamic
+ * assembly is saved using the Save method. To generate an executable, the
+ * SetEntryPoint method must be called to identify the method that is the
+ * entry point to the assembly. Assemblies are saved as DLL by default,
+ * unless SetEntryPoint requests the generation of a console application
+ * or a Windows-based application.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class AssemblyBuilder(name: AssemblyName)
+ extends Assembly(name)
+ with ICustomAttributeSetter
+ with Visitable
+{
+ //##########################################################################
+ // public methods
+
+ /**
+ * Defines a dynamic module with the given name that will be saved
+ * to the specified file. No symbol information is emitted.
+ */
+ def DefineDynamicModule(name: String, fileName: String): ModuleBuilder = {
+ val module = new ModuleBuilder(name, fileName, "" + null, this)
+ addModule(name, module)
+ return module
+ }
+
+ /** Returns the dynamic module with the specified name. */
+ def GetDynamicModule(name: String): ModuleBuilder = {
+ return GetModule(name).asInstanceOf[ModuleBuilder]
+ }
+
+ /** Saves this dynamic assembly to disk. */
+ @throws(classOf[IOException])
+ def Save(fileName: String) {
+ generatedFiles = new ArrayList()
+ ILPrinterVisitor.printAssembly(this, fileName)
+ }
+
+ @throws(classOf[IOException])
+ def Save(destPath: String, sourceFilesPath: String) {
+ generatedFiles = new ArrayList()
+ ILPrinterVisitor.printAssembly(this, destPath, sourceFilesPath)
+ }
+
+ /** Returns the list of generated files from calling Save(). */
+ def GetGeneratedFiles(): Array[String] = {
+ return generatedFiles.toArray(new Array[String](generatedFiles.size())).asInstanceOf[Array[String]]
+ }
+
+ /** Sets the entry point for this dynamic assembly. */
+ def SetEntryPoint(entryMethod: MethodInfo) {
+ EntryPoint = entryMethod
+ }
+
+ /** Sets a custom attribute. */
+ def SetCustomAttribute(constr: ConstructorInfo, value: Array[byte]) {
+ addCustomAttribute(constr, value)
+ }
+
+ //##########################################################################
+ // protected members
+
+ // the access properties - Save, Run, RunAndSave
+ private var access : Int = _
+
+ // all extern assemblies used in this assembly builder
+ protected var externAssemblies = new HashSet[Assembly]()
+
+ // register an extern assembly
+ protected def registerExternAssembly(assembly: Assembly) {
+ externAssemblies.add(assembly)
+ }
+
+ // get all extern Assemblies used in this Assembly Builder
+ def getExternAssemblies(): Array[Assembly] = {
+ externAssemblies = new HashSet[Assembly](Assembly.assemblies.values().asInstanceOf[java.util.Collection[Assembly]])
+ externAssemblies.remove(this)
+ return externAssemblies.toArray(new Array[Assembly](0)).asInstanceOf[Array[Assembly]]
+ }
+
+ def loadModules() {}
+
+ // contains list of generated .msil files after calling Save()
+ var generatedFiles: ArrayList[String] = new ArrayList[String]()
+
+ //##########################################################################
+ //##########################################################################
+
+ /** the apply method for a visitor */
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseAssemblyBuilder(this)
+ }
+
+ //##########################################################################
+}
+
+object AssemblyBuilderFactory {
+ /**
+ * Defines a dynamic assembly with the specified name.
+ */
+ def DefineDynamicAssembly(name: AssemblyName): AssemblyBuilder = {
+ //Assembly.reset()
+ return new AssemblyBuilder(name)
+ }
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ConstructorBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ConstructorBuilder.scala
new file mode 100644
index 0000000000..6472bf678d
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ConstructorBuilder.scala
@@ -0,0 +1,65 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: ConstructorBuilder.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.ConstructorInfo
+import ch.epfl.lamp.compiler.msil.Type
+import java.io.IOException
+
+/**
+ * Defines and represents a constructor of a dynamic class.
+ * ConstructorBuilder is used to fully describe a constructor in
+ * Microsoft intermediate language (MSIL), including the name, attributes,
+ * signature, and constructor body. It is used in conjunction with the
+ * TypeBuilder class to create classes at run time. Call DefineConstructor
+ * to get an instance of ConstructorBuilder.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class ConstructorBuilder(declType: Type, attrs: int, paramTypes: Array[Type])
+ extends ConstructorInfo(declType, attrs, paramTypes)
+ with ICustomAttributeSetter
+ with Visitable
+{
+
+ //##########################################################################
+ // public interface
+
+ /** Defines a parameter of this constructor. */
+ def DefineParameter(pos: int, attr: int, name: String): ParameterBuilder = {
+ val param = new ParameterBuilder(name, params(pos).ParameterType, attr, pos)
+ params(pos) = param
+ return param
+ }
+
+ /** Returns an ILGenerator for this constructor. */
+ def GetILGenerator(): ILGenerator = {
+ return ilGenerator
+ }
+
+ /** Sets a custom attribute. */
+ def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) {
+ addCustomAttribute(constr, value)
+ }
+
+ //##########################################################################
+
+ /** The apply method for a visitor. */
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseConstructorBuilder(this)
+ }
+
+ //##########################################################################
+
+ // the Intermediate Language Generator
+ // it contains the method's body
+ protected var ilGenerator: ILGenerator = new ILGenerator(this)
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/EmitUtils.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/EmitUtils.scala
new file mode 100644
index 0000000000..a2c71df0d7
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/EmitUtils.scala
@@ -0,0 +1,55 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: EmitUtils.java 168 2005-12-12 14:20:06Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.*
+
+/**
+ * This class holds some usefull methods or fields which are not in the
+ * Reflection or Reflection.Emit Namespace (see .NET documentation)
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+object EmitUtils {
+
+ //##########################################################################
+
+ /**
+ * Defines a dynamic assembly with the specified name.
+ */
+ def DefineDynamicAssembly(name: AssemblyName): AssemblyBuilder = new AssemblyBuilder(name)
+
+ /**
+ * Helper functions that adds a space only after non-empty string
+ */
+ def append(sb: StringBuffer, str: String): StringBuffer = {
+ if (sb.length() > 0) {
+ var last: Char = sb.charAt(sb.length() - 1)
+ if (last != ' ' && last != '\t' || last != '\n')
+ sb.append(" ")
+ }
+ //return sb.append(str)
+ return trim(sb.append(str))
+ }
+
+ /**
+ * Helper functions that adds a space only after non-empty string
+ */
+ def append(str: StringBuffer, o: Object): String = append(str, "" + o)
+
+ /**
+ * Helper function that removes the trailing spaces
+ */
+ def trim(sb: StringBuffer): StringBuffer = {
+ while ((sb.length() > 0) && (sb.charAt(sb.length() - 1) == ' '))
+ sb.deleteCharAt(sb.length() - 1)
+ return sb
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/EmitUtils.scala2 b/src/msil/ch/epfl/lamp/compiler/msil/emit/EmitUtils.scala2
new file mode 100644
index 0000000000..c59a4293e8
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/EmitUtils.scala2
@@ -0,0 +1,55 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: EmitUtils.java 168 2005-12-12 14:20:06Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.*
+
+/**
+ * This class holds some usefull methods or fields which are not in the
+ * Reflection or Reflection.Emit Namespace (see .NET documentation)
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+object EmitUtils {
+
+ //##########################################################################
+
+ /**
+ * Defines a dynamic assembly with the specified name.
+ */
+ def DefineDynamicAssembly(name: AssemblyName): AssemblyBuilder = new AssemblyBuilder(name)
+
+ /**
+ * Helper functions that adds a space only after non-empty string
+ */
+ def append(sb: StringBuffer, str: String): StringBuffer = {
+ if (sb.length() > 0) {
+ var last: Char = sb.charAt(sb.length() - 1)
+ if (last != ' ' && last != '\t' || last != '\n')
+ sb.append(" ")
+ }
+ //return sb.append(str)
+ return trim(sb.append(str))
+ }
+
+ /**
+ * Helper functions that adds a space only after non-empty string
+ */
+ def append(str: StringBuffer, o: Object): String = append(str, "" + o)
+
+ /**
+ * Helper function that removes the trailing spaces
+ */
+ def trim(sb: StringBuffer): StringBuffer = {
+ while ((sb.length() > 0) && (sb.charAt(sb.length() - 1) == ' '))
+ sb.deleteCharAt(sb.length() - 1)
+ return sb
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/EmptyVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/EmptyVisitor.scala
new file mode 100644
index 0000000000..ea1d428db0
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/EmptyVisitor.scala
@@ -0,0 +1,83 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: EmptyVisitor.java 168 2005-12-12 14:20:06Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+/**
+ * Supplies empty method bodies to be overridden by subclasses.
+ */
+class EmptyVisitor extends Visitor {
+
+ //##########################################################################
+
+ /**
+ * Visit an AssemblyBuilder
+ */
+ def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) {
+ }
+
+ /**
+ * Visit a ModuleBuilder
+ */
+ def caseModuleBuilder(moduleBuilder: ModuleBuilder) {
+ }
+
+ /**
+ * Visit a TypeBuilder
+ */
+ def caseTypeBuilder(typeBuilder: TypeBuilder) {
+ }
+
+ /**
+ * Visit a FieldBuilder
+ */
+ def caseFieldBuilder(fieldBuilder: FieldBuilder) {
+ }
+
+ /**
+ * Visit a ConstructorBuilder
+ */
+ def caseConstructorBuilder(constructorBuilder: ConstructorBuilder) {
+ }
+
+ /**
+ * Visit a MethodBuilder
+ */
+ def caseMethodBuilder(methodBuilder: MethodBuilder) {
+ }
+
+ /**
+ * Visit a ParameterBuilder
+ */
+ def caseParameterBuilder(parameterBuilder: ParameterBuilder) {
+ }
+
+ /**
+ * Visit an ILGenerator
+ */
+ def caseILGenerator(iLGenerator: ILGenerator) {
+ }
+
+ /**
+ * visit an OpCode
+ */
+ def caseOpCode(opCode: OpCode) {
+ }
+
+ /**
+ * Visit a Label
+ */
+ def caseLabel(label: Label) {
+ }
+
+ /**
+ * Visit a LocalBuilder
+ */
+ def caseLocalBuilder(localBuilder: LocalBuilder) {
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/EmptyVisitor.scala2 b/src/msil/ch/epfl/lamp/compiler/msil/emit/EmptyVisitor.scala2
new file mode 100644
index 0000000000..ea1d428db0
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/EmptyVisitor.scala2
@@ -0,0 +1,83 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: EmptyVisitor.java 168 2005-12-12 14:20:06Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+/**
+ * Supplies empty method bodies to be overridden by subclasses.
+ */
+class EmptyVisitor extends Visitor {
+
+ //##########################################################################
+
+ /**
+ * Visit an AssemblyBuilder
+ */
+ def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) {
+ }
+
+ /**
+ * Visit a ModuleBuilder
+ */
+ def caseModuleBuilder(moduleBuilder: ModuleBuilder) {
+ }
+
+ /**
+ * Visit a TypeBuilder
+ */
+ def caseTypeBuilder(typeBuilder: TypeBuilder) {
+ }
+
+ /**
+ * Visit a FieldBuilder
+ */
+ def caseFieldBuilder(fieldBuilder: FieldBuilder) {
+ }
+
+ /**
+ * Visit a ConstructorBuilder
+ */
+ def caseConstructorBuilder(constructorBuilder: ConstructorBuilder) {
+ }
+
+ /**
+ * Visit a MethodBuilder
+ */
+ def caseMethodBuilder(methodBuilder: MethodBuilder) {
+ }
+
+ /**
+ * Visit a ParameterBuilder
+ */
+ def caseParameterBuilder(parameterBuilder: ParameterBuilder) {
+ }
+
+ /**
+ * Visit an ILGenerator
+ */
+ def caseILGenerator(iLGenerator: ILGenerator) {
+ }
+
+ /**
+ * visit an OpCode
+ */
+ def caseOpCode(opCode: OpCode) {
+ }
+
+ /**
+ * Visit a Label
+ */
+ def caseLabel(label: Label) {
+ }
+
+ /**
+ * Visit a LocalBuilder
+ */
+ def caseLocalBuilder(localBuilder: LocalBuilder) {
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala
new file mode 100644
index 0000000000..e8941e7ab8
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/FieldBuilder.scala
@@ -0,0 +1,58 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: FieldBuilder.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.FieldInfo
+import ch.epfl.lamp.compiler.msil.Type
+import ch.epfl.lamp.compiler.msil.FieldAttributes
+import ch.epfl.lamp.compiler.msil.ConstructorInfo
+import java.io.IOException
+
+/**
+ * Discovers the attributes of a field and provides access to field metadata.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class FieldBuilder(name: String, declType: Type, attrs: int, fieldType: Type)
+ extends FieldInfo(name, declType, attrs, fieldType)
+ with ICustomAttributeSetter
+ with Visitable
+{
+
+ //##########################################################################
+ // public interface
+
+ /** Sets a custom attribute. */
+ def SetCustomAttribute(constr: ConstructorInfo, value: Array[Byte]) {
+ addCustomAttribute(constr, value)
+ }
+
+ //##########################################################################
+
+ /** the apply method for a visitor */
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseFieldBuilder(this)
+ }
+
+ //##########################################################################
+
+ protected var defaultValue: Object = _
+
+ /** Sets the default value of this field. */
+ def SetConstant(defaultValue: Object) {
+ this.defaultValue = defaultValue
+ }
+
+ /** Specifies the field layout. */
+ def SetOffset(iOffset: Int) {
+ //this.fieldOffset = FieldAttributes.Offset.Value(iOffset)
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ICustomAttributeSetter.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ICustomAttributeSetter.scala
new file mode 100644
index 0000000000..1249223b83
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ICustomAttributeSetter.scala
@@ -0,0 +1,19 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: ICustomAttributeSetter.java 168 2005-12-12 14:20:06Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.ConstructorInfo
+
+/**
+ * Declares the possibility to set a custom attribute for a member
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+trait ICustomAttributeSetter {
+ def SetCustomAttribute(constr: ConstructorInfo, value: Array[byte])
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
new file mode 100644
index 0000000000..a94259dd2e
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
@@ -0,0 +1,538 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: ILGenerator.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil._
+import ch.epfl.lamp.compiler.msil.util.Table
+import java.util.ArrayList
+import java.util.Stack
+import java.util.Iterator
+import java.util.Map
+import java.util.HashMap
+import java.io.IOException
+import ILGenerator._
+
+/**
+ * Generates Microsoft intermediate language (MSIL) instructions.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+ final class ILGenerator(_owner: MethodBase) extends Visitable {
+
+ //##########################################################################
+ // public interface
+
+ /**
+ * Puts the specified instruction onto the stream of instructions.
+ */
+ def Emit(opcode: OpCode) {
+ // switch opcode
+ if (opcode == OpCode.Ret) {
+ emit(opcode, null, 0)
+ } else {
+ emit(opcode, null)
+ }
+ }
+
+ /**
+ * Puts the specified instruction and character argument onto
+ * the Microsoft intermediate language (MSIL) stream of instructions.
+ */
+ def Emit(opcode: OpCode, arg: Char) {
+ emit(opcode,new Character(arg))
+ }
+
+ /**
+ * Puts the specified instruction and metadata token for the
+ * specified constructor onto the Microsoft intermediate language
+ * (MSIL) stream of instructions.
+ */
+ def Emit(opcode: OpCode, arg: ConstructorInfo) {
+ assert(arg != null)
+ // newobj
+ // pop size is the number of parameters
+ emit(opcode,arg, OpCode.PUSH_size(opcode.CEE_push) -
+ arg.GetParameters().length)
+ }
+
+ /**
+ * Puts the specified instruction onto the Microsoft intermediate language (MSIL)
+ * stream followed by the index of the given local variable.
+ */
+ def Emit(opcode: OpCode, arg: LocalBuilder) {
+ assert(arg != null)
+ // ldarg | ldarg.s | ldarga
+ // ldarga.s | ldloc | ldloc.s | ldloca
+ // ldloca.s | starg | starg.s | stloc
+ // stloc.s
+
+ // <instr_var> <localname>
+ emit(opcode, arg)
+ }
+
+
+ /**
+ * Puts the specified instruction and numerical argument onto
+ * the Microsoft intermediate language (MSIL) stream of instructions.
+ */
+ def Emit(opcode: OpCode, arg: Double) {
+ // ldc.r4 | ldc.r8
+ emit(opcode, new java.lang.Double(arg))
+ }
+
+ /**
+ * Puts the specified instruction and metadata token for the
+ * specified field onto the Microsoft intermediate language (MSIL)
+ * stream of instructions.
+ */
+ def Emit(opcode: OpCode,arg: FieldInfo) {
+ assert(arg != null)
+ // ldfld | ldflda | ldsfld | ldsflda | stfld | stsfld
+ emit(opcode,arg)
+ }
+
+ /**
+ * Puts the specified instruction and numerical argument onto
+ * the Microsoft intermediate language (MSIL) stream of instructions.
+ */
+ def Emit(opcode: OpCode, arg: Short ) {
+ emit(opcode, new java.lang.Short(arg))
+ }
+
+ /**
+ * Puts the specified instruction and numerical argument onto
+ * the Microsoft intermediate language (MSIL) stream of instructions.
+ */
+ def Emit(opcode: OpCode, arg: Int) {
+ // ldc.i4 | ldc.i4.s | unaligned
+ emit(opcode, new java.lang.Integer(arg))
+ }
+
+ /**
+ * Puts the specified instruction and numerical argument onto
+ * the Microsoft intermediate language (MSIL) stream of instructions.
+ */
+ def Emit(opcode: OpCode, arg: Long) {
+ // ldc.i8
+ emit(opcode, new java.lang.Long(arg))
+ }
+
+ /**
+ * Puts the specified instruction onto the Microsoft intermediate
+ * language (MSIL) stream and leaves space to include a label when
+ * fixes are done.
+ */
+ def Emit(opcode: OpCode,label: Label) {
+ assert(label != null)
+ // beq | beq.s | bge | bge.s |
+ // bge.un | bge.un.s | bgt | bgt.s | bgt.un | bgt.un.s |
+ // ble | ble.s | ble.un | ble.un.s | blt | blt.s |
+ // blt.un | blt.un.s | bne.un | bne.un.s | br | br.s |
+ // brfalse | brfalse.s | brtrue | brtrue.s | leave | leave.s
+
+ emit(opcode, label)
+ // is the label initialized ? if true backward jump else forward jump
+ if (label.isInitialized()) {
+// if (arg.stacksize != lastLabel.stacksize) {
+// System.err.println("ILGenerator.Emit: Stack depth differs depending on path:");
+// System.err.println("\tmethod = " + owner);
+// System.err.println("\tPC = 0x" + Table.short2hex(lastLabel.address));
+// }
+ //assert arg.stacksize == lastLabel.stacksize;
+ }
+ else {
+ label.setStacksize(lastLabel.getStacksize())
+ }
+ }
+
+ /**
+ * Puts the specified instruction onto the Microsoft intermediate
+ * language (MSIL) stream and leaves space to include a label when
+ * fixes are done.
+ */
+ def Emit(opcode: OpCode, arg: Array[Label] ) {
+ assert(arg != null)
+ // switch
+
+ // <instr> ::= <instr_switch> ( <labels> )
+ // Examples:
+ // switch (0x3, -14, Label1)
+ // switch (5, Label2)
+ emit(opcode, arg, arg.length)
+ }
+
+ /**
+ * Puts the specified instruction onto the Microsoft intermediate
+ * language (MSIL) stream followed by the metadata token for the
+ * given method.
+ */
+ def Emit(opcode: OpCode,arg: MethodInfo) {
+ assert(arg != null)
+ // call | callvirt | jmp | ldftn | ldvirtftn
+ // pop size is the number of parameters
+ // pop 1 more if method is not static !
+ // push size is either 0 (void Method) either 1
+ assert(arg.ReturnType != null, "No ReturnType: " + arg.DeclaringType + "::" + arg.Name)
+
+ val popush: Int = if (opcode == OpCode.Ldftn ||
+ opcode == OpCode.Ldvirtftn ||
+ opcode == OpCode.Jmp)
+ {
+ OpCode.PUSH_size(opcode.CEE_push) - OpCode.POP_size(opcode.CEE_pop)
+ } else if (opcode == OpCode.Calli || opcode == OpCode.Callvirt) {
+ (if(arg.ReturnType == VOID) 0 else 1) - arg.GetParameters().length - 1
+ } else {
+ (if(arg.ReturnType == VOID) 0 else 1) - arg.GetParameters().length
+ }
+ emit(opcode, arg, popush)
+ }
+
+ /**
+ * Puts the specified instruction and numerical argument onto
+ * the Microsoft intermediate language (MSIL) stream of instructions.
+ */
+ def Emit(opcode: OpCode, arg: Float ) {
+ emit(opcode, new java.lang.Float(arg))
+ }
+
+ /**
+ * Puts the specified instruction onto the Microsoft intermediate
+ * language (MSIL) stream followed by the metadata token for the
+ * given string.
+ */
+ def Emit(opcode: OpCode, arg: String ) {
+ assert(arg != null)
+ // ldstr
+ emit(opcode, arg)
+ }
+
+ /**
+ * Puts the specified instruction onto the Microsoft intermediate
+ * language (MSIL) stream followed by the metadata token for the
+ * given type.
+ */
+ def Emit(opcode: OpCode, arg: Type) {
+ assert(arg != null)
+ // box | castclass | cpobj | initobj | isinst |
+ // ldelema | ldobj | mkrefany | newarr | refanyval |
+ // sizeof | stobj | unbox
+
+ emit(opcode, arg)
+ }
+
+ /**
+ * Puts a call or callvirt instruction onto the Microsoft intermediate
+ * language (MSIL) stream.
+ */
+ def EmitCall(opcode: OpCode, arg: MethodInfo,
+ optionalParameterTypes: Array[Type]) {
+ assert(arg != null)
+ // pop size is the number of parameters
+ // push size is either 0 (void Method) either 1
+ //System.out.println(arg.ReturnType.Size + " " + arg.GetParameters().length);
+ emit(opcode, arg, (if(arg.ReturnType == VOID) 0 else 1) -
+ arg.GetParameters().length)
+ }
+
+ /**
+ * Emits the Microsoft intermediate language (MSIL) necessary to
+ * call WriteLine with the given field.
+ */
+ def EmitWriteLine(arg: FieldInfo) {
+ // first load field info
+ // if static use OpCode.Ldsfld
+ if (arg.IsStatic())
+ Emit(OpCodes.Ldsfld, arg)
+ else
+ Emit(OpCodes.Ldfld, arg)
+ // then call System.Console.WriteLine(arg.Type)
+ val t: Type = Type.GetType("System.Console")
+ val argsType: Array[Type] = new Array[Type](1)
+ argsType(0) = arg.FieldType
+ val m: MethodInfo = t.GetMethod("WriteLine", argsType)
+ EmitCall(OpCode.Call, m, null)
+ }
+
+ /**
+ * Emits the Microsoft intermediate language (MSIL) necessary
+ * to call WriteLine with the given local variable.
+ */
+ def EmitWriteLine(arg: LocalBuilder) {
+ // first load local variable
+ Emit(OpCodes.Ldloc, arg)
+ // then call System.Console.WriteLine(arg.Type)
+ val t: Type = Type.GetType("System.Console")
+ val argsType: Array[Type] = new Array[Type](1)
+ argsType(0) = arg.LocalType
+ val m: MethodInfo = t.GetMethod("WriteLine", argsType)
+ EmitCall(OpCode.Call, m, null)
+ }
+
+ /**
+ * Emits the Microsoft intermediate language (MSIL) to call
+ * WriteLine with a string.
+ */
+ def EmitWriteLine(arg: String) {
+ // first load string
+ Emit(OpCode.Ldstr, arg)
+ // then call System.Console.WriteLine(string)
+ val t: Type = Type.GetType("System.Console")
+ val argsType: Array[Type] = new Array[Type](1)
+ argsType(0) = Type.GetType("System.String")
+ val m: MethodInfo = t.GetMethod("WriteLine", argsType)
+ EmitCall(OpCode.Call, m, null)
+ }
+
+ /**
+ * Declares a local variable.
+ */
+ def DeclareLocal(localType: Type): LocalBuilder = {
+ val l: LocalBuilder = new LocalBuilder(locals, localType)
+ locals = locals + 1
+ localList.add(l)
+ return l
+ }
+
+ /**
+ * Returns a new label that can be used as a token for branching.
+ * In order to set the position of the label within the stream, you
+ * must call MarkLabel. This is just a token and does not yet represent
+ * any particular location within the stream.
+ */
+ def DefineLabel():Label = {
+ new Label.NormalLabel()
+ }
+
+ /**
+ * Marks the Microsoft intermediate language (MSIL) stream's
+ * current position with the given label.
+ */
+ def MarkLabel(label: Label) {
+ label.mergeWith(lastLabel)
+ /*
+ label.address = lastLabel.address;
+ //label.stacksize = lastLabel.stacksize;
+ if (label.stacksize >= 0)
+ lastLabel.stacksize = label.stacksize;
+ */
+ }
+
+ /** Begins a lexical scope. */
+ def BeginScope() {
+ emitSpecialLabel(Label.NewScope)
+ }
+
+ /** Ends a lexical scope. */
+ def EndScope() {
+ emitSpecialLabel(Label.EndScope)
+ }
+
+ /**
+ * Begins an exception block for a non-filtered exception.
+ * The label for the end of the block. This will leave you in the correct
+ * place to execute finally blocks or to finish the try.
+ */
+ def BeginExceptionBlock() {
+ emitSpecialLabel(Label.Try)
+ val endExc: Label = new Label.NormalLabel() // new Label(lastLabel) ???
+ excStack.push(Label.Try, endExc)
+ return endExc
+ }
+
+ /** Begins a catch block. */
+ def BeginCatchBlock(exceptionType: Type) {
+ val kind = excStack.peekKind()
+ if (kind == Label.Kind.Try ||
+ kind == Label.Kind.Catch) {
+ /* ok */
+ } else {
+ throw new RuntimeException("Catch should follow either a try or catch")
+ }
+ val endExc: Label = excStack.popLabel()
+ Emit(OpCodes.Leave, endExc)
+ // the CLI automatically provide the exception object on the evaluation stack
+ // we adjust the stacksize
+ lastLabel.incStacksize()
+ excStack.push(Label.Catch, endExc)
+ emitSpecialLabel(Label.Catch, exceptionType)
+ }
+
+ /** Ends an exception block. */
+ def EndExceptionBlock() {
+ val kind = excStack.peekKind()
+ if (kind == Label.Kind.Try) {
+ throw new RuntimeException("Try block with neither catch nor finally")
+ } else if (kind == Label.Kind.Catch) {
+ Emit(OpCodes.Leave, excStack.peekLabel())
+ } else if (kind == Label.Kind.Finally) {
+ Emit(OpCodes.Endfinally)
+ }
+ MarkLabel(excStack.popLabel())
+ emitSpecialLabel(Label.EndTry)
+ }
+
+ /**
+ * Begins a finally block in the Microsoft intermediate language
+ * (MSIL) instruction stream.
+ */
+ def BeginFinallyBlock() {
+ Emit(OpCodes.Leave, excStack.peekLabel())
+ emitSpecialLabel(Label.Finally)
+ }
+
+ /**
+ * Emits an instruction to throw an exception.
+ */
+ def ThrowException(exceptionType: Type) {
+ assert(exceptionType != null)
+ if (!exceptionType.isSubtypeOf(Type.GetType("System.Exception")))
+ throw new RuntimeException
+ (exceptionType + " doesn't extend System.Exception" )
+ val ctor: ConstructorInfo = exceptionType.GetConstructor(Type.EmptyTypes)
+ if (ctor == null)
+ throw new RuntimeException("Type " + exceptionType
+ + "doesn't have a default constructor")
+ Emit(OpCodes.Newobj, ctor)
+ Emit(OpCodes.Throw)
+ }
+
+ /**
+ * sets the line of the source file corresponding to the next instruction
+ */
+ def setPosition(line: Int) {
+ if (line != 0)
+ lineNums.put(lastLabel, Integer.toString(line))
+ }
+
+ def setPosition(line: Int, filename: String) {
+ if (line != 0)
+ lineNums.put(lastLabel, line + " '" + filename + "'")
+ }
+
+ def getLocals(): Array[LocalBuilder] = {
+ localList.toArray(new Array[LocalBuilder](0)).asInstanceOf[Array[LocalBuilder]]
+ }
+
+ def getLabelIterator(): Iterator[Label] = {
+ labelList.iterator()
+ }
+ def getOpcodeIterator(): Iterator[OpCode] = {
+ opcodeList.iterator()
+ }
+ def getArgumentIterator(): Iterator[Object] = {
+ argumentList.iterator()
+ }
+
+ //##########################################################################
+ // private implementation details
+
+
+
+ // the local variable list
+ private final val localList: ArrayList[LocalBuilder] = new ArrayList[LocalBuilder]()
+
+ // the label list, the opcode list and the opcode argument list
+ // labelList is an array of Label
+ // opcodeList is an array of OpCode
+ // argumentList is an array of Object (null if no argument)
+ private final val labelList: ArrayList[Label] = new ArrayList[Label]()
+ private final val opcodeList: ArrayList[OpCode] = new ArrayList[OpCode]()
+ private final val argumentList: ArrayList[Object] = new ArrayList[Object]()
+
+ // the program counter (pc)
+ // also called the stream's current position
+ private var pc: Int = 0
+
+ // last label
+ private var lastLabel: Label = new Label.NormalLabel(pc,0)
+
+ // the maximum size of stack
+ private var maxstack: Int = 0
+
+ // the number of the locals
+ private var locals: Int = 0
+
+ // stack of label for exception mechanism
+ private var excStack: ExceptionStack = new ExceptionStack()
+
+ // the method info owner of this ILGenerator
+ var owner: MethodBase = _owner
+
+ val lineNums: Map[Label, String] = new HashMap[Label, String]()
+
+
+ def getMaxStacksize(): Int = { this.maxstack }
+
+ // private emit with Object Argument
+ private def emit(opcode: OpCode, arg: Object) {
+ emit(opcode, arg, opcode.CEE_popush)
+ }
+
+ // private emit with Object Argument and override POPUSH
+ private def emit(opcode: OpCode, arg: Object, overridePOPUSH: Int) {
+ // add label, opcode and argument
+ labelList.add(lastLabel)
+ opcodeList.add(opcode)
+ argumentList.add(arg)
+ // compute new lastLabel (next label)
+ val stackSize: Int = lastLabel.getStacksize() + overridePOPUSH
+ if (stackSize < 0) {
+ throw new RuntimeException
+ //System.err.println
+ ("ILGenerator.emit(): Stack underflow in method: " + owner)
+ }
+ if (stackSize > maxstack)
+ maxstack = stackSize
+ var address: Int = lastLabel.getAddress() + opcode.CEE_length
+ if (opcode.CEE_opcode == OpCode.CEE_SWITCH) {
+ address = address + 4*arg.asInstanceOf[Array[Label]].length
+ }
+ lastLabel = new Label.NormalLabel(address, stackSize)
+ pc = pc + 1
+ }
+
+ private def emitSpecialLabel(l: Label) {
+ emitSpecialLabel(l, null)
+ }
+ private def emitSpecialLabel(l: Label, catchType: Type) {
+ labelList.add(l)
+ opcodeList.add(null)
+ argumentList.add(catchType)
+ }
+
+ //##########################################################################
+ //
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseILGenerator(this)
+ }
+
+ //##########################################################################
+} // class ILGenerator
+
+
+object ILGenerator {
+
+ val VOID: Type = Type.GetType("System.Void")
+ val NO_LABEL: String = ""
+
+ private final class ExceptionStack {
+ private val labels: Stack[Label] = new Stack[Label]()
+ private val kinds: Stack[Label] = new Stack[Label]()
+ def ExceptionStack() {}
+ def pop() { labels.pop(); kinds.pop() }
+ def push(kind: Label, label: Label) {
+ kinds.push(kind); labels.push(label)
+ }
+ def peekKind(): Label.Kind = {kinds.peek().asInstanceOf[Label].getKind() }
+ def peekLabel(): Label = { labels.peek().asInstanceOf[Label] }
+ def popLabel(): Label = { kinds.pop(); labels.pop().asInstanceOf[Label]}
+ }
+
+}
+
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
new file mode 100644
index 0000000000..e6b7cf4bbe
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
@@ -0,0 +1,735 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies in MSIL
+ */
+
+// $Id: ILPrinterVisitor.java 14755 2008-04-22 08:13:32Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import java.io.File
+import java.io.FileWriter
+import java.io.BufferedWriter
+import java.io.PrintWriter
+import java.io.IOException
+import java.util.Iterator
+import java.util.HashMap
+import java.util.Arrays
+import java.util.Comparator
+
+import ch.epfl.lamp.compiler.msil._
+import ch.epfl.lamp.compiler.msil.util.Table
+
+/**
+ * The MSIL printer Vistor. It prints a complete
+ * assembly in a single or multiple files. Then this file can be compiled by ilasm.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+abstract class ILPrinterVisitor extends Visitor {
+
+ import ILPrinterVisitor._
+ import OpCode._
+
+ //##########################################################################
+
+ protected final val assemblyNameComparator =
+ new Comparator[Assembly]() {
+ def compare(o1: Assembly, o2: Assembly): Int = {
+ val a1 = o1.asInstanceOf[Assembly]
+ val a2 = o2.asInstanceOf[Assembly]
+ return a1.GetName().Name.compareTo(a2.GetName().Name)
+ }
+ }
+
+ // the output file writer
+ protected var out: PrintWriter = null
+
+ // the left margin
+ private var lmargin = 0
+
+ // indicate a newline
+ private var newline = true
+
+ // print types without or with members?
+ protected var nomembers: boolean = false
+
+ // external assemblies
+ protected var as: Array[Assembly] = null
+
+ private def align() {
+ if (newline)
+ padding = lmargin
+ printPadding()
+ newline = false
+ }
+ private def indent() {
+ lmargin += TAB
+ }
+ private def undent() {
+ lmargin -= TAB
+ assert(lmargin >= 0)
+ }
+
+ private var padding = 0
+ private def pad(n: Int) {
+ assert(n >= 0, "negative padding: " + n)
+ padding += n
+ }
+ private def printPadding() {
+ if (padding <= 0)
+ return
+ while (padding > SPACES_LEN) {
+ out.print(SPACES)
+ padding -= SPACES_LEN
+ }
+ out.print(SPACES.substring(0, padding))
+ padding = 0
+ }
+
+ // methods to print code
+ protected def print(s: String) { align(); out.print(s)}
+ protected def print(o: Object) { align(); out.print(o) }
+ protected def print(c: char) { align(); out.print(c) }
+ protected def print(`val`: int) { align(); out.print(`val`)}
+ protected def print(`val`: long){ align(); out.print(`val`)}
+ protected def println() { out.println(); newline = true; padding = 0 }
+ protected def println(c: char) { print(c); println() }
+ protected def println(i: int) { print(i); println() }
+ protected def println(l: long) { print(l); println() }
+ protected def println(s: String){ print(s); println() }
+ protected def println(o: Object){ print(o); println() }
+ protected def printName(name: String) {
+ var ch = name.charAt(0)
+ //if (Character.isLetter(ch) && Character.isLowerCase(ch)) {
+ if (ch != '.') {
+ print('\''); print(name); print('\'')
+ } else
+ print(name)
+ }
+
+ protected def printAssemblyBoilerplate() {
+ // print all the external assemblies
+ for (val j <- 0 until as.length) {
+ printAssemblySignature(as(j), true)
+ }
+ // print assembly declaration
+ printAssemblySignature(currAssembly, false)
+ }
+
+ // the entrypoint method
+ protected var entryPoint: MethodInfo = null
+
+ // current opcode argument
+ protected var argument: Object = null
+
+ /***/
+ @throws(classOf[IOException])
+ protected def print(vAble: Visitable) {
+ if (vAble != null)
+ vAble.apply(this)
+ }
+
+ /**
+ * Visit an AssemblyBuilder
+ */
+ @throws(classOf[IOException])
+ def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder)
+
+ protected var currentModule: Module = null
+ /**
+ * Visit a ModuleBuilder
+ */
+ @throws(classOf[IOException])
+ def caseModuleBuilder(module: ModuleBuilder)
+
+ protected var currentType: Type = null
+ /**
+ * Visit a TypeBuilder
+ */
+ @throws(classOf[IOException])
+ def caseTypeBuilder(`type`: TypeBuilder) {
+ currentType = `type`
+ if (!`type`.Namespace.equals("") && `type`.DeclaringType == null) {
+ print(".namespace \'" ); print(`type`.Namespace); println("\'")
+ println("{"); indent()
+ }
+ print(".class ")
+ // <classHead> ::=
+ // <classAttr>* <id>
+ // [extends <typeReference>]
+ // [implements <typeReference> [, <typeReference>]*]
+ print(TypeAttributes.toString(`type`.Attributes))
+ print(" \'"); print(`type`.Name); print("\'")
+ if (`type`.BaseType() != null) {
+ println()
+ print(" extends ")
+ printReference(`type`.BaseType())
+ }
+ var ifaces: Array[Type] = `type`.getInterfaces()
+ if (ifaces.length > 0) {
+ println()
+ print(" implements ")
+ for (val i <- 0 until ifaces.length) {
+ if (i > 0) {
+ println(",")
+ print(" ")
+ }
+ printReference(ifaces(i))
+ }
+ }
+ println()
+ println("{")
+ indent()
+ if (!nomembers && `type`.sourceFilename != null)
+ println(".line " + `type`.sourceLine
+ + " '" + `type`.sourceFilename + "'")
+ if (!nomembers) {
+ printAttributes(`type`)
+ }
+ // print nested classes
+ val nested = `type`.nestedTypeBuilders.iterator()
+ while(nested.hasNext())
+ print(nested.next().asInstanceOf[TypeBuilder])
+
+ // print each field
+ val fields = `type`.fieldBuilders.iterator()
+ while(fields.hasNext())
+ print(fields.next().asInstanceOf[FieldBuilder])
+
+ // print each constructor
+ val constrs = `type`.constructorBuilders.iterator()
+ while (constrs.hasNext())
+ print(constrs.next().asInstanceOf[ConstructorBuilder])
+
+ // print each method
+ val methods = `type`.methodBuilders.iterator()
+ while (methods.hasNext()) {
+ val method = methods.next().asInstanceOf[MethodBuilder]
+ assert(method.DeclaringType == `type`)
+ print(method)
+ }
+
+ undent(); println("}")
+ if (!`type`.Namespace.equals("") && `type`.DeclaringType == null) {
+ undent(); println("}")
+ }
+ currentType = null
+ }
+
+ /**
+ * Visit a FieldBuilder
+ */
+ @throws(classOf[IOException])
+ def caseFieldBuilder(field: FieldBuilder) {
+ if (nomembers) return
+ // [[int32]] <fieldAttr>* <type> <id> [= <fieldInit> | at <dataLabel>]
+ print(".field ")
+ print(FieldAttributes.toString(field.Attributes))
+ print(" "); printSignature(field.FieldType)
+ print(" \'"); print(field.Name); print("\'")
+ if (field.IsLiteral()) {
+ print(" = ")
+ val value = field.getValue()
+ if (value == null) {
+ print("nullref")
+ } else if (value.isInstanceOf[String]) {
+ print(msilString(value.asInstanceOf[String]))
+ } else if (value.isInstanceOf[Boolean]) {
+ print("bool (")
+ print(if((value.asInstanceOf[Boolean]).booleanValue()) { "true" } else { "false" })
+ print(")")
+ } else if (value.isInstanceOf[Byte]) {
+ print("int8 (")
+ print(value)
+ print(")")
+ } else if (value.isInstanceOf[java.lang.Short]) {
+ print("int16 (")
+ print(value)
+ print(")")
+ } else if (value.isInstanceOf[Character]) {
+ print("char (")
+ print((value.asInstanceOf[Character]).charValue())
+ print(")")
+ } else if (value.isInstanceOf[Integer]) {
+ print("int32 (")
+ print((value.asInstanceOf[Integer]).intValue())
+ print(")")
+ } else if (value.isInstanceOf[Long]) {
+ print("int64 (")
+ print((value.asInstanceOf[Long]).longValue())
+ print(")")
+ } else if (value.isInstanceOf[Float]) {
+ // !!! check if encoding is correct
+ val bits = java.lang.Float.floatToRawIntBits((value.asInstanceOf[Float]).floatValue())
+ // float32(float32(...)) != float32(...)
+ print("float32 (float32 (")
+ print(bits)
+ print("))")
+ } else if (value.isInstanceOf[Double]) {
+ // !!! check if encoding is correct
+ var bits = java.lang.Double.doubleToRawLongBits((value.asInstanceOf[Double]).doubleValue())
+ // float64(float64(...)) != float64(...)
+ print("float64 (float64 (")
+ print(bits)
+ print("))")
+ } else {
+ throw new Error("ILPrinterVisitor: Illegal default value: "
+ + value.getClass())
+ }
+ }
+ println()
+ printAttributes(field)
+ }
+
+ /**
+ * Visit a ConstructorBuilder
+ */
+ @throws(classOf[IOException])
+ def caseConstructorBuilder(constr: ConstructorBuilder) {
+ if (nomembers) return
+ print(".method "); printHeader(constr, VOID)
+ println(); println("{"); indent()
+ printAttributes(constr)
+ try {
+ print(constr.GetILGenerator())
+ } catch {
+ case e : RuntimeException => {
+ System.err.println("In method " + constr)
+ e.printStackTrace()
+ }
+ }
+ undent(); println("}")
+ }
+
+ /**
+ * Visit a MethodBuilder
+ */
+ @throws(classOf[IOException])
+ def caseMethodBuilder(method: MethodBuilder) {
+ if (nomembers) return
+ print(".method "); printHeader(method, method.ReturnType)
+ if (method.IsAbstract()
+ || (method.DeclaringType != null
+ && method.DeclaringType.IsInterface()
+ && !method.IsStatic()))
+ {
+ println(" {"); indent()
+ printAttributes(method)
+ undent(); println("}")
+ } else {
+ println(); println("{"); indent()
+ printAttributes(method)
+ if (method == entryPoint)
+ println(".entrypoint")
+ try {
+ print(method.GetILGenerator())
+ } catch {
+ case e: RuntimeException =>
+ System.err.println("In method " + method)
+ e.printStackTrace()
+ }
+ undent(); println("}")
+ }
+ }
+
+ /**
+ * Visit a ParameterBuilder
+ */
+ @throws(classOf[IOException])
+ def caseParameterBuilder(param: ParameterBuilder) {
+ print(ParameterAttributes.toString(param.Attributes))
+ printSignature(param.ParameterType)
+ //print(' ') print(marshal)
+ print(' '); printName(param.Name)
+ }
+
+ /**
+ * Visit an ILGenerator
+ */
+ @throws(classOf[IOException])
+ def caseILGenerator(code: ILGenerator) {
+ // print maxstack
+ println(".maxstack " + code.getMaxStacksize())
+ // get the local variables
+ var locals: Array[LocalBuilder] = code.getLocals()
+ if (locals.length > 0) {
+ println(".locals init (")
+ indent()
+ for (val i <- 0 until locals.length) {
+ if (i > 0) println(",")
+ print(locals(i))
+ } // end while
+ undent()
+ println(")")
+ }
+ // get 3 iterators for the 3 lists
+ val itL = code.getLabelIterator()
+ val itO = code.getOpcodeIterator()
+ val itA = code.getArgumentIterator()
+ // iterate over each opcode
+ while (itO.hasNext()) {
+ // first print label
+ val label = itL.next().asInstanceOf[Label]
+ var o = code.lineNums.get(label)
+ if (o != null)
+ println(".line " + o)
+ argument = itA.next().asInstanceOf[Object]
+ printLabel(label)
+ val o2 = itO.next()
+ if (o2 != null) {
+ print(" ")
+ print(o2.asInstanceOf[OpCode])
+ }
+ println()
+ } // end while
+ }
+
+ /**
+ * visit an OpCode
+ */
+ @throws(classOf[IOException])
+ def caseOpCode(opCode: OpCode) {
+ var opString = opCode.toString()
+ print(opString)
+ pad(12 - opString.length())
+
+ // switch opcode
+ if (opCode == OpCode.Ldstr) {
+ print(msilString(argument.toString()))
+ } else if(opCode == OpCode.Switch) {
+ // switch ( <labels> )
+ print("(")
+ val targets = argument.asInstanceOf[Array[Label]]
+ val m = targets.length
+ for (val i <- 0 until m) {
+ if (i != 0) print(", ")
+ print(targets(i))
+ } // end for
+ print(")")
+ } else if(opCode == OpCode.Call || opCode == OpCode.Callvirt || opCode == OpCode.Jmp || opCode == OpCode.Ldftn || opCode == OpCode.Ldvirtftn) {
+ // call | callvirt | jmp | ldftn | ldvirtftn
+ // <instr_method> <callConv> <type> [ <typeSpec> :: ] <methodName>
+ printSignature(argument.asInstanceOf[MethodBase])
+ } else if (opCode == OpCode.Newobj) {
+ printSignature(argument.asInstanceOf[ConstructorInfo])
+ // ldfld | ldflda | ldsfld | ldsflda | stfld | stsfld
+ } else if (opCode == OpCode.Ldfld || opCode == OpCode.Ldflda || opCode == OpCode.Ldsfld || opCode == OpCode.Ldsflda || opCode == OpCode.Stfld || opCode == OpCode.Stsfld) {
+ printSignature(argument.asInstanceOf[FieldInfo])
+ } else if (opCode == OpCode.Castclass || opCode == OpCode.Isinst || opCode == OpCode.Ldobj || opCode == OpCode.Newarr) {
+ printSignature(argument.asInstanceOf[Type])
+ } else if (opCode == OpCode.Box || opCode == OpCode.Unbox || opCode == OpCode.Ldtoken) {
+ printReference(argument.asInstanceOf[Type])
+ } else if (opCode == OpCode.Ldloc || opCode == OpCode.Ldloc_S || opCode == OpCode.Ldloca || opCode == OpCode.Ldloca_S || opCode == OpCode.Stloc || opCode == OpCode.Stloc_S) {
+ val loc = argument.asInstanceOf[LocalBuilder]
+ print(loc.slot); print("\t// "); printSignature(loc.LocalType)
+ print(" \'"); print(loc.name); print("\'")
+ //print("'") print(((LocalBuilder)argument).name) print("'")
+ } else {
+ // by default print toString argument if any
+ if (argument != null)
+ print(argument)
+ } // end switch
+ }
+
+ /**
+ * Visit a Label
+ */
+ def printLabel(label: Label) {
+ val kind = label.getKind()
+ if (kind == Label.Kind.Normal) {
+ print(label+ ": ")
+ } else if (kind == Label.Kind.NewScope) {
+ print("{"); indent()
+ } else if (kind == Label.Kind.EndScope) {
+ undent(); print("}")
+ } else if (kind == Label.Kind.Try) {
+ print(".try {"); indent()
+ } else if (kind == Label.Kind.Catch) {
+ undent()
+ println("}")
+ print("catch ")
+ printReference(argument.asInstanceOf[Type])
+ print(" {")
+ indent()
+ } else if (kind == Label.Kind.Filter) {
+ undent()
+ println("}")
+ print("filter {")
+ indent()
+ } else if (kind == Label.Kind.EndFilter) {
+ print("endfilter")
+ undent()
+ println("}")
+ } else if (kind == Label.Kind.Finally) {
+ undent()
+ println("}")
+ print("finally {")
+ indent()
+ } else if (kind == Label.Kind.EndTry) {
+ undent()
+ print("}")
+ }
+ }
+
+ /**
+ * Visit a LocalBuilder
+ */
+ @throws(classOf[IOException])
+ def caseLocalBuilder(localBuilder: LocalBuilder) {
+ // print type
+ printSignature(localBuilder.LocalType)
+ // space
+ print(" \'")
+ // print name
+ print(localBuilder.name)
+ print("\'")
+ }
+
+
+ //##########################################################################
+
+ def printAssemblySignature(assem: Assembly, extern: boolean) {
+ print(".assembly ")
+ if (extern)
+ print("extern ")
+ val an = assem.GetName()
+ printName(an.Name); println()
+ println("{")
+ if (!extern)
+ printAttributes(assem)
+ val v = an.Version
+ if (v != null) {
+ print(" .ver "); print(v.Major); print(':'); print(v.Minor)
+ print(':'); print(v.Build); print(':')
+ print(v.Revision); println()
+ }
+ var key = an.GetPublicKeyToken()
+ if (key != null) {
+ print(" .publickeytoken = ("); print(PEFile.bytes2hex(key))
+ println(")")
+ } else {
+ key = an.GetPublicKey()
+ if (key != null) {
+ print(" .publickey = ("); print(PEFile.bytes2hex(key))
+ println(")")
+ }
+ }
+ println("}")
+ }
+
+
+ def printSignature(field: FieldInfo) {
+ printSignature(field.FieldType)
+ //print(' ') print(owner)
+ print(' ')
+ //if (field.IsStatic && field.DeclaringType != currentType) {
+ printReference(field.DeclaringType)
+ print("::")
+ //}
+ printName(field.Name)
+ }
+
+ // print method head
+ @throws(classOf[IOException])
+ def printHeader(method: MethodBase, returnType: Type) {
+ print(MethodAttributes.toString(method.Attributes))
+ print(' '); print(CallingConventions.toString(method.CallingConvention))
+ print(' '); printSignature(returnType)
+ //print(' ') print(marshal)
+ print(' '); printName(method.Name)
+ val params = method.GetParameters()
+ print('(')
+ for (val i <- 0 until params.length) {
+ if (i > 0) print(", ")
+ print(params(i).asInstanceOf[ParameterBuilder])
+ }
+ print(") ")
+
+ print(MethodImplAttributes
+ .toString(method.GetMethodImplementationFlags()))
+ }
+
+
+ def printSignature(method: MethodBase) {
+ var returnType: Type = null
+ if (method.isInstanceOf[MethodInfo])
+ returnType = (method.asInstanceOf[MethodInfo]).ReturnType
+ else if (method.isInstanceOf[ConstructorInfo])
+ returnType = VOID
+ else
+ throw new RuntimeException()
+
+ val s = CallingConventions.toString(method.CallingConvention)
+ print(s)
+ if (s.length() > 0) print(' ')
+ printSignature(returnType)
+ //print(' ') print(owner)
+ print(' '); printReference(method.DeclaringType)
+ print("::"); printName(method.Name)
+
+ var params = method.GetParameters()
+ print("(")
+ for (val i <- 0 until params.length) {
+ if (i > 0) print(", ")
+ printSignature(params(i).ParameterType)
+ }
+ print(")")
+ }
+
+ def printSignature(`type`: Type) {
+ val sig : Object = primitive.get(`type`)
+ if (sig != null) {
+ print(sig)
+ return
+ }
+
+ if (`type`.HasElementType()) {
+ printSignature(`type`.GetElementType())
+ if (`type`.IsArray())
+ print("[]")
+ else if (`type`.IsPointer())
+ print('*')
+ else if (`type`.IsByRef())
+ print('&')
+ } else {
+ print(if(`type`.IsValueType()) "valuetype " else "class ")
+ printReference(`type`)
+ }
+ }
+
+ def printReference(`type`: Type) {
+ if (`type`.Assembly() != currentModule.Assembly) {
+ print('['); print(`type`.Assembly().GetName().Name); print("]")
+ } else if (`type`.Module != currentModule) {
+ print("[.module "); print(`type`.Module.Name); print("]")
+ }
+ printTypeName(`type`)
+ }
+
+ def printTypeName(`type`: Type) {
+ if (`type`.DeclaringType != null) {
+ printTypeName(`type`.DeclaringType)
+ print('/')
+ printName(`type`.Name)
+ } else {
+ printName(`type`.FullName)
+ }
+ }
+
+ def printAttributes(icap: ICustomAttributeProvider) {
+ var attrs = icap.GetCustomAttributes(false)
+ for (val i <- 0 until attrs.length) {
+ print(".custom ")
+ printSignature((attrs(i).asInstanceOf[Attribute]).getConstructor())
+ print(" = (")
+ print(PEFile.bytes2hex((attrs(i).asInstanceOf[Attribute]).getValue()))
+ println(")")
+ }
+ }
+
+ //##########################################################################
+
+} // class ILPrinterVisitor
+
+object ILPrinterVisitor {
+ final val VOID: Type = Type.GetType("System.Void")
+ protected final val TAB = 4
+
+ protected final val SPACES = " "
+ protected final val SPACES_LEN = SPACES.length()
+
+ def hasControlChars(str: String): Boolean = {
+ for(val i <- 0 until str.length()) {
+ var ch = str.charAt(i)
+ ch match {
+ case '\b' =>
+ case '\t' =>
+ case '\n' =>
+ case '\f' =>
+ case '\r' =>
+ case _ => if(Character.isISOControl(ch)) return true
+ }
+ }
+ return false
+ }
+
+ final val EMPTY: String = ""
+ def msilString(s: String): String = {
+ if (hasControlChars(s)) {
+ try {
+ return "bytearray (" + PEFile.bytes2hex(s.getBytes("UTF-16LE")) + ")"
+ } catch {
+ case e : java.io.UnsupportedEncodingException => throw new RuntimeException(e)
+ }
+ }
+ var str = new StringBuffer(s)
+ var ss = EMPTY
+ var i = 0
+ while(i < str.length()) {
+ ss = EMPTY
+ val c = str.charAt(i)
+ c match {
+ case '\b' => ss = "\\b"
+ case '\t' => ss = "\\t"
+ case '\n' => ss = "\\n"
+ case '\f' => ss = "\\f"
+ case '\r' => ss = "\\r"
+ case '\"' => ss = "\\\""
+ case '\'' => ss = "\\\'"
+ case '\\' => ss = "\\\\"
+ case _ => if (Character.isISOControl(c))
+ ss = "\\u" + PEFile.int2hex(Character.getNumericValue(c))
+ }
+ if (ss != EMPTY) {
+ str.replace(i, i + 1, ss)
+ i = i + ss.length() - 1
+ }
+ i = i + 1
+ }
+ return "\"" + str.toString() + "\""
+ }
+
+ /**
+ * the main printer method
+ */
+ @throws(classOf[IOException])
+ def printAssembly(assemblyBuilder: AssemblyBuilder, fileName: String) {
+ assemblyBuilder.apply(new SingleFileILPrinterVisitor(fileName))
+ }
+
+ @throws(classOf[IOException])
+ def printAssembly(assemblyBuilder: AssemblyBuilder, destPath: String, sourceFilesPath: String) {
+ assemblyBuilder.apply(new MultipleFilesILPrinterVisitor(destPath, sourceFilesPath))
+ }
+
+ /** The current assembly */
+ var currAssembly: Assembly = _
+
+ final var primitive = new HashMap[Type, String]()
+ def addPrimitive(name: String, sig: String) {
+ var `type` =
+ Type.GetType(name)
+ assert(`type` != null, "Cannot lookup primitive type " + `type`)
+ primitive.put(`type`, sig)
+ }
+
+ addPrimitive("System.Object", "object")
+ addPrimitive("System.String", "string")
+ addPrimitive("System.Void", "void")
+ addPrimitive("System.Boolean", "bool")
+ addPrimitive("System.Char", "char")
+ addPrimitive("System.SByte", "int8")
+ addPrimitive("System.Byte", "unsigned int8")
+ addPrimitive("System.Int16", "int16")
+ addPrimitive("System.UInt16", "unsigned int16")
+ addPrimitive("System.Int32", "int32")
+ addPrimitive("System.UInt32", "unsigned int32")
+ addPrimitive("System.Int64", "int64")
+ addPrimitive("System.UInt64", "unsigned int64")
+ addPrimitive("System.IntPtr", "native int")
+ addPrimitive("System.UIntPtr", "unsigned native int")
+ addPrimitive("System.Single", "float32")
+ addPrimitive("System.Double", "float64")
+ addPrimitive("System.TypedReference", "typedref")
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala
new file mode 100644
index 0000000000..e6ec60576f
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala
@@ -0,0 +1,149 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: Label.java 8550 2006-08-31 16:15:26Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.Type
+
+/**
+ * Represents a label in the instruction stream. Label is used in conjunction
+ * with the ILGenerator class.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+abstract class Label protected {
+ import Label._
+ def isInitialized(): Boolean
+ def getKind(): Kind
+ def getAddress(): Int
+ def getStacksize(): Int
+ def setStacksize(stacksize: Int): Unit
+ def incStacksize(): Unit
+ def mergeWith(that: Label): Unit
+}
+
+object Label {
+ final val DUMMY: Int = -((1<<31)-1)
+
+ //##########################################################################
+
+ final class NormalLabel(_address: Int, _stacksize: Int) extends Label {
+
+ //##########################################################################
+ // protected constructors
+
+ //the position of the label
+ private var address: Int = _address
+
+ //the stacksize at the label
+ private var stacksize: Int = _stacksize
+
+ def this() {
+ this(-1, DUMMY)
+ }
+
+ def this(that: NormalLabel) {
+ this(that.getAddress(), that.getStacksize())
+ }
+
+ //##########################################################################
+ // instrumental methods only used by ILGenerator
+
+ def isInitialized() = (getAddress() != -1) || (stacksize != DUMMY)
+
+ def getAddress() = address
+
+ def getStacksize() = stacksize
+
+ def setStacksize(stacksize: Int) {
+ assert(stacksize >= 0)
+ this.stacksize = stacksize
+ }
+
+ def incStacksize() {
+ stacksize = stacksize + 1
+ }
+
+ def getKind(): Kind = Kind.Normal
+
+ def mergeWith(that: Label) {
+ //assert address < 0 : "this.address = " + address + " that.address = " + that.address
+ address = that.getAddress()
+
+ // assert stacksize == that.stacksize
+ // : "this.stacksize = " + stacksize + " that.stacksize = "
+ // + that.stacksize
+ // stacksize = that.stacksize
+ val ss: Int = Math.max(stacksize, that.getStacksize())
+ stacksize = ss
+ that.setStacksize(ss)
+ }
+
+ //##########################################################################
+ //
+
+ /**
+ * the toString Method return the label name
+ * it's "IL" + address
+ */
+ override def toString(): String = {
+ var pad: String = ""
+ if (address < 16) pad = "000"
+ else if (address < 256) pad = "00"
+ else if (address < 4096) pad = "0"
+ return "IL_" + pad + Integer.toHexString(address)
+ }
+
+ def getString(): String = {
+ val name = super.toString()
+ val i: Int = name.lastIndexOf('.')
+ return name.substring(i+1, name.length())
+ }
+ }
+
+ //########################################################################
+ // Special Labels
+
+ final class SpecialLabel(_kind: Label.Kind) extends Label {
+ private final var kind: Label.Kind = _kind
+ def isInitialized() = true
+ def getAddress(): Int = { throw new RuntimeException("" + kind.toString()) }
+ def getStacksize(): Int = { throw new RuntimeException("" + kind.toString()) }
+ def setStacksize(stacksize: Int) { throw new RuntimeException(kind.toString()) }
+ def incStacksize() { throw new RuntimeException(kind.toString()) }
+ def getKind(): Kind = kind
+ def mergeWith(that: Label) { throw new RuntimeException(kind.toString()) }
+ override def toString(): String = "Label(" + kind.toString() + ")"
+ }
+
+ final val NewScope: Label = new SpecialLabel(Kind.NewScope)
+ final val EndScope: Label = new SpecialLabel(Kind.EndScope)
+ final val Try: Label = new SpecialLabel(Kind.Try)
+ final val Catch: Label = new SpecialLabel(Kind.Catch)
+ final val Filter: Label = new SpecialLabel(Kind.Filter)
+ final val EndFilter: Label = new SpecialLabel(Kind.EndFilter)
+ final val Finally: Label = new SpecialLabel(Kind.Finally)
+ final val EndTry: Label = new SpecialLabel(Kind.EndTry)
+
+ final class Kind() {}
+
+ final object Kind {
+ final val Normal: Kind = new Kind()
+
+ final val NewScope: Kind = new Kind()
+ final val EndScope: Kind = new Kind()
+
+ final val Try: Kind = new Kind()
+ final val Catch: Kind = new Kind()
+ final val Filter: Kind = new Kind()
+ final val EndFilter: Kind = new Kind()
+ final val Finally: Kind = new Kind()
+ final val EndTry: Kind = new Kind()
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/LocalBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/LocalBuilder.scala
new file mode 100644
index 0000000000..aabea9ba4e
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/LocalBuilder.scala
@@ -0,0 +1,45 @@
+/**
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: LocalBuilder.java 168 2005-12-12 14:20:06Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.Type
+
+/**
+ * Represents a local variable within a method or constructor.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class LocalBuilder(_slot : Int, localType : Type) extends Visitable {
+
+ /**
+ * the type of the local variable.
+ */
+ var LocalType : Type = localType
+
+ // the name of the local variable
+ var name : String = "L_" + slot
+
+ // the slot occupied by this local in the corresponding ILGenerator
+ var slot : Int = _slot
+
+ /**
+ * Sets the name of this local variable.
+ */
+ def SetLocalSymInfo(name : String) {
+ this.name = name
+ }
+
+ override def toString() : String = name
+
+ /**
+ * the apply method for a visitor
+ */
+ def apply(v : Visitor) {
+ v.caseLocalBuilder(this)
+ }
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/MethodBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/MethodBuilder.scala
new file mode 100644
index 0000000000..da5da79d53
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/MethodBuilder.scala
@@ -0,0 +1,71 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: MethodBuilder.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.MethodInfo
+import ch.epfl.lamp.compiler.msil.ParameterInfo
+import ch.epfl.lamp.compiler.msil.Type
+import ch.epfl.lamp.compiler.msil.ConstructorInfo
+import java.io.IOException
+
+/**
+ * Defines and represents a method of a dynamic class.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class MethodBuilder(name: String, declType: Type, attrs: Int, returnType: Type, paramTypes: Array[Type])
+ extends MethodInfo(name, declType, attrs, returnType, paramTypes)
+ with ICustomAttributeSetter
+ with Visitable
+{
+
+ //##########################################################################
+ // public interface
+
+ /** Defines a parameter of this method. TODO: Parameters are indexed staring
+ * from number 1 for the first parameter
+ */
+ def DefineParameter(pos: Int, attr: Int, name: String): ParameterBuilder = {
+ val param = new ParameterBuilder(name, params(pos).ParameterType, attr, pos)
+ params(pos) = param
+ return param
+ }
+
+ /** Returns an ILGenerator for this method. */
+ def GetILGenerator(): ILGenerator = {
+ if (ilGenerator == null)
+ throw new RuntimeException
+ ("No code generator avaiable for this method: " + this)
+ return ilGenerator
+ }
+
+ /** Sets a custom attribute. */
+ def SetCustomAttribute(constr: ConstructorInfo, value: Array[byte]) {
+ addCustomAttribute(constr, value)
+ }
+
+ //##########################################################################
+
+ /** The apply method for a visitor. */
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseMethodBuilder(this)
+ }
+
+ //##########################################################################
+
+ // the Intermediate Language Generator
+ // it contains the method's body
+ protected final val ilGenerator : ILGenerator =
+ if (DeclaringType == null // global method
+ || !DeclaringType.IsInterface())
+ new ILGenerator(this)
+ else null
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala
new file mode 100644
index 0000000000..211a965d69
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala
@@ -0,0 +1,134 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: ModuleBuilder.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil._
+import java.util.HashMap
+import java.util.ArrayList
+import java.io.IOException
+
+/**
+ * Defines and represents a module. Get an instance of ModuleBuilder
+ * by calling DefineDynamicModule
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly: Assembly)
+ extends Module(name, fullname, scopeName, assembly)
+ with ICustomAttributeSetter
+ with Visitable
+{
+
+ //##########################################################################
+ // public interface
+
+ /**
+ * Complete the global function definitions for this dynamic module.
+ * This method should be called when the user is done with defining
+ * all of the global functions within this dynamic module. After calling
+ * this function, no more new global functions or new global data are
+ * allowed.
+ */
+ def CreateGlobalFunctions() {
+ if (globalsCreated)
+ throw new RuntimeException("Global functions are already created")
+ this.fields = fieldBuilders.toArray(fields).asInstanceOf[Array[FieldInfo]]
+ this.methods = methodBuilders.toArray(methods).asInstanceOf[Array[MethodInfo]]
+ globalsCreated = true
+ }
+
+ /**
+ * Constructs a TypeBuilder for a type with the specified name
+ */
+ def DefineType(typeName: String): TypeBuilder = {
+ return DefineType(typeName, 0, null, Type.EmptyTypes)
+ }
+
+ /**
+ * Constructs a TypeBuilder for a type with the specified name
+ * and specified attributes
+ */
+ def DefineType(typeName: String, attributes: Int): TypeBuilder = {
+ return DefineType(typeName, attributes, null, Type.EmptyTypes)
+ }
+
+ /**
+ * Constructs a TypeBuilder given type name, its attributes,
+ * and the type that the defined type extends.
+ */
+ def DefineType(typeName: String, attributes: Int,
+ baseType: Type): TypeBuilder = {
+ return DefineType(typeName, attributes, baseType, Type.EmptyTypes)
+ }
+
+ /**
+ * Constructs a TypeBuilder given the Full specification of a type,
+ * Given the type name, attributes, the type that the defined type
+ * extends, and the interfaces that the defined type implements.
+ */
+ def DefineType(typeName: String,
+ attributes: Int,
+ baseType: Type,
+ interfaces: Array[Type]): TypeBuilder =
+ {
+ var t: Type = GetType(typeName) // Module.GetType(String)
+ if (t != null)
+ throw new RuntimeException
+ ("Type [" + Assembly + "]" + typeName + "' already exists!")
+ val `type` =
+ new TypeBuilder(this, attributes, typeName, baseType, interfaces, null)
+ addType(`type`)
+ return `type`
+ }
+
+ /**
+ * Defines a global method given its name, attributes, return type, and
+ * parameter types.
+ */
+ def DefineGlobalMethod(name: String, attributes: Int,
+ returnType: Type, paramTypes: Array[Type]): MethodBuilder =
+ {
+ val method =
+ new MethodBuilder(name, null, attributes, returnType, paramTypes)
+ methodBuilders.add(method)
+ return method
+ }
+
+
+ override def GetTypes(): Array[Type] = {
+ return typesMap.values().toArray(Type.EmptyTypes).asInstanceOf[Array[Type]]
+ }
+
+ /** Sets a custom attribute. */
+ def SetCustomAttribute(constr: ConstructorInfo, value: Array[byte]) {
+ addCustomAttribute(constr, value)
+ }
+
+ //##########################################################################
+ // internal members
+
+ var globalsCreated = false
+ protected var fieldBuilders = new ArrayList[FieldInfo]()
+ protected var methodBuilders = new ArrayList[MethodInfo]()
+
+ override def addType(t: Type): Type = {
+ return super.addType(t)
+ }
+
+ //##########################################################################
+
+ /**
+ * the apply method for a visitor
+ */
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseModuleBuilder(this)
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala
new file mode 100644
index 0000000000..63028f1f90
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala
@@ -0,0 +1,139 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies in MSIL
+ */
+
+// $Id: ILPrinterVisitor.java 8664 2006-09-12 16:48:03Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import java.io.File
+import java.io.FileWriter
+import java.io.BufferedWriter
+import java.io.PrintWriter
+import java.io.IOException
+import java.util.Iterator
+import java.util.HashMap
+import java.util.Arrays
+
+import ch.epfl.lamp.compiler.msil._
+import ch.epfl.lamp.compiler.msil.emit
+import ch.epfl.lamp.compiler.msil.util.Table
+
+/**
+ * The MSIL printer Vistor. It prints a complete
+ * assembly into seperate files. Then these files can be compiled by ilasm.
+ *
+ * @author Nikolay Mihaylov
+ * @author Daniel Lorch
+ * @version 1.0
+ */
+final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: String) extends ILPrinterVisitor {
+ /**
+ * Visit an AssemblyBuilder
+ */
+ @throws(classOf[IOException])
+ def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) {
+ ILPrinterVisitor.currAssembly = assemblyBuilder
+
+ // first get the entryPoint
+ this.entryPoint = assemblyBuilder.EntryPoint
+
+ // all external assemblies
+ as = assemblyBuilder.getExternAssemblies()
+ Arrays.sort(as, assemblyNameComparator)
+
+ // print each module
+ var m: Array[Module] = assemblyBuilder.GetModules()
+ nomembers = true
+ for(val i <- 0 until m.length) {
+ print(m(i).asInstanceOf[ModuleBuilder])
+ }
+
+ nomembers = false
+ for(val i <- 0 until m.length) {
+ print(m(i).asInstanceOf[ModuleBuilder])
+ }
+ ILPrinterVisitor.currAssembly = null
+ }
+
+ /**
+ * Visit a ModuleBuilder
+ */
+ @throws(classOf[IOException])
+ def caseModuleBuilder(module: ModuleBuilder) {
+ val assemblyBuilder = ILPrinterVisitor.currAssembly.asInstanceOf[AssemblyBuilder]
+
+ // print module declaration
+ currentModule = module
+
+ // global methods typically contain the main method
+ if (!module.globalsCreated)
+ module.CreateGlobalFunctions()
+
+ var m: Array[MethodInfo] = module.GetMethods()
+
+ // "Types" contain all the classes
+ var t: Array[Type] = module.GetTypes()
+ for(val i <- 0 until t.length) {
+ val tBuilder = t(i).asInstanceOf[TypeBuilder]
+ val sourceFilename = tBuilder.sourceFilename
+ val sourceFilepath = new File(tBuilder.sourceFilepath).getCanonicalPath
+ val sourcePath = new File(sourceFilesPath).getCanonicalPath
+ var append = false
+
+ if(!sourceFilepath.startsWith(sourcePath)) {
+ throw new IOException("Source file " + sourceFilename + " must lie inside sourcepath " + sourcePath)
+ }
+
+ assert(sourceFilepath.endsWith(".scala"), "Source file doesn't end with .scala")
+ val relativeFilename = sourceFilepath.substring(sourcePath.length, sourceFilepath.length() - 6) + ".msil"
+ val fileName = new File(destPath, relativeFilename)
+ if(assemblyBuilder.generatedFiles.contains(fileName.getPath)) {
+ append = true
+ } else {
+ fileName.getParentFile().mkdirs()
+ assemblyBuilder.generatedFiles.add(fileName.getPath)
+ }
+
+ out = new PrintWriter(new BufferedWriter(new FileWriter(fileName, append)))
+ // only write assembly boilerplate and class prototypes
+ if (!append && nomembers) {
+ printAssemblyBoilerplate()
+
+ print(".module \'"); print(module.Name); println("\'")
+ printAttributes(module)
+ }
+
+ print(t(i).asInstanceOf[TypeBuilder])
+ out.close()
+ }
+
+ // now write the global methods (typically contains the "main" method)
+ if(!nomembers) {
+ var globalMethods: File = new File(destPath, ILPrinterVisitor.currAssembly.GetName().Name + ".msil")
+ val append = assemblyBuilder.generatedFiles.contains(globalMethods.getPath)
+
+ out = new PrintWriter(new BufferedWriter(new FileWriter(globalMethods, append)))
+
+ // make sure we're the first in the list (ilasm uses the first file name to guess the output file name)
+ assemblyBuilder.generatedFiles.add(0, globalMethods.getPath)
+
+ // if this file hasn't been created by one of the classes, write boilerplate
+ if(!append) {
+ printAssemblyBoilerplate()
+
+ print(".module \'"); print(module.Name); println("\'")
+ printAttributes(module)
+ }
+
+ for(val i <- 0 until m.length) {
+ print(m(i).asInstanceOf[MethodBuilder])
+ }
+
+ out.close()
+ }
+
+ currentModule = null
+ }
+
+} // class MultipleFilesILPrinterVisitor
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala
new file mode 100644
index 0000000000..c6ff59ba66
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCode.scala
@@ -0,0 +1,1935 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: OpCode.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import java.io.IOException
+
+/** Describes a Microsoft intermediate language (MSIL) instruction.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class OpCode extends Visitable {
+ import OpCode._
+
+ /** The Operation Code of Microsoft intermediate language (MSIL) instruction. */
+ var CEE_opcode : Int = _
+
+ /** The name of the Microsoft intermediate language (MSIL) instruction. */
+ var CEE_string: String = _
+
+ /** The type of Microsoft intermediate language (MSIL) instruction. */
+ var CEE_code: short = _
+
+ /** How the Microsoft intermediate language (MSIL) instruction pops the stack. */
+ var CEE_pop: byte = _
+
+ /** How the Microsoft intermediate language (MSIL) instruction pushes operand onto the stack. */
+ var CEE_push: byte = _
+
+ /** Describes the type of flow control. */
+ var CEE_flow: byte = _
+
+ /** ????? */
+ var CEE_inline: byte = _
+
+ var CEE_length: byte = _
+
+ var CEE_popush: byte = _
+
+ /**
+ * the apply method for a visitor
+ */
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseOpCode(this)
+ }
+
+ protected def length(): byte = {
+ val code = OpCode.length(CEE_code)
+ val inline = OpCode.INLINE_length(CEE_inline)
+ return if(inline < 0) { -1 } else { (code + inline).asInstanceOf[byte] }
+ }
+
+ protected def popush(): byte = {
+ val pop = OpCode.POP_size(CEE_pop)
+ val push = OpCode.PUSH_size(CEE_push)
+ return if(pop < 0 || push < 0) { OpCode.POPUSH_SPECIAL } else { (push - pop).asInstanceOf[byte] }
+ }
+
+ override def toString(): String = {
+ return CEE_string
+ }
+}
+
+object OpCode {
+
+ //########################################################################
+ // Common Execution Environment opcodes
+
+ final val CEE_NOP : Int = 0x0000
+ final val CEE_BREAK : Int = 0x0001
+ final val CEE_LDARG_0 : Int = 0x0002
+ final val CEE_LDARG_1 : Int = 0x0003
+ final val CEE_LDARG_2 : Int = 0x0004
+ final val CEE_LDARG_3 : Int = 0x0005
+ final val CEE_LDLOC_0 : Int = 0x0006
+ final val CEE_LDLOC_1 : Int = 0x0007
+ final val CEE_LDLOC_2 : Int = 0x0008
+ final val CEE_LDLOC_3 : Int = 0x0009
+ final val CEE_STLOC_0 : Int = 0x000A
+ final val CEE_STLOC_1 : Int = 0x000B
+ final val CEE_STLOC_2 : Int = 0x000C
+ final val CEE_STLOC_3 : Int = 0x000D
+ final val CEE_LDARG_S : Int = 0x000E
+ final val CEE_LDARGA_S : Int = 0x000F
+ final val CEE_STARG_S : Int = 0x0010
+ final val CEE_LDLOC_S : Int = 0x0011
+ final val CEE_LDLOCA_S : Int = 0x0012
+ final val CEE_STLOC_S : Int = 0x0013
+ final val CEE_LDNULL : Int = 0x0014
+ final val CEE_LDC_I4_M1 : Int = 0x0015
+ final val CEE_LDC_I4_0 : Int = 0x0016
+ final val CEE_LDC_I4_1 : Int = 0x0017
+ final val CEE_LDC_I4_2 : Int = 0x0018
+ final val CEE_LDC_I4_3 : Int = 0x0019
+ final val CEE_LDC_I4_4 : Int = 0x001A
+ final val CEE_LDC_I4_5 : Int = 0x001B
+ final val CEE_LDC_I4_6 : Int = 0x001C
+ final val CEE_LDC_I4_7 : Int = 0x001D
+ final val CEE_LDC_I4_8 : Int = 0x001E
+ final val CEE_LDC_I4_S : Int = 0x001F
+ final val CEE_LDC_I4 : Int = 0x0020
+ final val CEE_LDC_I8 : Int = 0x0021
+ final val CEE_LDC_R4 : Int = 0x0022
+ final val CEE_LDC_R8 : Int = 0x0023
+ final val CEE_UNUSED49 : Int = 0x0024
+ final val CEE_DUP : Int = 0x0025
+ final val CEE_POP : Int = 0x0026
+ final val CEE_JMP : Int = 0x0027
+ final val CEE_CALL : Int = 0x0028
+ final val CEE_CALLI : Int = 0x0029
+ final val CEE_RET : Int = 0x002A
+ final val CEE_BR_S : Int = 0x002B
+ final val CEE_BRFALSE_S : Int = 0x002C
+ final val CEE_BRTRUE_S : Int = 0x002D
+ final val CEE_BEQ_S : Int = 0x002E
+ final val CEE_BGE_S : Int = 0x002F
+ final val CEE_BGT_S : Int = 0x0030
+ final val CEE_BLE_S : Int = 0x0031
+ final val CEE_BLT_S : Int = 0x0032
+ final val CEE_BNE_UN_S : Int = 0x0033
+ final val CEE_BGE_UN_S : Int = 0x0034
+ final val CEE_BGT_UN_S : Int = 0x0035
+ final val CEE_BLE_UN_S : Int = 0x0036
+ final val CEE_BLT_UN_S : Int = 0x0037
+ final val CEE_BR : Int = 0x0038
+ final val CEE_BRFALSE : Int = 0x0039
+ final val CEE_BRTRUE : Int = 0x003A
+ final val CEE_BEQ : Int = 0x003B
+ final val CEE_BGE : Int = 0x003C
+ final val CEE_BGT : Int = 0x003D
+ final val CEE_BLE : Int = 0x003E
+ final val CEE_BLT : Int = 0x003F
+ final val CEE_BNE_UN : Int = 0x0040
+ final val CEE_BGE_UN : Int = 0x0041
+ final val CEE_BGT_UN : Int = 0x0042
+ final val CEE_BLE_UN : Int = 0x0043
+ final val CEE_BLT_UN : Int = 0x0044
+ final val CEE_SWITCH : Int = 0x0045
+ final val CEE_LDIND_I1 : Int = 0x0046
+ final val CEE_LDIND_U1 : Int = 0x0047
+ final val CEE_LDIND_I2 : Int = 0x0048
+ final val CEE_LDIND_U2 : Int = 0x0049
+ final val CEE_LDIND_I4 : Int = 0x004A
+ final val CEE_LDIND_U4 : Int = 0x004B
+ final val CEE_LDIND_I8 : Int = 0x004C
+ final val CEE_LDIND_I : Int = 0x004D
+ final val CEE_LDIND_R4 : Int = 0x004E
+ final val CEE_LDIND_R8 : Int = 0x004F
+ final val CEE_LDIND_REF : Int = 0x0050
+ final val CEE_STIND_REF : Int = 0x0051
+ final val CEE_STIND_I1 : Int = 0x0052
+ final val CEE_STIND_I2 : Int = 0x0053
+ final val CEE_STIND_I4 : Int = 0x0054
+ final val CEE_STIND_I8 : Int = 0x0055
+ final val CEE_STIND_R4 : Int = 0x0056
+ final val CEE_STIND_R8 : Int = 0x0057
+ final val CEE_ADD : Int = 0x0058
+ final val CEE_SUB : Int = 0x0059
+ final val CEE_MUL : Int = 0x005A
+ final val CEE_DIV : Int = 0x005B
+ final val CEE_DIV_UN : Int = 0x005C
+ final val CEE_REM : Int = 0x005D
+ final val CEE_REM_UN : Int = 0x005E
+ final val CEE_AND : Int = 0x005F
+ final val CEE_OR : Int = 0x0060
+ final val CEE_XOR : Int = 0x0061
+ final val CEE_SHL : Int = 0x0062
+ final val CEE_SHR : Int = 0x0063
+ final val CEE_SHR_UN : Int = 0x0064
+ final val CEE_NEG : Int = 0x0065
+ final val CEE_NOT : Int = 0x0066
+ final val CEE_CONV_I1 : Int = 0x0067
+ final val CEE_CONV_I2 : Int = 0x0068
+ final val CEE_CONV_I4 : Int = 0x0069
+ final val CEE_CONV_I8 : Int = 0x006A
+ final val CEE_CONV_R4 : Int = 0x006B
+ final val CEE_CONV_R8 : Int = 0x006C
+ final val CEE_CONV_U4 : Int = 0x006D
+ final val CEE_CONV_U8 : Int = 0x006E
+ final val CEE_CALLVIRT : Int = 0x006F
+ final val CEE_CPOBJ : Int = 0x0070
+ final val CEE_LDOBJ : Int = 0x0071
+ final val CEE_LDSTR : Int = 0x0072
+ final val CEE_NEWOBJ : Int = 0x0073
+ final val CEE_CASTCLASS : Int = 0x0074
+ final val CEE_ISINST : Int = 0x0075
+ final val CEE_CONV_R_UN : Int = 0x0076
+ final val CEE_UNUSED58 : Int = 0x0077
+ final val CEE_UNUSED1 : Int = 0x0078
+ final val CEE_UNBOX : Int = 0x0079
+ final val CEE_THROW : Int = 0x007A
+ final val CEE_LDFLD : Int = 0x007B
+ final val CEE_LDFLDA : Int = 0x007C
+ final val CEE_STFLD : Int = 0x007D
+ final val CEE_LDSFLD : Int = 0x007E
+ final val CEE_LDSFLDA : Int = 0x007F
+ final val CEE_STSFLD : Int = 0x0080
+ final val CEE_STOBJ : Int = 0x0081
+ final val CEE_CONV_OVF_I1_UN : Int = 0x0082
+ final val CEE_CONV_OVF_I2_UN : Int = 0x0083
+ final val CEE_CONV_OVF_I4_UN : Int = 0x0084
+ final val CEE_CONV_OVF_I8_UN : Int = 0x0085
+ final val CEE_CONV_OVF_U1_UN : Int = 0x0086
+ final val CEE_CONV_OVF_U2_UN : Int = 0x0087
+ final val CEE_CONV_OVF_U4_UN : Int = 0x0088
+ final val CEE_CONV_OVF_U8_UN : Int = 0x0089
+ final val CEE_CONV_OVF_I_UN : Int = 0x008A
+ final val CEE_CONV_OVF_U_UN : Int = 0x008B
+ final val CEE_BOX : Int = 0x008C
+ final val CEE_NEWARR : Int = 0x008D
+ final val CEE_LDLEN : Int = 0x008E
+ final val CEE_LDELEMA : Int = 0x008F
+ final val CEE_LDELEM_I1 : Int = 0x0090
+ final val CEE_LDELEM_U1 : Int = 0x0091
+ final val CEE_LDELEM_I2 : Int = 0x0092
+ final val CEE_LDELEM_U2 : Int = 0x0093
+ final val CEE_LDELEM_I4 : Int = 0x0094
+ final val CEE_LDELEM_U4 : Int = 0x0095
+ final val CEE_LDELEM_I8 : Int = 0x0096
+ final val CEE_LDELEM_I : Int = 0x0097
+ final val CEE_LDELEM_R4 : Int = 0x0098
+ final val CEE_LDELEM_R8 : Int = 0x0099
+ final val CEE_LDELEM_REF : Int = 0x009A
+ final val CEE_STELEM_I : Int = 0x009B
+ final val CEE_STELEM_I1 : Int = 0x009C
+ final val CEE_STELEM_I2 : Int = 0x009D
+ final val CEE_STELEM_I4 : Int = 0x009E
+ final val CEE_STELEM_I8 : Int = 0x009F
+ final val CEE_STELEM_R4 : Int = 0x00A0
+ final val CEE_STELEM_R8 : Int = 0x00A1
+ final val CEE_STELEM_REF : Int = 0x00A2
+ final val CEE_UNUSED2 : Int = 0x00A3
+ final val CEE_UNUSED3 : Int = 0x00A4
+ final val CEE_UNUSED4 : Int = 0x00A5
+ final val CEE_UNUSED5 : Int = 0x00A6
+ final val CEE_UNUSED6 : Int = 0x00A7
+ final val CEE_UNUSED7 : Int = 0x00A8
+ final val CEE_UNUSED8 : Int = 0x00A9
+ final val CEE_UNUSED9 : Int = 0x00AA
+ final val CEE_UNUSED10 : Int = 0x00AB
+ final val CEE_UNUSED11 : Int = 0x00AC
+ final val CEE_UNUSED12 : Int = 0x00AD
+ final val CEE_UNUSED13 : Int = 0x00AE
+ final val CEE_UNUSED14 : Int = 0x00AF
+ final val CEE_UNUSED15 : Int = 0x00B0
+ final val CEE_UNUSED16 : Int = 0x00B1
+ final val CEE_UNUSED17 : Int = 0x00B2
+ final val CEE_CONV_OVF_I1 : Int = 0x00B3
+ final val CEE_CONV_OVF_U1 : Int = 0x00B4
+ final val CEE_CONV_OVF_I2 : Int = 0x00B5
+ final val CEE_CONV_OVF_U2 : Int = 0x00B6
+ final val CEE_CONV_OVF_I4 : Int = 0x00B7
+ final val CEE_CONV_OVF_U4 : Int = 0x00B8
+ final val CEE_CONV_OVF_I8 : Int = 0x00B9
+ final val CEE_CONV_OVF_U8 : Int = 0x00BA
+ final val CEE_UNUSED50 : Int = 0x00BB
+ final val CEE_UNUSED18 : Int = 0x00BC
+ final val CEE_UNUSED19 : Int = 0x00BD
+ final val CEE_UNUSED20 : Int = 0x00BE
+ final val CEE_UNUSED21 : Int = 0x00BF
+ final val CEE_UNUSED22 : Int = 0x00C0
+ final val CEE_UNUSED23 : Int = 0x00C1
+ final val CEE_REFANYVAL : Int = 0x00C2
+ final val CEE_CKFINITE : Int = 0x00C3
+ final val CEE_UNUSED24 : Int = 0x00C4
+ final val CEE_UNUSED25 : Int = 0x00C5
+ final val CEE_MKREFANY : Int = 0x00C6
+ final val CEE_UNUSED59 : Int = 0x00C7
+ final val CEE_UNUSED60 : Int = 0x00C8
+ final val CEE_UNUSED61 : Int = 0x00C9
+ final val CEE_UNUSED62 : Int = 0x00CA
+ final val CEE_UNUSED63 : Int = 0x00CB
+ final val CEE_UNUSED64 : Int = 0x00CC
+ final val CEE_UNUSED65 : Int = 0x00CD
+ final val CEE_UNUSED66 : Int = 0x00CE
+ final val CEE_UNUSED67 : Int = 0x00CF
+ final val CEE_LDTOKEN : Int = 0x00D0
+ final val CEE_CONV_U2 : Int = 0x00D1
+ final val CEE_CONV_U1 : Int = 0x00D2
+ final val CEE_CONV_I : Int = 0x00D3
+ final val CEE_CONV_OVF_I : Int = 0x00D4
+ final val CEE_CONV_OVF_U : Int = 0x00D5
+ final val CEE_ADD_OVF : Int = 0x00D6
+ final val CEE_ADD_OVF_UN : Int = 0x00D7
+ final val CEE_MUL_OVF : Int = 0x00D8
+ final val CEE_MUL_OVF_UN : Int = 0x00D9
+ final val CEE_SUB_OVF : Int = 0x00DA
+ final val CEE_SUB_OVF_UN : Int = 0x00DB
+ final val CEE_ENDFINALLY : Int = 0x00DC
+ final val CEE_LEAVE : Int = 0x00DD
+ final val CEE_LEAVE_S : Int = 0x00DE
+ final val CEE_STIND_I : Int = 0x00DF
+ final val CEE_CONV_U : Int = 0x00E0
+ final val CEE_UNUSED26 : Int = 0x00E1
+ final val CEE_UNUSED27 : Int = 0x00E2
+ final val CEE_UNUSED28 : Int = 0x00E3
+ final val CEE_UNUSED29 : Int = 0x00E4
+ final val CEE_UNUSED30 : Int = 0x00E5
+ final val CEE_UNUSED31 : Int = 0x00E6
+ final val CEE_UNUSED32 : Int = 0x00E7
+ final val CEE_UNUSED33 : Int = 0x00E8
+ final val CEE_UNUSED34 : Int = 0x00E9
+ final val CEE_UNUSED35 : Int = 0x00EA
+ final val CEE_UNUSED36 : Int = 0x00EB
+ final val CEE_UNUSED37 : Int = 0x00EC
+ final val CEE_UNUSED38 : Int = 0x00ED
+ final val CEE_UNUSED39 : Int = 0x00EE
+ final val CEE_UNUSED40 : Int = 0x00EF
+ final val CEE_UNUSED41 : Int = 0x00F0
+ final val CEE_UNUSED42 : Int = 0x00F1
+ final val CEE_UNUSED43 : Int = 0x00F2
+ final val CEE_UNUSED44 : Int = 0x00F3
+ final val CEE_UNUSED45 : Int = 0x00F4
+ final val CEE_UNUSED46 : Int = 0x00F5
+ final val CEE_UNUSED47 : Int = 0x00F6
+ final val CEE_UNUSED48 : Int = 0x00F7
+ final val CEE_PREFIX7 : Int = 0x00F8
+ final val CEE_PREFIX6 : Int = 0x00F9
+ final val CEE_PREFIX5 : Int = 0x00FA
+ final val CEE_PREFIX4 : Int = 0x00FB
+ final val CEE_PREFIX3 : Int = 0x00FC
+ final val CEE_PREFIX2 : Int = 0x00FD
+ final val CEE_PREFIX1 : Int = 0x00FE
+ final val CEE_PREFIXREF : Int = 0x00FF
+
+ final val CEE_ARGLIST : Int = 0x0100
+ final val CEE_CEQ : Int = 0x0101
+ final val CEE_CGT : Int = 0x0102
+ final val CEE_CGT_UN : Int = 0x0103
+ final val CEE_CLT : Int = 0x0104
+ final val CEE_CLT_UN : Int = 0x0105
+ final val CEE_LDFTN : Int = 0x0106
+ final val CEE_LDVIRTFTN : Int = 0x0107
+ final val CEE_UNUSED56 : Int = 0x0108
+ final val CEE_LDARG : Int = 0x0109
+ final val CEE_LDARGA : Int = 0x010A
+ final val CEE_STARG : Int = 0x010B
+ final val CEE_LDLOC : Int = 0x010C
+ final val CEE_LDLOCA : Int = 0x010D
+ final val CEE_STLOC : Int = 0x010E
+ final val CEE_LOCALLOC : Int = 0x010F
+ final val CEE_UNUSED57 : Int = 0x0110
+ final val CEE_ENDFILTER : Int = 0x0111
+ final val CEE_UNALIGNED : Int = 0x0112
+ final val CEE_VOLATILE : Int = 0x0113
+ final val CEE_TAILCALL : Int = 0x0114
+ final val CEE_INITOBJ : Int = 0x0115
+ final val CEE_UNUSED68 : Int = 0x0116
+ final val CEE_CPBLK : Int = 0x0117
+ final val CEE_INITBLK : Int = 0x0118
+ final val CEE_UNUSED69 : Int = 0x0119
+ final val CEE_RETHROW : Int = 0x011A
+ final val CEE_UNUSED51 : Int = 0x011B
+ final val CEE_SIZEOF : Int = 0x011C
+ final val CEE_REFANYTYPE : Int = 0x011D
+ final val CEE_UNUSED52 : Int = 0x011E
+ final val CEE_UNUSED53 : Int = 0x011F
+ final val CEE_UNUSED54 : Int = 0x0120
+ final val CEE_UNUSED55 : Int = 0x0121
+ final val CEE_UNUSED70 : Int = 0x0122
+
+ final val CEE_ILLEGAL : Int = 0x0140
+ final val CEE_MACRO_END : Int = 0x0141
+
+ final val CEE_BRNULL : Int = 0x0180 // CEE_BRFALSE
+ final val CEE_BRNULL_S : Int = 0x0181 // CEE_BRFALSE_S
+ final val CEE_BRZERO : Int = 0x0182 // CEE_BRFALSE
+ final val CEE_BRZERO_S : Int = 0x0183 // CEE_BRFALSE_S
+ final val CEE_BRINST : Int = 0x0184 // CEE_BRTRUE
+ final val CEE_BRINST_S : Int = 0x0185 // CEE_BRTRUE_S
+ final val CEE_LDIND_U8 : Int = 0x0186 // CEE_LDIND_I8
+ final val CEE_LDELEM_U8 : Int = 0x0187 // CEE_LDELEM_I8
+ final val CEE_LDC_I4_M1x : Int = 0x0188 // CEE_LDC_I4_M1
+ final val CEE_ENDFAULT : Int = 0x0189 // CEE_ENDFINALLY
+
+ final val CEE_BRNONZERO : Int = 0x01C0 // CEE_BRTRUE
+ final val CEE_BRNONZERO_S : Int = 0x01C1 // CEE_BRTRUE_S
+
+ final val CEE_BRNOT : Int = 0x01C2
+ final val CEE_BRNOT_S : Int = 0x01C3
+ final val CEE_NOCODE : Int = 0x01C4
+
+ final val CEE_count : Int = 0x0200
+
+
+ //########################################################################
+ // Opcode's amount and type of poped data
+
+ final val POP_NONE : byte = 0x00
+ final val POP_1 : byte = 0x01
+ final val POP_1_1 : byte = 0x02
+ final val POP_I : byte = 0x03
+ final val POP_I_1 : byte = 0x04
+ final val POP_I_I : byte = 0x05
+ final val POP_I_I8 : byte = 0x06
+ final val POP_I_R4 : byte = 0x07
+ final val POP_I_R8 : byte = 0x08
+ final val POP_I_I_I : byte = 0x09
+ final val POP_REF : byte = 0x0A
+ final val POP_REF_1 : byte = 0x0B
+ final val POP_REF_I : byte = 0x0C
+ final val POP_REF_I_I : byte = 0x0D
+ final val POP_REF_I_I8 : byte = 0x0E
+ final val POP_REF_I_R4 : byte = 0x0F
+ final val POP_REF_I_R8 : byte = 0x10
+ final val POP_REF_I_REF : byte = 0x11
+ final val POP_SPECIAL : byte = 0x12
+ final val POP_count : Int = 0x13
+ final val POP_size : Array[byte] = new Array[byte](POP_count)
+
+ POP_size(POP_NONE) = 0
+ POP_size(POP_1) = 1
+ POP_size(POP_1_1) = 2
+ POP_size(POP_I) = 1
+ POP_size(POP_I_1) = 2
+ POP_size(POP_I_I) = 2
+ POP_size(POP_I_I8) = 2
+ POP_size(POP_I_R4) = 2
+ POP_size(POP_I_R8) = 2
+ POP_size(POP_I_I_I) = 3
+ POP_size(POP_REF) = 1
+ POP_size(POP_REF_1) = 2
+ POP_size(POP_REF_I) = 2
+ POP_size(POP_REF_I_I) = 3
+ POP_size(POP_REF_I_I8) = 3
+ POP_size(POP_REF_I_R4) = 3
+ POP_size(POP_REF_I_R8) = 3
+ POP_size(POP_REF_I_REF) = 3
+ POP_size(POP_SPECIAL) = -1
+
+ //########################################################################
+ // Opcode's amount and type of pushed data
+
+ final val PUSH_NONE : byte = 0x00
+ final val PUSH_1 : byte = 0x01
+ final val PUSH_1_1 : byte = 0x02
+ final val PUSH_I : byte = 0x03
+ final val PUSH_I8 : byte = 0x04
+ final val PUSH_R4 : byte = 0x05
+ final val PUSH_R8 : byte = 0x06
+ final val PUSH_REF : byte = 0x07
+ final val PUSH_SPECIAL : byte = 0x08
+ final val PUSH_count : Int = 0x09
+ final val PUSH_size : Array[byte] = new Array[byte](PUSH_count)
+
+ PUSH_size(PUSH_NONE) = 0
+ PUSH_size(PUSH_1) = 1
+ PUSH_size(PUSH_1_1) = 2
+ PUSH_size(PUSH_I) = 1
+ PUSH_size(PUSH_I8) = 1
+ PUSH_size(PUSH_R4) = 1
+ PUSH_size(PUSH_R8) = 1
+ PUSH_size(PUSH_REF) = 1
+ PUSH_size(PUSH_SPECIAL) = -1
+
+ //########################################################################
+ // Opcode's amount of moved data
+
+ final val POPUSH_SPECIAL : byte = -128
+
+ //########################################################################
+ // Opcode's inline argument types
+
+ final val INLINE_NONE : byte = 0x00
+ final val INLINE_VARIABLE_S : byte = 0x01
+ final val INLINE_TARGET_S : byte = 0x02
+ final val INLINE_I_S : byte = 0x03
+ final val INLINE_VARIABLE : byte = 0x04
+ final val INLINE_TARGET : byte = 0x05
+ final val INLINE_I : byte = 0x06
+ final val INLINE_I8 : byte = 0x07
+ final val INLINE_R : byte = 0x08
+ final val INLINE_R8 : byte = 0x09
+ final val INLINE_STRING : byte = 0x0A
+ final val INLINE_TYPE : byte = 0x0B
+ final val INLINE_FIELD : byte = 0x0C
+ final val INLINE_METHOD : byte = 0x0D
+ final val INLINE_SIGNATURE : byte = 0x0E
+ final val INLINE_TOKEN : byte = 0x0F
+ final val INLINE_SWITCH : byte = 0x10
+ final val INLINE_count : Int = 0x11
+ final val INLINE_length : Array[byte] = new Array[byte](INLINE_count)
+
+ INLINE_length(INLINE_NONE) = 0
+ INLINE_length(INLINE_VARIABLE_S) = 1
+ INLINE_length(INLINE_TARGET_S) = 1
+ INLINE_length(INLINE_I_S) = 1
+ INLINE_length(INLINE_VARIABLE) = 2
+ INLINE_length(INLINE_TARGET) = 4
+ INLINE_length(INLINE_I) = 4
+ INLINE_length(INLINE_I8) = 8
+ INLINE_length(INLINE_R) = 4
+ INLINE_length(INLINE_R8) = 8
+ INLINE_length(INLINE_STRING) = 4
+ INLINE_length(INLINE_TYPE) = 4
+ INLINE_length(INLINE_FIELD) = 4
+ INLINE_length(INLINE_METHOD) = 4
+ INLINE_length(INLINE_SIGNATURE) = 4
+ INLINE_length(INLINE_SWITCH) = 4
+ INLINE_length(INLINE_TOKEN) = 4
+
+ //########################################################################
+ // Opcode's control flow implications
+
+ final val FLOW_META : byte = 0x00
+ final val FLOW_NEXT : byte = 0x01
+ final val FLOW_BRANCH : byte = 0x02
+ final val FLOW_COND_BRANCH : byte = 0x03
+ final val FLOW_BREAK : byte = 0x04
+ final val FLOW_CALL : byte = 0x05
+ final val FLOW_RETURN : byte = 0x06
+ final val FLOW_THROW : byte = 0x07
+ final val FLOW_count : Int = 0x08
+
+ //########################################################################
+ // Init methods for Opcode
+
+ def opcode(that: OpCode, opcode: int, string: String, code: Int,
+ pop: byte, push: byte, inline: byte, flow: byte) {
+ that.CEE_opcode = opcode
+ that.CEE_string = string
+ that.CEE_code = code.asInstanceOf[short]
+ that.CEE_pop = pop
+ that.CEE_push = push
+ that.CEE_inline = inline
+ that.CEE_flow = flow
+ that.CEE_length = that.length()
+ that.CEE_popush = that.popush()
+ }
+
+ def length(code: Int): byte = {
+ if ((code & 0xFFFFFF00) == 0xFFFFFF00) return 1
+ if ((code & 0xFFFFFF00) == 0xFFFFFE00) return 2
+ return 0
+ }
+
+ //########################################################################
+ // case OpCode
+
+ /**
+ * Adds two values and pushes the result onto the evaluation stack.
+ */
+ final val Add = new OpCode()
+ opcode(Add, CEE_ADD, "add", 0xFFFFFF58, POP_1_1, PUSH_1, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Fills space if bytecodes are patched. No meaningful operation is performed
+ * although a processing cycle can be consumed.
+ */
+ final val Nop = new OpCode()
+ opcode(Nop, CEE_NOP, "nop", 0xFFFFFF00, POP_NONE, PUSH_NONE, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Signals the Common Language Infrastructure (CLI) to inform the debugger that
+ * a break point has been tripped.
+ */
+ final val Break = new OpCode()
+ opcode(Break, CEE_BREAK, "break" , 0xFFFFFF01, POP_NONE, PUSH_NONE , INLINE_NONE , FLOW_BREAK)
+
+ /**
+ * Loads the argument at index 0 onto the evaluation stack.
+ */
+ final val Ldarg_0 = new OpCode()
+ opcode(Ldarg_0, CEE_LDARG_0 , "ldarg.0" , 0xFFFFFF02, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the argument at index 1 onto the evaluation stack.
+ */
+ final val Ldarg_1 = new OpCode()
+ opcode(Ldarg_1, CEE_LDARG_1 , "ldarg.1" , 0xFFFFFF03, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the argument at index 2 onto the evaluation stack.
+ */
+ final val Ldarg_2 = new OpCode()
+ opcode(Ldarg_2, CEE_LDARG_2 , "ldarg.2" , 0xFFFFFF04, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the argument at index 3 onto the evaluation stack.
+ */
+ final val Ldarg_3 = new OpCode()
+ opcode(Ldarg_3, CEE_LDARG_3 , "ldarg.3" , 0xFFFFFF05, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the local variable at index 0 onto the evaluation stack.
+ */
+ final val Ldloc_0 = new OpCode()
+ opcode(Ldloc_0, CEE_LDLOC_0 , "ldloc.0" , 0xFFFFFF06, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the local variable at index 1 onto the evaluation stack.
+ */
+ final val Ldloc_1 = new OpCode()
+ opcode(Ldloc_1, CEE_LDLOC_1 , "ldloc.1" , 0xFFFFFF07, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the local variable at index 2 onto the evaluation stack.
+ */
+ final val Ldloc_2 = new OpCode()
+ opcode(Ldloc_2, CEE_LDLOC_2 , "ldloc.2" , 0xFFFFFF08, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the local variable at index 3 onto the evaluation stack.
+ */
+ final val Ldloc_3 = new OpCode()
+ opcode(Ldloc_3, CEE_LDLOC_3 , "ldloc.3" , 0xFFFFFF09, POP_NONE, PUSH_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Pops the current value from the top of the evaluation stack and
+ * stores it in a the local variable list at index 0.
+ */
+ final val Stloc_0 = new OpCode()
+ opcode(Stloc_0, CEE_STLOC_0 , "stloc.0" , 0xFFFFFF0A, POP_1 , PUSH_NONE, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Pops the current value from the top of the evaluation stack and
+ * stores it in a the local variable list at index 1.
+ */
+ final val Stloc_1 = new OpCode()
+ opcode(Stloc_1, CEE_STLOC_1 , "stloc.1" , 0xFFFFFF0B, POP_1 , PUSH_NONE, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Pops the current value from the top of the evaluation stack and
+ * stores it in a the local variable list at index 2.
+ */
+ final val Stloc_2 = new OpCode()
+ opcode(Stloc_2, CEE_STLOC_2 , "stloc.2" , 0xFFFFFF0C, POP_1 , PUSH_NONE, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Pops the current value from the top of the evaluation stack and
+ * stores it in a the local variable list at index 3.
+ */
+ final val Stloc_3 = new OpCode()
+ opcode(Stloc_3, CEE_STLOC_3 , "stloc.3" , 0xFFFFFF0D, POP_1 , PUSH_NONE, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the argument (referenced by a specified short form index)
+ * onto the evaluation stack.
+ */
+ final val Ldarg_S = new OpCode()
+ opcode(Ldarg_S, CEE_LDARG_S , "ldarg.s" , 0xFFFFFF0E, POP_NONE, PUSH_1 , INLINE_VARIABLE_S, FLOW_NEXT)
+
+ /**
+ * Load an argument address, in short form, onto the evaluation stack.
+ */
+ final val Ldarga_S = new OpCode()
+ opcode(Ldarga_S, CEE_LDARGA_S , "ldarga.s" , 0xFFFFFF0F, POP_NONE, PUSH_I , INLINE_VARIABLE_S, FLOW_NEXT)
+
+ /**
+ * Loads the local variable at a specific index onto the evaluation stack,
+ * short form.
+ */
+ final val Ldloc_S = new OpCode()
+ opcode(Ldloc_S, CEE_LDLOC_S , "ldloc.s" , 0xFFFFFF11, POP_NONE, PUSH_1 , INLINE_VARIABLE_S, FLOW_NEXT)
+
+ /**
+ * Loads the address of the local variable at a specific index onto
+ * the evaluation stack, short form.
+ */
+ final val Ldloca_S = new OpCode()
+ opcode(Ldloca_S, CEE_LDLOCA_S , "ldloca.s" , 0xFFFFFF12, POP_NONE, PUSH_I , INLINE_VARIABLE_S, FLOW_NEXT)
+
+ /**
+ * Stores the value on top of the evaluation stack in the argument slot
+ * at a specified index, short form.
+ */
+ final val Starg_S = new OpCode()
+ opcode(Starg_S, CEE_STARG_S , "starg.s" , 0xFFFFFF10, POP_1 , PUSH_NONE , INLINE_VARIABLE_S, FLOW_NEXT)
+
+ /**
+ * Pops the current value from the top of the evaluation stack and stores it
+ * in a the local variable list at index (short form).
+ */
+ final val Stloc_S = new OpCode()
+ opcode(Stloc_S, CEE_STLOC_S , "stloc.s" , 0xFFFFFF13, POP_1 , PUSH_NONE, INLINE_VARIABLE_S, FLOW_NEXT)
+
+ /**
+ * Pushes a null reference (type O) onto the evaluation stack.
+ */
+ final val Ldnull = new OpCode()
+ opcode(Ldnull, CEE_LDNULL , "ldnull" , 0xFFFFFF14, POP_NONE, PUSH_REF , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of -1 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_M1 = new OpCode()
+ opcode(Ldc_I4_M1, CEE_LDC_I4_M1, "ldc.i4.m1", 0xFFFFFF15, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 0 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_0 = new OpCode()
+ opcode(Ldc_I4_0, CEE_LDC_I4_0 , "ldc.i4.0" , 0xFFFFFF16, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 1 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_1 = new OpCode()
+ opcode(Ldc_I4_1, CEE_LDC_I4_1 , "ldc.i4.1" , 0xFFFFFF17, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 2 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_2 = new OpCode()
+ opcode(Ldc_I4_2, CEE_LDC_I4_2 , "ldc.i4.2" , 0xFFFFFF18, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 3 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_3 = new OpCode()
+ opcode(Ldc_I4_3, CEE_LDC_I4_3 , "ldc.i4.3" , 0xFFFFFF19, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 4 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_4 = new OpCode()
+ opcode(Ldc_I4_4, CEE_LDC_I4_4 , "ldc.i4.4" , 0xFFFFFF1A, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 5 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_5 = new OpCode()
+ opcode(Ldc_I4_5, CEE_LDC_I4_5 , "ldc.i4.5" , 0xFFFFFF1B, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 6 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_6 = new OpCode()
+ opcode(Ldc_I4_6, CEE_LDC_I4_6 , "ldc.i4.6", 0xFFFFFF1C, POP_NONE, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 7 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_7 = new OpCode()
+ opcode(Ldc_I4_7, CEE_LDC_I4_7 , "ldc.i4.7", 0xFFFFFF1D, POP_NONE , PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the integer value of 8 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_8 = new OpCode()
+ opcode(Ldc_I4_8, CEE_LDC_I4_8 , "ldc.i4.8", 0xFFFFFF1E, POP_NONE , PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes the supplied int8 value onto the evaluation stack as an int32, short form.
+ */
+ final val Ldc_I4_S = new OpCode()
+ opcode(Ldc_I4_S, CEE_LDC_I4_S , "ldc.i4.s", 0xFFFFFF1F, POP_NONE , PUSH_I, INLINE_I_S, FLOW_NEXT)
+
+ /**
+ * Pushes a supplied value of type int32 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4 = new OpCode()
+ opcode(Ldc_I4, CEE_LDC_I4, "ldc.i4" , 0xFFFFFF20, POP_NONE , PUSH_I, INLINE_I , FLOW_NEXT)
+
+ /**
+ * Pushes a supplied value of type int64 onto the evaluation stack as an int64.
+ */
+ final val Ldc_I8 = new OpCode()
+ opcode(Ldc_I8, CEE_LDC_I8, "ldc.i8" , 0xFFFFFF21, POP_NONE , PUSH_I8, INLINE_I8 , FLOW_NEXT)
+
+ /**
+ * Pushes a supplied value of type float32 onto the evaluation stack as type F (float).
+ */
+ final val Ldc_R4 = new OpCode()
+ opcode(Ldc_R4, CEE_LDC_R4, "ldc.r4" , 0xFFFFFF22, POP_NONE , PUSH_R4, INLINE_R , FLOW_NEXT)
+
+ /**
+ * Pushes a supplied value of type float64 onto the evaluation stack as type F (float).
+ */
+ final val Ldc_R8 = new OpCode()
+ opcode(Ldc_R8, CEE_LDC_R8, "ldc.r8" , 0xFFFFFF23, POP_NONE , PUSH_R8, INLINE_R8 , FLOW_NEXT)
+
+ /**
+ * Copies the current topmost value on the evaluation stack, and then pushes the copy
+ * onto the evaluation stack.
+ */
+ final val Dup = new OpCode()
+ opcode(Dup, CEE_DUP , "dup" , 0xFFFFFF25, POP_1 , PUSH_1_1 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Removes the value currently on top of the evaluation stack.
+ */
+ final val Pop = new OpCode()
+ opcode(Pop, CEE_POP , "pop" , 0xFFFFFF26, POP_1 , PUSH_NONE , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Exits current method and jumps to specified method.
+ */
+ final val Jmp = new OpCode()
+ opcode(Jmp, CEE_JMP , "jmp" , 0xFFFFFF27, POP_NONE , PUSH_NONE , INLINE_METHOD, FLOW_CALL)
+
+ /**
+ * Calls the method indicated by the passed method descriptor.
+ */
+ final val Call = new OpCode()
+ opcode(Call, CEE_CALL , "call" , 0xFFFFFF28, POP_SPECIAL, PUSH_SPECIAL, INLINE_METHOD , FLOW_CALL)
+
+ /**
+ * Calls the method indicated on the evaluation stack (as a pointer to an entry point)
+ * with arguments described by a calling convention.
+ */
+ final val Calli = new OpCode()
+ opcode(Calli, CEE_CALLI, "calli" , 0xFFFFFF29, POP_SPECIAL, PUSH_SPECIAL, INLINE_SIGNATURE , FLOW_CALL)
+
+ /**
+ * Returns from the current method, pushing a return value (if present) from the caller's
+ * evaluation stack onto the callee's evaluation stack.
+ */
+ final val Ret = new OpCode()
+ opcode(Ret, CEE_RET , "ret" , 0xFFFFFF2A, POP_SPECIAL, PUSH_NONE, INLINE_NONE , FLOW_RETURN)
+
+ /**
+ * Unconditionally transfers control to a target instruction (short form).
+ */
+ final val Br_S = new OpCode()
+ opcode(Br_S, CEE_BR_S , "br.s" , 0xFFFFFF2B, POP_NONE, PUSH_NONE, INLINE_TARGET_S , FLOW_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if value is false, a null reference, or zero.
+ */
+ final val Brfalse_S = new OpCode()
+ opcode(Brfalse_S, CEE_BRFALSE_S,"brfalse.s", 0xFFFFFF2C, POP_I, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if value is true, not null, or non-zero.
+ */
+ final val Brtrue_S = new OpCode()
+ opcode(Brtrue_S, CEE_BRTRUE_S , "brtrue.s", 0xFFFFFF2D, POP_I, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if two values are equal.
+ */
+ final val Beq_S = new OpCode()
+ opcode(Beq_S, CEE_BEQ_S, "beq.s", 0xFFFFFF2E, POP_1_1 , PUSH_NONE, INLINE_TARGET_S , FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is greater than
+ * or equal to the second value.
+ */
+ final val Bge_S = new OpCode()
+ opcode(Bge_S, CEE_BGE_S, "bge.s", 0xFFFFFF2F, POP_1_1 , PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is greater than
+ * the second value.
+ */
+ final val Bgt_S = new OpCode()
+ opcode(Bgt_S, CEE_BGT_S, "bgt.s" , 0xFFFFFF30, POP_1_1 , PUSH_NONE, INLINE_TARGET_S , FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is less than
+ * or equal to the second value.
+ */
+ final val Ble_S = new OpCode()
+ opcode(Ble_S, CEE_BLE_S, "ble.s" , 0xFFFFFF31, POP_1_1 , PUSH_NONE, INLINE_TARGET_S , FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is less than
+ * the second value.
+ */
+ final val Blt_S = new OpCode()
+ opcode(Blt_S, CEE_BLT_S, "blt.s", 0xFFFFFF32, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) when two unsigned integer values
+ * or unordered float values are not equal.
+ */
+ final val Bne_Un_S = new OpCode()
+ opcode(Bne_Un_S, CEE_BNE_UN_S, "bne.un.s", 0xFFFFFF33, POP_1_1 , PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if if the the first value is greather
+ * than the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Bge_Un_S = new OpCode()
+ opcode(Bge_Un_S, CEE_BGE_UN_S, "bge.un.s", 0xFFFFFF34, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is greater than
+ * the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Bgt_Un_S = new OpCode()
+ opcode(Bgt_Un_S, CEE_BGT_UN_S, "bgt.un.s", 0xFFFFFF35, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is less than
+ * or equal to the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Ble_Un_S = new OpCode()
+ opcode(Ble_Un_S, CEE_BLE_UN_S , "ble.un.s", 0xFFFFFF36, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is less than
+ * the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Blt_Un_S = new OpCode()
+ opcode(Blt_Un_S, CEE_BLT_UN_S, "blt.un.s", 0xFFFFFF37, POP_1_1, PUSH_NONE, INLINE_TARGET_S, FLOW_COND_BRANCH)
+
+ /**
+ * Unconditionally transfers control to a target instruction.
+ */
+ final val Br = new OpCode()
+ opcode(Br, CEE_BR , "br" , 0xFFFFFF38, POP_NONE, PUSH_NONE, INLINE_TARGET, FLOW_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if value is false, a null reference
+ * (Nothing in Visual Basic), or zero.
+ */
+ final val Brfalse = new OpCode()
+ opcode(Brfalse, CEE_BRFALSE, "brfalse", 0xFFFFFF39, POP_I, PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if value is true, not null, or non-zero.
+ */
+ final val Brtrue = new OpCode()
+ opcode(Brtrue, CEE_BRTRUE , "brtrue", 0xFFFFFF3A, POP_I , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if two values are equal.
+ */
+ final val Beq = new OpCode()
+ opcode(Beq, CEE_BEQ, "beq", 0xFFFFFF3B, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if the first value is greater than or
+ * equal to the second value.
+ */
+ final val Bge = new OpCode()
+ opcode(Bge, CEE_BGE, "bge", 0xFFFFFF3C, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if the first value is greater than the second value.
+ */
+ final val Bgt = new OpCode()
+ opcode(Bgt, CEE_BGT, "bgt", 0xFFFFFF3D, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if the first value is less than or equal
+ * to the second value.
+ */
+ final val Ble = new OpCode()
+ opcode(Ble, CEE_BLE, "ble", 0xFFFFFF3E, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if the first value is less than the second value.
+ */
+ final val Blt = new OpCode()
+ opcode(Blt, CEE_BLT, "blt", 0xFFFFFF3F, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction when two unsigned integer values or
+ * unordered float values are not equal.
+ */
+ final val Bne_Un = new OpCode()
+ opcode(Bne_Un, CEE_BNE_UN , "bne.un", 0xFFFFFF40, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if the the first value is greather than
+ * the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Bge_Un = new OpCode()
+ opcode(Bge_Un, CEE_BGE_UN , "bge.un", 0xFFFFFF41, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if the first value is greater than the
+ * second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Bgt_Un = new OpCode()
+ opcode(Bgt_Un, CEE_BGT_UN , "bgt.un", 0xFFFFFF42, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if the first value is less than or equal to
+ * the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Ble_Un = new OpCode()
+ opcode(Ble_Un, CEE_BLE_UN , "ble.un" , 0xFFFFFF43, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Transfers control to a target instruction if the first value is less than the second value,
+ * when comparing unsigned integer values or unordered float values.
+ */
+ final val Blt_Un = new OpCode()
+ opcode(Blt_Un, CEE_BLT_UN , "blt.un", 0xFFFFFF44, POP_1_1 , PUSH_NONE, INLINE_TARGET, FLOW_COND_BRANCH)
+
+ /**
+ * Implements a jump table.
+ */
+ final val Switch = new OpCode()
+ opcode(Switch, CEE_SWITCH , "switch", 0xFFFFFF45, POP_I , PUSH_NONE, INLINE_SWITCH, FLOW_COND_BRANCH)
+
+ /**
+ * Loads a value of type int8 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_I1 = new OpCode()
+ opcode(Ldind_I1, CEE_LDIND_I1 , "ldind.i1" , 0xFFFFFF46, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type int16 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_I2 = new OpCode()
+ opcode(Ldind_I2, CEE_LDIND_I2 , "ldind.i2" , 0xFFFFFF48, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type int32 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_I4 = new OpCode()
+ opcode(Ldind_I4, CEE_LDIND_I4 , "ldind.i4" , 0xFFFFFF4A, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type int64 as an int64 onto the evaluation stack indirectly.
+ */
+ final val Ldind_I8 = new OpCode()
+ opcode(Ldind_I8, CEE_LDIND_I8 , "ldind.i8" , 0xFFFFFF4C, POP_I , PUSH_I8 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type natural int as a natural int onto the evaluation stack indirectly.
+ */
+ final val Ldind_I = new OpCode()
+ opcode(Ldind_I, CEE_LDIND_I , "ldind.i" , 0xFFFFFF4D, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type float32 as a type F (float) onto the evaluation stack indirectly.
+ */
+ final val Ldind_R4 = new OpCode()
+ opcode(Ldind_R4, CEE_LDIND_R4 , "ldind.r4" , 0xFFFFFF4E, POP_I , PUSH_R4 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type float64 as a type F (float) onto the evaluation stack indirectly.
+ */
+ final val Ldind_R8 = new OpCode()
+ opcode(Ldind_R8, CEE_LDIND_R8 , "ldind.r8" , 0xFFFFFF4F, POP_I , PUSH_R8 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads an object reference as a type O (object reference) onto the evaluation stack indirectly.
+ */
+ final val Ldind_Ref = new OpCode()
+ opcode(Ldind_Ref, CEE_LDIND_REF, "ldind.ref", 0xFFFFFF50, POP_I , PUSH_REF, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type unsigned int8 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_U1 = new OpCode()
+ opcode(Ldind_U1, CEE_LDIND_U1 , "ldind.u1" , 0xFFFFFF47, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type unsigned int16 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_U2 = new OpCode()
+ opcode(Ldind_U2, CEE_LDIND_U2 , "ldind.u2" , 0xFFFFFF49, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Loads a value of type unsigned int32 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_U4 = new OpCode()
+ opcode(Ldind_U4, CEE_LDIND_U4 , "ldind.u4" , 0xFFFFFF4B, POP_I , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Stores a object reference value at a supplied address.
+ */
+ final val Stind_Ref = new OpCode()
+ opcode(Stind_Ref, CEE_STIND_REF, "stind.ref", 0xFFFFFF51, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Stores a value of type int8 at a supplied address.
+ */
+ final val Stind_I1 = new OpCode()
+ opcode(Stind_I1, CEE_STIND_I1 , "stind.i1", 0xFFFFFF52, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Stores a value of type int16 at a supplied address.
+ */
+ final val Stind_I2 = new OpCode()
+ opcode(Stind_I2, CEE_STIND_I2 , "stind.i2", 0xFFFFFF53, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Stores a value of type int32 at a supplied address.
+ */
+ final val Stind_I4 = new OpCode()
+ opcode(Stind_I4, CEE_STIND_I4 , "stind.i4", 0xFFFFFF54, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Stores a value of type int64 at a supplied address.
+ */
+ final val Stind_I8 = new OpCode()
+ opcode(Stind_I8, CEE_STIND_I8 , "stind.i8", 0xFFFFFF55, POP_I_I8, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Stores a value of type float32 at a supplied address.
+ */
+ final val Stind_R4 = new OpCode()
+ opcode(Stind_R4, CEE_STIND_R4 , "stind.r4", 0xFFFFFF56, POP_I_R4, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Stores a value of type float64 at a supplied address.
+ */
+ final val Stind_R8 = new OpCode()
+ opcode(Stind_R8, CEE_STIND_R8 , "stind.r8", 0xFFFFFF57, POP_I_R8, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Subtracts one value from another and pushes the result onto the evaluation stack.
+ */
+ final val Sub = new OpCode()
+ opcode(Sub, CEE_SUB, "sub" , 0xFFFFFF59, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Multiplies two values and pushes the result on the evaluation stack.
+ */
+ final val Mul = new OpCode()
+ opcode(Mul, CEE_MUL, "mul" , 0xFFFFFF5A, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Divides two values and pushes the result as a floating-point (type F) or
+ * quotient (type int32) onto the evaluation stack.
+ */
+ final val Div = new OpCode()
+ opcode(Div, CEE_DIV, "div" , 0xFFFFFF5B, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Divides two unsigned integer values and pushes the result (int32) onto the evaluation stack.
+ */
+ final val Div_Un = new OpCode()
+ opcode(Div_Un, CEE_DIV_UN, "div.un" , 0xFFFFFF5C, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Divides two values and pushes the remainder onto the evaluation stack.
+ */
+ final val Rem = new OpCode()
+ opcode(Rem, CEE_REM , "rem" , 0xFFFFFF5D, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Divides two unsigned values and pushes the remainder onto the evaluation stack.
+ */
+ final val Rem_Un = new OpCode()
+ opcode(Rem_Un, CEE_REM_UN, "rem.un" , 0xFFFFFF5E, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Computes the bitwise AND of two values and pushes the result onto the evalution stack.
+ */
+ final val And = new OpCode()
+ opcode(And, CEE_AND, "and" , 0xFFFFFF5F, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Compute the bitwise complement of the two integer values on top of the stack and
+ * pushes the result onto the evaluation stack.
+ */
+ final val Or = new OpCode()
+ opcode(Or, CEE_OR , "or" , 0xFFFFFF60, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Computes the bitwise XOR of the top two values on the evaluation stack,
+ * pushing the result onto the evaluation stack.
+ */
+ final val Xor = new OpCode()
+ opcode(Xor, CEE_XOR, "xor" , 0xFFFFFF61, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Shifts an integer value to the left (in zeroes) by a specified number of bits,
+ * pushing the result onto the evaluation stack.
+ */
+ final val Shl = new OpCode()
+ opcode(Shl, CEE_SHL, "shl" , 0xFFFFFF62, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Shifts an integer value (in sign) to the right by a specified number of bits,
+ * pushing the result onto the evaluation stack.
+ */
+ final val Shr = new OpCode()
+ opcode(Shr, CEE_SHR, "shr" , 0xFFFFFF63, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Shifts an unsigned integer value (in zeroes) to the right by a specified number of bits,
+ * pushing the result onto the evaluation stack.
+ */
+ final val Shr_Un = new OpCode()
+ opcode(Shr_Un, CEE_SHR_UN, "shr.un" , 0xFFFFFF64, POP_1_1, PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Negates a value and pushes the result onto the evaluation stack.
+ */
+ final val Neg = new OpCode()
+ opcode(Neg, CEE_NEG , "neg" , 0xFFFFFF65, POP_1 , PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Computes the bitwise complement of the integer value on top of the stack and pushes
+ * the result onto the evaluation stack as the same type.
+ */
+ final val Not = new OpCode()
+ opcode(Not, CEE_NOT , "not" , 0xFFFFFF66, POP_1 , PUSH_1 , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to int8, then extends (pads) it to int32.
+ */
+ final val Conv_I1 = new OpCode()
+ opcode(Conv_I1, CEE_CONV_I1, "conv.i1", 0xFFFFFF67, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to int16, then extends (pads) it to int32.
+ */
+ final val Conv_I2 = new OpCode()
+ opcode(Conv_I2, CEE_CONV_I2, "conv.i2", 0xFFFFFF68, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to int32.
+ */
+ final val Conv_I4 = new OpCode()
+ opcode(Conv_I4, CEE_CONV_I4, "conv.i4", 0xFFFFFF69, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to int64.
+ */
+ final val Conv_I8 = new OpCode()
+ opcode(Conv_I8, CEE_CONV_I8, "conv.i8", 0xFFFFFF6A, POP_1 , PUSH_I8, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to float32.
+ */
+ final val Conv_R4 = new OpCode()
+ opcode(Conv_R4, CEE_CONV_R4, "conv.r4", 0xFFFFFF6B, POP_1 , PUSH_R4, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to float64.
+ */
+ final val Conv_R8 = new OpCode()
+ opcode(Conv_R8, CEE_CONV_R8, "conv.r8", 0xFFFFFF6C, POP_1 , PUSH_R8, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned int32, and extends it to int32.
+ */
+ final val Conv_U4 = new OpCode()
+ opcode(Conv_U4, CEE_CONV_U4, "conv.u4", 0xFFFFFF6D, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned int64, and extends it to int64.
+ */
+ final val Conv_U8 = new OpCode()
+ opcode(Conv_U8, CEE_CONV_U8, "conv.u8", 0xFFFFFF6E, POP_1 , PUSH_I8, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Calls a late-bound method on an object, pushing the return value onto the evaluation stack.
+ */
+ final val Callvirt = new OpCode()
+ opcode(Callvirt, CEE_CALLVIRT, "callvirt", 0xFFFFFF6F,POP_SPECIAL,PUSH_SPECIAL,INLINE_METHOD,FLOW_CALL)
+
+ /**
+ * Copies the value type located at the address of an object (type &, * or natural int)
+ * to the address of the destination object (type &, * or natural int).
+ */
+ final val Cpobj = new OpCode()
+ opcode(Cpobj, CEE_CPOBJ , "cpobj" , 0xFFFFFF70, POP_I_I , PUSH_NONE, INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Copies the value type object pointed to by an address to the top of the evaluation stack.
+ */
+ final val Ldobj = new OpCode()
+ opcode(Ldobj, CEE_LDOBJ , "ldobj" , 0xFFFFFF71, POP_I , PUSH_1 , INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Pushes a new object reference to a string literal stored in the metadata.
+ */
+ final val Ldstr = new OpCode()
+ opcode(Ldstr, CEE_LDSTR , "ldstr" , 0xFFFFFF72, POP_NONE , PUSH_REF , INLINE_STRING, FLOW_NEXT)
+
+ /**
+ * Creates a new object or a new instance of a value type, pushing an object reference
+ * (type O) onto the evaluation stack.
+ */
+ final val Newobj = new OpCode()
+ opcode(Newobj, CEE_NEWOBJ, "newobj", 0xFFFFFF73, POP_SPECIAL , PUSH_REF , INLINE_METHOD, FLOW_CALL)
+
+ /**
+ * Attempts to cast an object passed by reference to the specified class.
+ */
+ final val Castclass = new OpCode()
+ opcode(Castclass, CEE_CASTCLASS, "castclass", 0xFFFFFF74, POP_REF , PUSH_REF , INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Tests whether an object reference (type O) is an instance of a particular class.
+ */
+ final val Isinst = new OpCode()
+ opcode(Isinst, CEE_ISINST , "isinst" , 0xFFFFFF75, POP_REF , PUSH_I , INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Converts the unsigned integer value on top of the evaluation stack to float32.
+ */
+ final val Conv_R_Un = new OpCode()
+ opcode(Conv_R_Un, CEE_CONV_R_UN, "conv.r.un", 0xFFFFFF76, POP_1 , PUSH_R8 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the boxed representation of a value type to its unboxed form.
+ */
+ final val Unbox = new OpCode()
+ opcode(Unbox, CEE_UNBOX , "unbox" , 0xFFFFFF79, POP_REF , PUSH_I , INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Throws the exception object currently on the evaluation stack.
+ */
+ final val Throw = new OpCode()
+ opcode(Throw, CEE_THROW , "throw" , 0xFFFFFF7A, POP_REF , PUSH_NONE, INLINE_NONE , FLOW_THROW)
+
+ /**
+ * Finds the value of a field in the object whose reference is currently
+ * on the evaluation stack.
+ */
+ final val Ldfld = new OpCode()
+ opcode(Ldfld, CEE_LDFLD , "ldfld" , 0xFFFFFF7B, POP_REF , PUSH_1 , INLINE_FIELD , FLOW_NEXT)
+
+ /**
+ * Finds the address of a field in the object whose reference is currently
+ * on the evaluation stack.
+ */
+ final val Ldflda = new OpCode()
+ opcode(Ldflda, CEE_LDFLDA , "ldflda" , 0xFFFFFF7C, POP_REF , PUSH_I , INLINE_FIELD , FLOW_NEXT)
+
+ /**
+ * Pushes the value of a static field onto the evaluation stack.
+ */
+ final val Ldsfld = new OpCode()
+ opcode(Ldsfld, CEE_LDSFLD , "ldsfld" , 0xFFFFFF7E, POP_NONE , PUSH_1 , INLINE_FIELD , FLOW_NEXT)
+
+ /**
+ * Pushes the address of a static field onto the evaluation stack.
+ */
+ final val Ldsflda = new OpCode()
+ opcode(Ldsflda, CEE_LDSFLDA, "ldsflda", 0xFFFFFF7F, POP_NONE , PUSH_I , INLINE_FIELD , FLOW_NEXT)
+
+ /**
+ * Replaces the value stored in the field of an object reference or pointer with a new value.
+ */
+ final val Stfld = new OpCode()
+ opcode(Stfld, CEE_STFLD , "stfld" , 0xFFFFFF7D, POP_REF_1, PUSH_NONE, INLINE_FIELD , FLOW_NEXT)
+
+ /**
+ * Replaces the value of a static field with a value from the evaluation stack.
+ */
+ final val Stsfld = new OpCode()
+ opcode(Stsfld, CEE_STSFLD , "stsfld" , 0xFFFFFF80, POP_1 , PUSH_NONE, INLINE_FIELD , FLOW_NEXT)
+
+ /**
+ * Copies a value of a specified type from the evaluation stack into a supplied memory address.
+ */
+ final val Stobj = new OpCode()
+ opcode(Stobj, CEE_STOBJ , "stobj" , 0xFFFFFF81, POP_I_1, PUSH_NONE, INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed int8 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I1_Un = new OpCode()
+ opcode(Conv_Ovf_I1_Un, CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", 0xFFFFFF82, POP_1,PUSH_I,INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed int16 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I2_Un = new OpCode()
+ opcode(Conv_Ovf_I2_Un, CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", 0xFFFFFF83,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed int32,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I4_Un = new OpCode()
+ opcode(Conv_Ovf_I4_Un, CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", 0xFFFFFF84,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed int64,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I8_Un = new OpCode()
+ opcode(Conv_Ovf_I8_Un, CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", 0xFFFFFF85,POP_1,PUSH_I8, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed natural int,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I_Un = new OpCode()
+ opcode(Conv_Ovf_I_Un, CEE_CONV_OVF_I_UN , "conv.ovf.i.un" , 0xFFFFFF8A,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned int8 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U1_Un = new OpCode()
+ opcode(Conv_Ovf_U1_Un, CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", 0xFFFFFF86,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned int16 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U2_Un = new OpCode()
+ opcode(Conv_Ovf_U2_Un, CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", 0xFFFFFF87,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned int32,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U4_Un = new OpCode()
+ opcode(Conv_Ovf_U4_Un, CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", 0xFFFFFF88,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned int64,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U8_Un = new OpCode()
+ opcode(Conv_Ovf_U8_Un, CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", 0xFFFFFF89,POP_1,PUSH_I8, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned natural int,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U_Un = new OpCode()
+ opcode(Conv_Ovf_U_Un, CEE_CONV_OVF_U_UN , "conv.ovf.u.un" , 0xFFFFFF8B,POP_1,PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts a value type to an object reference (type O).
+ */
+ final val Box = new OpCode()
+ opcode(Box, CEE_BOX , "box" , 0xFFFFFF8C, POP_1 , PUSH_REF , INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Pushes an object reference to a new zero-based, one-dimensional array whose elements
+ * are of a specific type onto the evaluation stack.
+ */
+ final val Newarr = new OpCode()
+ opcode(Newarr, CEE_NEWARR, "newarr" , 0xFFFFFF8D, POP_I , PUSH_REF , INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Pushes the number of elements of a zero-based, one-dimensional array
+ * onto the evaluation stack.
+ */
+ final val Ldlen = new OpCode()
+ opcode(Ldlen, CEE_LDLEN, "ldlen", 0xFFFFFF8E, POP_REF, PUSH_I,INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the address of the array element at a specified array index onto
+ * the top of the evaluation stack as type & (managed pointer).
+ */
+ final val Ldelema = new OpCode()
+ opcode(Ldelema, CEE_LDELEMA, "ldelema" , 0xFFFFFF8F, POP_REF_I, PUSH_I, INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type natural int at a specified array index onto the top
+ * of the evaluation stack as a natural int.
+ */
+ final val Ldelem_I = new OpCode()
+ opcode(Ldelem_I, CEE_LDELEM_I, "ldelem.i" , 0xFFFFFF97, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type int8 at a specified array index onto the top of the
+ * evaluation stack as an int32.
+ */
+ final val Ldelem_I1 = new OpCode()
+ opcode(Ldelem_I1, CEE_LDELEM_I1, "ldelem.i1" , 0xFFFFFF90, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type int16 at a specified array index onto the top of
+ * the evaluation stack as an int32.
+ */
+ final val Ldelem_I2 = new OpCode()
+ opcode(Ldelem_I2, CEE_LDELEM_I2, "ldelem.i2" , 0xFFFFFF92, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type int32 at a specified array index onto the top of the
+ * evaluation stack as an int32.
+ */
+ final val Ldelem_I4 = new OpCode()
+ opcode(Ldelem_I4, CEE_LDELEM_I4, "ldelem.i4" , 0xFFFFFF94, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type int64 at a specified array index onto the top of the
+ * evaluation stack as an int64.
+ */
+ final val Ldelem_I8 = new OpCode()
+ opcode(Ldelem_I8, CEE_LDELEM_I8, "ldelem.i8" , 0xFFFFFF96, POP_REF_I, PUSH_I8, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type float32 at a specified array index onto the top of the
+ * evaluation stack as type F (float)
+ */
+ final val Ldelem_R4 = new OpCode()
+ opcode(Ldelem_R4, CEE_LDELEM_R4, "ldelem.r4" , 0xFFFFFF98, POP_REF_I, PUSH_R4, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type float64 at a specified array index onto the top of the
+ * evaluation stack as type F (float) .
+ */
+ final val Ldelem_R8 = new OpCode()
+ opcode(Ldelem_R8, CEE_LDELEM_R8, "ldelem.r8" , 0xFFFFFF99, POP_REF_I, PUSH_R8, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element containing an object reference at a specified array index onto
+ * the top of the evaluation stack as type O (object reference).
+ */
+ final val Ldelem_Ref = new OpCode()
+ opcode(Ldelem_Ref, CEE_LDELEM_REF, "ldelem.ref", 0xFFFFFF9A, POP_REF_I, PUSH_REF, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type unsigned int8 at a specified array index onto the top
+ * of the evaluation stack as an int32.
+ */
+ final val Ldelem_U1 = new OpCode()
+ opcode(Ldelem_U1, CEE_LDELEM_U1, "ldelem.u1" , 0xFFFFFF91, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type unsigned int16 at a specified array index onto the top
+ * of the evaluation stack as an int32.
+ */
+ final val Ldelem_U2 = new OpCode()
+ opcode(Ldelem_U2, CEE_LDELEM_U2, "ldelem.u2" , 0xFFFFFF93, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Loads the element with type unsigned int32 at a specified array index onto the top
+ * of the evaluation stack as an int32.
+ */
+ final val Ldelem_U4 = new OpCode()
+ opcode(Ldelem_U4, CEE_LDELEM_U4, "ldelem.u4" , 0xFFFFFF95, POP_REF_I, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Replaces the array element at a given index with the natural int value on
+ * the evaluation stack.
+ */
+ final val Stelem_I = new OpCode()
+ opcode(Stelem_I, CEE_STELEM_I, "stelem.i", 0xFFFFFF9B, POP_REF_I_I, PUSH_NONE, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Replaces the array element at a given index with the int8 value on the evaluation stack.
+ */
+ final val Stelem_I1 = new OpCode()
+ opcode(Stelem_I1, CEE_STELEM_I1, "stelem.i1", 0xFFFFFF9C, POP_REF_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Replaces the array element at a given index with the int16 value on the evaluation stack.
+ */
+ final val Stelem_I2 = new OpCode()
+ opcode(Stelem_I2, CEE_STELEM_I2, "stelem.i2", 0xFFFFFF9D, POP_REF_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Replaces the array element at a given index with the int32 value on the evaluation stack.
+ */
+ final val Stelem_I4 = new OpCode()
+ opcode(Stelem_I4, CEE_STELEM_I4, "stelem.i4", 0xFFFFFF9E, POP_REF_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Replaces the array element at a given index with the int64 value on the evaluation stack.
+ */
+ final val Stelem_I8 = new OpCode()
+ opcode(Stelem_I8, CEE_STELEM_I8,"stelem.i8", 0xFFFFFF9F, POP_REF_I_I8, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Replaces the array element at a given index with the float32 value on the evaluation stack.
+ */
+ final val Stelem_R4 = new OpCode()
+ opcode(Stelem_R4, CEE_STELEM_R4,"stelem.r4", 0xFFFFFFA0, POP_REF_I_R4, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Replaces the array element at a given index with the float64 value on the evaluation stack.
+ */
+ final val Stelem_R8 = new OpCode()
+ opcode(Stelem_R8, CEE_STELEM_R8,"stelem.r8", 0xFFFFFFA1, POP_REF_I_R8, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Replaces the array element at a given index with the object ref value (type O)
+ * on the evaluation stack.
+ */
+ final val Stelem_Ref = new OpCode()
+ opcode(Stelem_Ref, CEE_STELEM_REF,"stelem.ref",0xFFFFFFA2,POP_REF_I_REF,PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to signed int8 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I1 = new OpCode()
+ opcode(Conv_Ovf_I1, CEE_CONV_OVF_I1, "conv.ovf.i1", 0xFFFFFFB3, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to signed int16 and
+ * extending it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I2 = new OpCode()
+ opcode(Conv_Ovf_I2, CEE_CONV_OVF_I2, "conv.ovf.i2", 0xFFFFFFB5, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the sevaluation tack to signed int32,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I4 = new OpCode()
+ opcode(Conv_Ovf_I4, CEE_CONV_OVF_I4, "conv.ovf.i4", 0xFFFFFFB7, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to signed int64,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I8 = new OpCode()
+ opcode(Conv_Ovf_I8, CEE_CONV_OVF_I8, "conv.ovf.i8", 0xFFFFFFB9, POP_1, PUSH_I8, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned int8 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U1 = new OpCode()
+ opcode(Conv_Ovf_U1, CEE_CONV_OVF_U1, "conv.ovf.u1", 0xFFFFFFB4, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned int16 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U2 = new OpCode()
+ opcode(Conv_Ovf_U2, CEE_CONV_OVF_U2, "conv.ovf.u2", 0xFFFFFFB6, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned int32,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U4 = new OpCode()
+ opcode(Conv_Ovf_U4, CEE_CONV_OVF_U4, "conv.ovf.u4", 0xFFFFFFB8, POP_1, PUSH_I , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned int64,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U8 = new OpCode()
+ opcode(Conv_Ovf_U8, CEE_CONV_OVF_U8, "conv.ovf.u8", 0xFFFFFFBA, POP_1, PUSH_I8, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Retrieves the address (type &) embedded in a typed reference.
+ */
+ final val Refanyval = new OpCode()
+ opcode(Refanyval, CEE_REFANYVAL, "refanyval", 0xFFFFFFC2, POP_1, PUSH_I , INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Retrieves the type token embedded in a typed reference .
+ */
+ final val Refanytype = new OpCode()
+ opcode(Refanytype, CEE_REFANYTYPE, "refanytype", 0xFFFFFE1D, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Throws ArithmeticException if value is not a finite number.
+ */
+ final val Ckfinite = new OpCode()
+ opcode(Ckfinite, CEE_CKFINITE, "ckfinite" , 0xFFFFFFC3, POP_1, PUSH_R8 , INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Pushes a typed reference to an instance of a specific type onto the evaluation stack.
+ */
+ final val Mkrefany = new OpCode()
+ opcode(Mkrefany, CEE_MKREFANY, "mkrefany" , 0xFFFFFFC6, POP_I, PUSH_1 , INLINE_TYPE , FLOW_NEXT)
+
+ /**
+ * Converts a metadata token to its runtime representation, pushing it onto the evaluation stack.
+ */
+ final val Ldtoken = new OpCode()
+ opcode(Ldtoken, CEE_LDTOKEN , "ldtoken" , 0xFFFFFFD0, POP_NONE, PUSH_I, INLINE_TOKEN , FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned int8, and extends it to int32.
+ */
+ final val Conv_U1 = new OpCode()
+ opcode(Conv_U1, CEE_CONV_U1 , "conv.u1" , 0xFFFFFFD2, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned int16, and extends it to int32.
+ */
+ final val Conv_U2 = new OpCode()
+ opcode(Conv_U2, CEE_CONV_U2 , "conv.u2" , 0xFFFFFFD1, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to natural int.
+ */
+ final val Conv_I = new OpCode()
+ opcode(Conv_I, CEE_CONV_I , "conv.i" , 0xFFFFFFD3, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to signed natural int,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I = new OpCode()
+ opcode(Conv_Ovf_I, CEE_CONV_OVF_I , "conv.ovf.i", 0xFFFFFFD4, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned natural int,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U = new OpCode()
+ opcode(Conv_Ovf_U, CEE_CONV_OVF_U , "conv.ovf.u", 0xFFFFFFD5, POP_1, PUSH_I, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Adds two integers, performs an overflow check, and pushes the result
+ * onto the evaluation stack.
+ */
+ final val Add_Ovf = new OpCode()
+ opcode(Add_Ovf, CEE_ADD_OVF , "add.ovf" , 0xFFFFFFD6, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Adds two unsigned integer values, performs an overflow check, and pushes the result
+ * onto the evaluation stack.
+ */
+ final val Add_Ovf_Un = new OpCode()
+ opcode(Add_Ovf_Un, CEE_ADD_OVF_UN , "add.ovf.un", 0xFFFFFFD7, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Multiplies two integer values, performs an overflow check, and pushes the result
+ * onto the evaluation stack.
+ */
+ final val Mul_Ovf = new OpCode()
+ opcode(Mul_Ovf, CEE_MUL_OVF , "mul.ovf" , 0xFFFFFFD8, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Multiplies two unsigned integer values , performs an overflow check ,
+ * and pushes the result onto the evaluation stack.
+ */
+ final val Mul_Ovf_Un = new OpCode()
+ opcode(Mul_Ovf_Un, CEE_MUL_OVF_UN , "mul.ovf.un", 0xFFFFFFD9, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Subtracts one integer value from another, performs an overflow check,
+ * and pushes the result onto the evaluation stack.
+ */
+ final val Sub_Ovf = new OpCode()
+ opcode(Sub_Ovf, CEE_SUB_OVF , "sub.ovf" , 0xFFFFFFDA, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Subtracts one unsigned integer value from another, performs an overflow check,
+ * and pushes the result onto the evaluation stack.
+ */
+ final val Sub_Ovf_Un = new OpCode()
+ opcode(Sub_Ovf_Un, CEE_SUB_OVF_UN, "sub.ovf.un", 0xFFFFFFDB, POP_1_1, PUSH_1, INLINE_NONE , FLOW_NEXT)
+
+ /**
+ * Transfers control from the fault or finally clause of an exception block back to
+ * the Common Language Infrastructure (CLI) exception handler.
+ */
+ final val Endfinally = new OpCode()
+ opcode(Endfinally, CEE_ENDFINALLY, "endfinally", 0xFFFFFFDC, POP_NONE, PUSH_NONE, INLINE_NONE, FLOW_RETURN)
+
+ /**
+ * Exits a protected region of code, unconditionally tranferring control
+ * to a specific target instruction.
+ */
+ final val Leave = new OpCode()
+ opcode(Leave, CEE_LEAVE, "leave", 0xFFFFFFDD, POP_NONE, PUSH_NONE, INLINE_TARGET, FLOW_BRANCH)
+
+ /**
+ * Exits a protected region of code, unconditionally tranferring control
+ * to a target instruction (short form).
+ */
+ final val Leave_S = new OpCode()
+ opcode(Leave_S, CEE_LEAVE_S, "leave.s", 0xFFFFFFDE, POP_NONE, PUSH_NONE, INLINE_TARGET_S, FLOW_BRANCH)
+
+ /**
+ * Stores a value of type natural int at a supplied address.
+ */
+ final val Stind_I = new OpCode()
+ opcode(Stind_I, CEE_STIND_I, "stind.i", 0xFFFFFFDF, POP_I_I , PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned natural int,
+ * and extends it to natural int.
+ */
+ final val Conv_U = new OpCode()
+ opcode(Conv_U, CEE_CONV_U, "conv.u", 0xFFFFFFE0, POP_1 , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Returns an unmanaged pointer to the argument list of the current method.
+ */
+ final val Arglist = new OpCode()
+ opcode(Arglist, CEE_ARGLIST, "arglist" , 0xFFFFFE00, POP_NONE, PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Compares two values. If they are equal, the integer value 1 (int32) is pushed
+ * onto the evaluation stack otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Ceq = new OpCode()
+ opcode(Ceq, CEE_CEQ, "ceq", 0xFFFFFE01, POP_1_1 , PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Compares two values. If the first value is greater than the second,
+ * the integer value 1 (int32) is pushed onto the evaluation stack
+ * otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Cgt = new OpCode()
+ opcode(Cgt, CEE_CGT, "cgt", 0xFFFFFE02, POP_1_1 , PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Compares two unsigned or unordered values. If the first value is greater than
+ * the second, the integer value 1 (int32) is pushed onto the evaluation stack
+ * otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Cgt_Un = new OpCode()
+ opcode(Cgt_Un, CEE_CGT_UN, "cgt.un", 0xFFFFFE03, POP_1_1 , PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Compares two values. If the first value is less than the second,
+ * the integer value 1 (int32) is pushed onto the evaluation stack
+ * otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Clt = new OpCode()
+ opcode(Clt, CEE_CLT, "clt" , 0xFFFFFE04, POP_1_1 , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Compares the unsigned or unordered values value1 and value2. If value1 is
+ * less than value2, then the integer value 1 (int32) is pushed onto the
+ * evaluation stack otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Clt_Un = new OpCode()
+ opcode(Clt_Un, CEE_CLT_UN , "clt.un" , 0xFFFFFE05, POP_1_1 , PUSH_I , INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Pushes an unmanaged pointer (type natural int) to the native code implementing
+ * a specific method onto the evaluation stack.
+ */
+ final val Ldftn = new OpCode()
+ opcode(Ldftn, CEE_LDFTN , "ldftn" , 0xFFFFFE06, POP_NONE, PUSH_I , INLINE_METHOD, FLOW_NEXT)
+
+ /**
+ * Pushes an unmanaged pointer (type natural int) to the native code implementing
+ * a particular virtual method associated with a specified object onto the evaluation stack.
+ */
+ final val Ldvirtftn = new OpCode()
+ opcode(Ldvirtftn, CEE_LDVIRTFTN, "ldvirtftn", 0xFFFFFE07, POP_REF , PUSH_I , INLINE_METHOD, FLOW_NEXT)
+
+ /**
+ * Loads an argument (referenced by a specified index value) onto the stack.
+ */
+ final val Ldarg = new OpCode()
+ opcode(Ldarg, CEE_LDARG , "ldarg" , 0xFFFFFE09, POP_NONE, PUSH_1 , INLINE_VARIABLE , FLOW_NEXT)
+
+ /**
+ * Load an argument address onto the evaluation stack.
+ */
+ final val Ldarga = new OpCode()
+ opcode(Ldarga, CEE_LDARGA , "ldarga", 0xFFFFFE0A, POP_NONE, PUSH_I, INLINE_VARIABLE , FLOW_NEXT)
+
+ /**
+ * Loads the local variable at a specific index onto the evaluation stack.
+ */
+ final val Ldloc = new OpCode()
+ opcode(Ldloc, CEE_LDLOC, "ldloc", 0xFFFFFE0C, POP_NONE, PUSH_1 , INLINE_VARIABLE , FLOW_NEXT)
+
+ /**
+ * Loads the address of the local variable at a specific index onto the evaluation stack.
+ */
+ final val Ldloca = new OpCode()
+ opcode(Ldloca, CEE_LDLOCA, "ldloca", 0xFFFFFE0D, POP_NONE, PUSH_I, INLINE_VARIABLE , FLOW_NEXT)
+
+ /**
+ * Stores the value on top of the evaluation stack in the argument slot at a specified index.
+ */
+ final val Starg = new OpCode()
+ opcode(Starg, CEE_STARG, "starg", 0xFFFFFE0B, POP_1 , PUSH_NONE, INLINE_VARIABLE , FLOW_NEXT)
+
+ /**
+ * Pops the current value from the top of the evaluation stack and stores it in a
+ * the local variable list at a specified index.
+ */
+ final val Stloc = new OpCode()
+ opcode(Stloc, CEE_STLOC, "stloc", 0xFFFFFE0E, POP_1 , PUSH_NONE, INLINE_VARIABLE , FLOW_NEXT)
+
+ /**
+ * Allocates a certain number of bytes from the local dynamic memory pool and pushes the
+ * address (a transient pointer, type *) of the first allocated byte onto the evaluation stack.
+ */
+ final val Localloc = new OpCode()
+ opcode(Localloc, CEE_LOCALLOC, "localloc" , 0xFFFFFE0F, POP_I, PUSH_I, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Transfers control from the filter clause of an exception back to the
+ * Common Language Infrastructure (CLI) exception handler.
+ */
+ final val Endfilter = new OpCode()
+ opcode(Endfilter, CEE_ENDFILTER, "endfilter" , 0xFFFFFE11, POP_I , PUSH_NONE, INLINE_NONE, FLOW_RETURN)
+
+ /**
+ * Indicates that an address currently atop the evaluation stack might not be aligned
+ * to the natural size of the immediately following ldind, stind, ldfld, stfld, ldobj,
+ * stobj, initblk, or cpblk instruction.
+ */
+ final val Unaligned = new OpCode()
+ opcode(Unaligned, CEE_UNALIGNED, "unaligned.", 0xFFFFFE12, POP_NONE, PUSH_NONE, INLINE_I_S , FLOW_META)
+
+ /**
+ * Specifies that an address currently atop the evaluation stack might be volatile,
+ * and the results of reading that location cannot be cached or that multiple stores
+ * to that location cannot be suppressed.
+ */
+ final val Volatile = new OpCode()
+ opcode(Volatile, CEE_VOLATILE, "volatile." , 0xFFFFFE13, POP_NONE, PUSH_NONE, INLINE_NONE, FLOW_META)
+
+ /**
+ * Performs a postfixed method call instruction such that the current method's stack
+ * frame is removed before the actual call instruction is executed.
+ */
+ final val Tailcall = new OpCode()
+ opcode(Tailcall, CEE_TAILCALL, "tail." , 0xFFFFFE14, POP_NONE, PUSH_NONE, INLINE_NONE, FLOW_META)
+
+ /**
+ * Initializes all the fields of the object at a specific address to a null reference
+ * or a 0 of the appropriate primitive type.
+ */
+ final val Initobj = new OpCode()
+ opcode(Initobj, CEE_INITOBJ , "initobj" , 0xFFFFFE15, POP_I , PUSH_NONE, INLINE_TYPE, FLOW_NEXT)
+
+ /**
+ * Copies a specified number bytes from a source address to a destination address .
+ */
+ final val Cpblk = new OpCode()
+ opcode(Cpblk, CEE_CPBLK , "cpblk" , 0xFFFFFE17, POP_I_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Initializes a specified block of memory at a specific address to a given size
+ * and initial value.
+ */
+ final val Initblk = new OpCode()
+ opcode(Initblk, CEE_INITBLK , "initblk" , 0xFFFFFE18, POP_I_I_I, PUSH_NONE, INLINE_NONE, FLOW_NEXT)
+
+ /**
+ * Rethrows the current exception.
+ */
+ final val Rethrow = new OpCode()
+ opcode(Rethrow, CEE_RETHROW , "rethrow", 0xFFFFFE1A, POP_NONE , PUSH_NONE, INLINE_NONE, FLOW_THROW)
+
+ /**
+ * Pushes the size, in bytes, of a supplied value type onto the evaluation stack.
+ */
+ final val Sizeof = new OpCode()
+ opcode(Sizeof, CEE_SIZEOF, "sizeof", 0xFFFFFE1C, POP_NONE , PUSH_I , INLINE_TYPE, FLOW_NEXT)
+
+
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala
new file mode 100644
index 0000000000..6a94c6fef6
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/OpCodes.scala
@@ -0,0 +1,1196 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: OpCodes.java 168 2005-12-12 14:20:06Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+
+/**
+ * Provides field representations of the Microsoft Intermediate Language (MSIL)
+ * instructions for emission by the ILGenerator class members (such as Emit).
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+object OpCodes {
+
+ //##########################################################################
+
+ /**
+ * Adds two values and pushes the result onto the evaluation stack.
+ */
+ final val Add = OpCode.Add
+
+ /**
+ * Fills space if bytecodes are patched. No meaningful operation is performed
+ * although a processing cycle can be consumed.
+ */
+ final val Nop = OpCode.Nop
+
+ /**
+ * Signals the Common Language Infrastructure (CLI) to inform the debugger that
+ * a break point has been tripped.
+ */
+ final val Break = OpCode.Break
+
+ /**
+ * Loads the argument at index 0 onto the evaluation stack.
+ */
+ final val Ldarg_0 = OpCode.Ldarg_0
+
+ /**
+ * Loads the argument at index 1 onto the evaluation stack.
+ */
+ final val Ldarg_1 = OpCode.Ldarg_1
+
+ /**
+ * Loads the argument at index 2 onto the evaluation stack.
+ */
+ final val Ldarg_2 = OpCode.Ldarg_2
+
+ /**
+ * Loads the argument at index 3 onto the evaluation stack.
+ */
+ final val Ldarg_3 = OpCode.Ldarg_3
+
+ /**
+ * Loads the local variable at index 0 onto the evaluation stack.
+ */
+ final val Ldloc_0 = OpCode.Ldloc_0
+
+ /**
+ * Loads the local variable at index 1 onto the evaluation stack.
+ */
+ final val Ldloc_1 = OpCode.Ldloc_1
+
+ /**
+ * Loads the local variable at index 2 onto the evaluation stack.
+ */
+ final val Ldloc_2 = OpCode.Ldloc_2
+
+ /**
+ * Loads the local variable at index 3 onto the evaluation stack.
+ */
+ final val Ldloc_3 = OpCode.Ldloc_3
+
+ /**
+ * Pops the current value from the top of the evaluation stack and
+ * stores it in a the local variable list at index 0.
+ */
+ final val Stloc_0 = OpCode.Stloc_0
+
+ /**
+ * Pops the current value from the top of the evaluation stack and
+ * stores it in a the local variable list at index 1.
+ */
+ final val Stloc_1 = OpCode.Stloc_1
+
+ /**
+ * Pops the current value from the top of the evaluation stack and
+ * stores it in a the local variable list at index 2.
+ */
+ final val Stloc_2 = OpCode.Stloc_2
+
+ /**
+ * Pops the current value from the top of the evaluation stack and
+ * stores it in a the local variable list at index 3.
+ */
+ final val Stloc_3 = OpCode.Stloc_3
+
+ /**
+ * Loads the argument (referenced by a specified short form index)
+ * onto the evaluation stack.
+ */
+ final val Ldarg_S = OpCode.Ldarg_S
+
+ /**
+ * Load an argument address, in short form, onto the evaluation stack.
+ */
+ final val Ldarga_S = OpCode.Ldarga_S
+
+ /**
+ * Loads the local variable at a specific index onto the evaluation stack,
+ * short form.
+ */
+ final val Ldloc_S = OpCode.Ldloc_S
+
+ /**
+ * Loads the address of the local variable at a specific index onto
+ * the evaluation stack, short form.
+ */
+ final val Ldloca_S = OpCode.Ldloca_S
+
+ /**
+ * Stores the value on top of the evaluation stack in the argument slot
+ * at a specified index, short form.
+ */
+ final val Starg_S = OpCode.Starg_S
+
+ /**
+ * Pops the current value from the top of the evaluation stack and stores it
+ * in a the local variable list at index (short form).
+ */
+ final val Stloc_S = OpCode.Stloc_S
+
+ /**
+ * Pushes a null reference (type O) onto the evaluation stack.
+ */
+ final val Ldnull = OpCode.Ldnull
+
+ /**
+ * Pushes the integer value of -1 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_M1 = OpCode.Ldc_I4_M1
+
+ /**
+ * Pushes the integer value of 0 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_0 = OpCode.Ldc_I4_0
+
+ /**
+ * Pushes the integer value of 1 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_1 = OpCode.Ldc_I4_1
+
+ /**
+ * Pushes the integer value of 2 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_2 = OpCode.Ldc_I4_2
+
+ /**
+ * Pushes the integer value of 3 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_3 = OpCode.Ldc_I4_3
+
+ /**
+ * Pushes the integer value of 4 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_4 = OpCode.Ldc_I4_4
+
+ /**
+ * Pushes the integer value of 5 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_5 = OpCode.Ldc_I4_5
+
+ /**
+ * Pushes the integer value of 6 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_6 = OpCode.Ldc_I4_6
+
+ /**
+ * Pushes the integer value of 7 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_7 = OpCode.Ldc_I4_7
+
+ /**
+ * Pushes the integer value of 8 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4_8 = OpCode.Ldc_I4_8
+
+ /**
+ * Pushes the supplied int8 value onto the evaluation stack as an int32, short form.
+ */
+ final val Ldc_I4_S = OpCode.Ldc_I4_S
+
+ /**
+ * Pushes a supplied value of type int32 onto the evaluation stack as an int32.
+ */
+ final val Ldc_I4 = OpCode.Ldc_I4
+
+ /**
+ * Pushes a supplied value of type int64 onto the evaluation stack as an int64.
+ */
+ final val Ldc_I8 = OpCode.Ldc_I8
+
+ /**
+ * Pushes a supplied value of type float32 onto the evaluation stack as type F (float).
+ */
+ final val Ldc_R4 = OpCode.Ldc_R4
+
+ /**
+ * Pushes a supplied value of type float64 onto the evaluation stack as type F (float).
+ */
+ final val Ldc_R8 = OpCode.Ldc_R8
+
+ /**
+ * Copies the current topmost value on the evaluation stack, and then pushes the copy
+ * onto the evaluation stack.
+ */
+ final val Dup = OpCode.Dup
+
+ /**
+ * Removes the value currently on top of the evaluation stack.
+ */
+ final val Pop = OpCode.Pop
+
+ /**
+ * Exits current method and jumps to specified method.
+ */
+ final val Jmp = OpCode.Jmp
+
+ /**
+ * Calls the method indicated by the passed method descriptor.
+ */
+ final val Call = OpCode.Call
+
+ /**
+ * Calls the method indicated on the evaluation stack (as a pointer to an entry point)
+ * with arguments described by a calling convention.
+ */
+ final val Calli = OpCode.Calli
+
+ /**
+ * Returns from the current method, pushing a return value (if present) from the caller's
+ * evaluation stack onto the callee's evaluation stack.
+ */
+ final val Ret = OpCode.Ret
+
+ /**
+ * Unconditionally transfers control to a target instruction (short form).
+ */
+ final val Br_S = OpCode.Br_S
+
+ /**
+ * Transfers control to a target instruction if value is false, a null reference, or zero.
+ */
+ final val Brfalse_S = OpCode.Brfalse_S
+
+ /**
+ * Transfers control to a target instruction (short form) if value is true, not null, or non-zero.
+ */
+ final val Brtrue_S = OpCode.Brtrue_S
+
+ /**
+ * Transfers control to a target instruction (short form) if two values are equal.
+ */
+ final val Beq_S = OpCode.Beq_S
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is greater than
+ * or equal to the second value.
+ */
+ final val Bge_S = OpCode.Bge_S
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is greater than
+ * the second value.
+ */
+ final val Bgt_S = OpCode.Bgt_S
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is less than
+ * or equal to the second value.
+ */
+ final val Ble_S = OpCode.Ble_S
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is less than
+ * the second value.
+ */
+ final val Blt_S = OpCode.Blt_S
+
+ /**
+ * Transfers control to a target instruction (short form) when two unsigned integer values
+ * or unordered float values are not equal.
+ */
+ final val Bne_Un_S = OpCode.Bne_Un_S
+
+ /**
+ * Transfers control to a target instruction (short form) if if the the first value is greather
+ * than the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Bge_Un_S = OpCode.Bge_Un_S
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is greater than
+ * the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Bgt_Un_S = OpCode.Bgt_Un_S
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is less than
+ * or equal to the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Ble_Un_S = OpCode.Ble_Un_S
+
+ /**
+ * Transfers control to a target instruction (short form) if the first value is less than
+ * the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Blt_Un_S = OpCode.Blt_Un_S
+
+ /**
+ * Unconditionally transfers control to a target instruction.
+ */
+ final val Br = OpCode.Br
+
+ /**
+ * Transfers control to a target instruction if value is false, a null reference
+ * (Nothing in Visual Basic), or zero.
+ */
+ final val Brfalse = OpCode.Brfalse
+
+ /**
+ * Transfers control to a target instruction if value is true, not null, or non-zero.
+ */
+ final val Brtrue = OpCode.Brtrue
+
+ /**
+ * Transfers control to a target instruction if two values are equal.
+ */
+ final val Beq = OpCode.Beq
+
+ /**
+ * Transfers control to a target instruction if the first value is greater than or
+ * equal to the second value.
+ */
+ final val Bge = OpCode.Bge
+
+ /**
+ * Transfers control to a target instruction if the first value is greater than the second value.
+ */
+ final val Bgt = OpCode.Bgt
+
+ /**
+ * Transfers control to a target instruction if the first value is less than or equal
+ * to the second value.
+ */
+ final val Ble = OpCode.Ble
+
+ /**
+ * Transfers control to a target instruction if the first value is less than the second value.
+ */
+ final val Blt = OpCode.Blt
+
+ /**
+ * Transfers control to a target instruction when two unsigned integer values or
+ * unordered float values are not equal.
+ */
+ final val Bne_Un = OpCode.Bne_Un
+
+ /**
+ * Transfers control to a target instruction if the the first value is greather than
+ * the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Bge_Un = OpCode.Bge_Un
+
+ /**
+ * Transfers control to a target instruction if the first value is greater than the
+ * second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Bgt_Un = OpCode.Bgt_Un
+
+ /**
+ * Transfers control to a target instruction if the first value is less than or equal to
+ * the second value, when comparing unsigned integer values or unordered float values.
+ */
+ final val Ble_Un = OpCode.Ble_Un
+
+ /**
+ * Transfers control to a target instruction if the first value is less than the second value,
+ * when comparing unsigned integer values or unordered float values.
+ */
+ final val Blt_Un = OpCode.Blt_Un
+
+ /**
+ * Implements a jump table.
+ */
+ final val Switch = OpCode.Switch
+
+ /**
+ * Loads a value of type int8 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_I1 = OpCode.Ldind_I1
+
+ /**
+ * Loads a value of type int16 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_I2 = OpCode.Ldind_I2
+
+ /**
+ * Loads a value of type int32 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_I4 = OpCode.Ldind_I4
+
+ /**
+ * Loads a value of type int64 as an int64 onto the evaluation stack indirectly.
+ */
+ final val Ldind_I8 = OpCode.Ldind_I8
+
+ /**
+ * Loads a value of type natural int as a natural int onto the evaluation stack indirectly.
+ */
+ final val Ldind_I = OpCode.Ldind_I
+
+ /**
+ * Loads a value of type float32 as a type F (float) onto the evaluation stack indirectly.
+ */
+ final val Ldind_R4 = OpCode.Ldind_R4
+
+ /**
+ * Loads a value of type float64 as a type F (float) onto the evaluation stack indirectly.
+ */
+ final val Ldind_R8 = OpCode.Ldind_R8
+
+ /**
+ * Loads an object reference as a type O (object reference) onto the evaluation stack indirectly.
+ */
+ final val Ldind_Ref = OpCode.Ldind_Ref
+
+ /**
+ * Loads a value of type unsigned int8 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_U1 = OpCode.Ldind_U1
+
+ /**
+ * Loads a value of type unsigned int16 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_U2 = OpCode.Ldind_U2
+
+ /**
+ * Loads a value of type unsigned int32 as an int32 onto the evaluation stack indirectly.
+ */
+ final val Ldind_U4 = OpCode.Ldind_U4
+
+ /**
+ * Stores a object reference value at a supplied address.
+ */
+ final val Stind_Ref = OpCode.Stind_Ref
+
+ /**
+ * Stores a value of type int8 at a supplied address.
+ */
+ final val Stind_I1 = OpCode.Stind_I1
+
+ /**
+ * Stores a value of type int16 at a supplied address.
+ */
+ final val Stind_I2 = OpCode.Stind_I2
+
+ /**
+ * Stores a value of type int32 at a supplied address.
+ */
+ final val Stind_I4 = OpCode.Stind_I4
+
+ /**
+ * Stores a value of type int64 at a supplied address.
+ */
+ final val Stind_I8 = OpCode.Stind_I8
+
+ /**
+ * Stores a value of type float32 at a supplied address.
+ */
+ final val Stind_R4 = OpCode.Stind_R4
+
+ /**
+ * Stores a value of type float64 at a supplied address.
+ */
+ final val Stind_R8 = OpCode.Stind_R8
+
+ /**
+ * Subtracts one value from another and pushes the result onto the evaluation stack.
+ */
+ final val Sub = OpCode.Sub
+
+ /**
+ * Multiplies two values and pushes the result on the evaluation stack.
+ */
+ final val Mul = OpCode.Mul
+
+ /**
+ * Divides two values and pushes the result as a floating-point (type F) or
+ * quotient (type int32) onto the evaluation stack.
+ */
+ final val Div = OpCode.Div
+
+ /**
+ * Divides two unsigned integer values and pushes the result (int32) onto the evaluation stack.
+ */
+ final val Div_Un = OpCode.Div_Un
+
+ /**
+ * Divides two values and pushes the remainder onto the evaluation stack.
+ */
+ final val Rem = OpCode.Rem
+
+ /**
+ * Divides two unsigned values and pushes the remainder onto the evaluation stack.
+ */
+ final val Rem_Un = OpCode.Rem_Un
+
+ /**
+ * Computes the bitwise AND of two values and pushes the result onto the evalution stack.
+ */
+ final val And = OpCode.And
+
+ /**
+ * Compute the bitwise complement of the two integer values on top of the stack and
+ * pushes the result onto the evaluation stack.
+ */
+ final val Or = OpCode.Or
+
+ /**
+ * Computes the bitwise XOR of the top two values on the evaluation stack,
+ * pushing the result onto the evaluation stack.
+ */
+ final val Xor = OpCode.Xor
+
+ /**
+ * Shifts an integer value to the left (in zeroes) by a specified number of bits,
+ * pushing the result onto the evaluation stack.
+ */
+ final val Shl = OpCode.Shl
+
+ /**
+ * Shifts an integer value (in sign) to the right by a specified number of bits,
+ * pushing the result onto the evaluation stack.
+ */
+ final val Shr = OpCode.Shr
+
+ /**
+ * Shifts an unsigned integer value (in zeroes) to the right by a specified number of bits,
+ * pushing the result onto the evaluation stack.
+ */
+ final val Shr_Un = OpCode.Shr_Un
+
+ /**
+ * Negates a value and pushes the result onto the evaluation stack.
+ */
+ final val Neg = OpCode.Neg
+
+ /**
+ * Computes the bitwise complement of the integer value on top of the stack and pushes
+ * the result onto the evaluation stack as the same type.
+ */
+ final val Not = OpCode.Not
+
+ /**
+ * Converts the value on top of the evaluation stack to int8, then extends (pads) it to int32.
+ */
+ final val Conv_I1 = OpCode.Conv_I1
+
+ /**
+ * Converts the value on top of the evaluation stack to int16, then extends (pads) it to int32.
+ */
+ final val Conv_I2 = OpCode.Conv_I2
+
+ /**
+ * Converts the value on top of the evaluation stack to int32.
+ */
+ final val Conv_I4 = OpCode.Conv_I4
+
+ /**
+ * Converts the value on top of the evaluation stack to int64.
+ */
+ final val Conv_I8 = OpCode.Conv_I8
+
+ /**
+ * Converts the value on top of the evaluation stack to float32.
+ */
+ final val Conv_R4 = OpCode.Conv_R4
+
+ /**
+ * Converts the value on top of the evaluation stack to float64.
+ */
+ final val Conv_R8 = OpCode.Conv_R8
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned int32, and extends it to int32.
+ */
+ final val Conv_U4 = OpCode.Conv_U4
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned int64, and extends it to int64.
+ */
+ final val Conv_U8 = OpCode.Conv_U8
+
+ /**
+ * Calls a late-bound method on an object, pushing the return value onto the evaluation stack.
+ */
+ final val Callvirt = OpCode.Callvirt
+
+ /**
+ * Copies the value type located at the address of an object (type &, * or natural int)
+ * to the address of the destination object (type &, * or natural int).
+ */
+ final val Cpobj = OpCode.Cpobj
+
+ /**
+ * Copies the value type object pointed to by an address to the top of the evaluation stack.
+ */
+ final val Ldobj = OpCode.Ldobj
+
+ /**
+ * Pushes a new object reference to a string literal stored in the metadata.
+ */
+ final val Ldstr = OpCode.Ldstr
+
+ /**
+ * Creates a new object or a new instance of a value type, pushing an object reference
+ * (type O) onto the evaluation stack.
+ */
+ final val Newobj = OpCode.Newobj
+
+ /**
+ * Attempts to cast an object passed by reference to the specified class.
+ */
+ final val Castclass = OpCode.Castclass
+
+ /**
+ * Tests whether an object reference (type O) is an instance of a particular class.
+ */
+ final val Isinst = OpCode.Isinst
+
+ /**
+ * Converts the unsigned integer value on top of the evaluation stack to float32.
+ */
+ final val Conv_R_Un = OpCode.Conv_R_Un
+
+ /**
+ * Converts the boxed representation of a value type to its unboxed form.
+ */
+ final val Unbox = OpCode.Unbox
+
+ /**
+ * Throws the exception object currently on the evaluation stack.
+ */
+ final val Throw = OpCode.Throw
+
+ /**
+ * Finds the value of a field in the object whose reference is currently
+ * on the evaluation stack.
+ */
+ final val Ldfld = OpCode.Ldfld
+
+ /**
+ * Finds the address of a field in the object whose reference is currently
+ * on the evaluation stack.
+ */
+ final val Ldflda = OpCode.Ldflda
+
+ /**
+ * Pushes the value of a static field onto the evaluation stack.
+ */
+ final val Ldsfld = OpCode.Ldsfld
+
+ /**
+ * Pushes the address of a static field onto the evaluation stack.
+ */
+ final val Ldsflda = OpCode.Ldsflda
+
+ /**
+ * Replaces the value stored in the field of an object reference or pointer with a new value.
+ */
+ final val Stfld = OpCode.Stfld
+
+ /**
+ * Replaces the value of a static field with a value from the evaluation stack.
+ */
+ final val Stsfld = OpCode.Stsfld
+
+ /**
+ * Copies a value of a specified type from the evaluation stack into a supplied memory address.
+ */
+ final val Stobj = OpCode.Stobj
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed int8 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I1_Un = OpCode.Conv_Ovf_I1_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed int16 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I2_Un = OpCode.Conv_Ovf_I2_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed int32,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I4_Un = OpCode.Conv_Ovf_I4_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed int64,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I8_Un = OpCode.Conv_Ovf_I8_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to signed natural int,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I_Un = OpCode.Conv_Ovf_I_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned int8 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U1_Un = OpCode.Conv_Ovf_U1_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned int16 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U2_Un = OpCode.Conv_Ovf_U2_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned int32,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U4_Un = OpCode.Conv_Ovf_U4_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned int64,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U8_Un = OpCode.Conv_Ovf_U8_Un
+
+ /**
+ * Converts the unsigned value on top of the evaluation stack to unsigned natural int,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U_Un = OpCode.Conv_Ovf_U_Un
+
+ /**
+ * Converts a value type to an object reference (type O).
+ */
+ final val Box = OpCode.Box
+
+ /**
+ * Pushes an object reference to a new zero-based, one-dimensional array whose elements
+ * are of a specific type onto the evaluation stack.
+ */
+ final val Newarr = OpCode.Newarr
+
+ /**
+ * Pushes the number of elements of a zero-based, one-dimensional array
+ * onto the evaluation stack.
+ */
+ final val Ldlen = OpCode.Ldlen
+
+ /**
+ * Loads the address of the array element at a specified array index onto
+ * the top of the evaluation stack as type & (managed pointer).
+ */
+ final val Ldelema = OpCode.Ldelema
+
+ /**
+ * Loads the element with type natural int at a specified array index onto the top
+ * of the evaluation stack as a natural int.
+ */
+ final val Ldelem_I = OpCode.Ldelem_I
+
+ /**
+ * Loads the element with type int8 at a specified array index onto the top of the
+ * evaluation stack as an int32.
+ */
+ final val Ldelem_I1 = OpCode.Ldelem_I1
+
+ /**
+ * Loads the element with type int16 at a specified array index onto the top of
+ * the evaluation stack as an int32.
+ */
+ final val Ldelem_I2 = OpCode.Ldelem_I2
+
+ /**
+ * Loads the element with type int32 at a specified array index onto the top of the
+ * evaluation stack as an int32.
+ */
+ final val Ldelem_I4 = OpCode.Ldelem_I4
+
+ /**
+ * Loads the element with type int64 at a specified array index onto the top of the
+ * evaluation stack as an int64.
+ */
+ final val Ldelem_I8 = OpCode.Ldelem_I8
+
+ /**
+ * Loads the element with type float32 at a specified array index onto the top of the
+ * evaluation stack as type F (float)
+ */
+ final val Ldelem_R4 = OpCode.Ldelem_R4
+
+ /**
+ * Loads the element with type float64 at a specified array index onto the top of the
+ * evaluation stack as type F (float) .
+ */
+ final val Ldelem_R8 = OpCode.Ldelem_R8
+
+ /**
+ * Loads the element containing an object reference at a specified array index onto
+ * the top of the evaluation stack as type O (object reference).
+ */
+ final val Ldelem_Ref = OpCode.Ldelem_Ref
+
+ /**
+ * Loads the element with type unsigned int8 at a specified array index onto the top
+ * of the evaluation stack as an int32.
+ */
+ final val Ldelem_U1 = OpCode.Ldelem_U1
+
+ /**
+ * Loads the element with type unsigned int16 at a specified array index onto the top
+ * of the evaluation stack as an int32.
+ */
+ final val Ldelem_U2 = OpCode.Ldelem_U2
+
+ /**
+ * Loads the element with type unsigned int32 at a specified array index onto the top
+ * of the evaluation stack as an int32.
+ */
+ final val Ldelem_U4 = OpCode.Ldelem_U4
+
+ /**
+ * Replaces the array element at a given index with the natural int value on
+ * the evaluation stack.
+ */
+ final val Stelem_I = OpCode.Stelem_I
+
+ /**
+ * Replaces the array element at a given index with the int8 value on the evaluation stack.
+ */
+ final val Stelem_I1 = OpCode.Stelem_I1
+
+ /**
+ * Replaces the array element at a given index with the int16 value on the evaluation stack.
+ */
+ final val Stelem_I2 = OpCode.Stelem_I2
+
+ /**
+ * Replaces the array element at a given index with the int32 value on the evaluation stack.
+ */
+ final val Stelem_I4 = OpCode.Stelem_I4
+
+ /**
+ * Replaces the array element at a given index with the int64 value on the evaluation stack.
+ */
+ final val Stelem_I8 = OpCode.Stelem_I8
+
+ /**
+ * Replaces the array element at a given index with the float32 value on the evaluation stack.
+ */
+ final val Stelem_R4 = OpCode.Stelem_R4
+
+ /**
+ * Replaces the array element at a given index with the float64 value on the evaluation stack.
+ */
+ final val Stelem_R8 = OpCode.Stelem_R8
+
+ /**
+ * Replaces the array element at a given index with the object ref value (type O)
+ * on the evaluation stack.
+ */
+ final val Stelem_Ref = OpCode.Stelem_Ref
+
+ /**
+ * Converts the signed value on top of the evaluation stack to signed int8 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I1 = OpCode.Conv_Ovf_I1
+
+ /**
+ * Converts the signed value on top of the evaluation stack to signed int16 and
+ * extending it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I2 = OpCode.Conv_Ovf_I2
+
+ /**
+ * Converts the signed value on top of the sevaluation tack to signed int32,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I4 = OpCode.Conv_Ovf_I4
+
+ /**
+ * Converts the signed value on top of the evaluation stack to signed int64,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I8 = OpCode.Conv_Ovf_I8
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned int8 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U1 = OpCode.Conv_Ovf_U1
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned int16 and
+ * extends it to int32, throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U2 = OpCode.Conv_Ovf_U2
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned int32,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U4 = OpCode.Conv_Ovf_U4
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned int64,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U8 = OpCode.Conv_Ovf_U8
+
+ /**
+ * Retrieves the address (type &) embedded in a typed reference.
+ */
+ final val Refanyval = OpCode.Refanyval
+
+ /**
+ * Retrieves the type token embedded in a typed reference .
+ */
+ final val Refanytype = OpCode.Refanytype
+
+ /**
+ * Throws ArithmeticException if value is not a finite number.
+ */
+ final val Ckfinite = OpCode.Ckfinite
+
+ /**
+ * Pushes a typed reference to an instance of a specific type onto the evaluation stack.
+ */
+ final val Mkrefany = OpCode.Mkrefany
+
+ /**
+ * Converts a metadata token to its runtime representation, pushing it onto the evaluation stack.
+ */
+ final val Ldtoken = OpCode.Ldtoken
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned int8, and extends it to int32.
+ */
+ final val Conv_U1 = OpCode.Conv_U1
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned int16, and extends it to int32.
+ */
+ final val Conv_U2 = OpCode.Conv_U2
+
+ /**
+ * Converts the value on top of the evaluation stack to natural int.
+ */
+ final val Conv_I = OpCode.Conv_I
+
+ /**
+ * Converts the signed value on top of the evaluation stack to signed natural int,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_I = OpCode.Conv_Ovf_I
+
+ /**
+ * Converts the signed value on top of the evaluation stack to unsigned natural int,
+ * throwing OverflowException on overflow.
+ */
+ final val Conv_Ovf_U = OpCode.Conv_Ovf_U
+
+ /**
+ * Adds two integers, performs an overflow check, and pushes the result
+ * onto the evaluation stack.
+ */
+ final val Add_Ovf = OpCode.Add_Ovf
+
+ /**
+ * Adds two unsigned integer values, performs an overflow check, and pushes the result
+ * onto the evaluation stack.
+ */
+ final val Add_Ovf_Un = OpCode.Add_Ovf_Un
+
+ /**
+ * Multiplies two integer values, performs an overflow check, and pushes the result
+ * onto the evaluation stack.
+ */
+ final val Mul_Ovf = OpCode.Mul_Ovf
+
+ /**
+ * Multiplies two unsigned integer values , performs an overflow check ,
+ * and pushes the result onto the evaluation stack.
+ */
+ final val Mul_Ovf_Un = OpCode.Mul_Ovf_Un
+
+ /**
+ * Subtracts one integer value from another, performs an overflow check,
+ * and pushes the result onto the evaluation stack.
+ */
+ final val Sub_Ovf = OpCode.Sub_Ovf
+
+ /**
+ * Subtracts one unsigned integer value from another, performs an overflow check,
+ * and pushes the result onto the evaluation stack.
+ */
+ final val Sub_Ovf_Un = OpCode.Sub_Ovf_Un
+
+ /**
+ * Transfers control from the fault or finally clause of an exception block back to
+ * the Common Language Infrastructure (CLI) exception handler.
+ */
+ final val Endfinally = OpCode.Endfinally
+
+ /**
+ * Exits a protected region of code, unconditionally tranferring control
+ * to a specific target instruction.
+ */
+ final val Leave = OpCode.Leave
+
+ /**
+ * Exits a protected region of code, unconditionally tranferring control
+ * to a target instruction (short form).
+ */
+ final val Leave_S = OpCode.Leave_S
+
+ /**
+ * Stores a value of type natural int at a supplied address.
+ */
+ final val Stind_I = OpCode.Stind_I
+
+ /**
+ * Converts the value on top of the evaluation stack to unsigned natural int,
+ * and extends it to natural int.
+ */
+ final val Conv_U = OpCode.Conv_U
+
+ /**
+ * Returns an unmanaged pointer to the argument list of the current method.
+ */
+ final val Arglist = OpCode.Arglist
+
+ /**
+ * Compares two values. If they are equal, the integer value 1 (int32) is pushed
+ * onto the evaluation stack otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Ceq = OpCode.Ceq
+
+ /**
+ * Compares two values. If the first value is greater than the second,
+ * the integer value 1 (int32) is pushed onto the evaluation stack
+ * otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Cgt = OpCode.Cgt
+
+ /**
+ * Compares two unsigned or unordered values. If the first value is greater than
+ * the second, the integer value 1 (int32) is pushed onto the evaluation stack
+ * otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Cgt_Un = OpCode.Cgt_Un
+
+ /**
+ * Compares two values. If the first value is less than the second,
+ * the integer value 1 (int32) is pushed onto the evaluation stack
+ * otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Clt = OpCode.Clt
+
+ /**
+ * Compares the unsigned or unordered values value1 and value2. If value1 is
+ * less than value2, then the integer value 1 (int32) is pushed onto the
+ * evaluation stack otherwise 0 (int32) is pushed onto the evaluation stack.
+ */
+ final val Clt_Un = OpCode.Clt_Un
+
+ /**
+ * Pushes an unmanaged pointer (type natural int) to the native code implementing
+ * a specific method onto the evaluation stack.
+ */
+ final val Ldftn = OpCode.Ldftn
+
+ /**
+ * Pushes an unmanaged pointer (type natural int) to the native code implementing
+ * a particular virtual method associated with a specified object onto the evaluation stack.
+ */
+ final val Ldvirtftn = OpCode.Ldvirtftn
+
+ /**
+ * Loads an argument (referenced by a specified index value) onto the stack.
+ */
+ final val Ldarg = OpCode.Ldarg
+
+ /**
+ * Load an argument address onto the evaluation stack.
+ */
+ final val Ldarga = OpCode.Ldarga
+
+ /**
+ * Loads the local variable at a specific index onto the evaluation stack.
+ */
+ final val Ldloc = OpCode.Ldloc
+
+ /**
+ * Loads the address of the local variable at a specific index onto the evaluation stack.
+ */
+ final val Ldloca = OpCode.Ldloca
+
+ /**
+ * Stores the value on top of the evaluation stack in the argument slot at a specified index.
+ */
+ final val Starg = OpCode.Starg
+
+ /**
+ * Pops the current value from the top of the evaluation stack and stores it in a
+ * the local variable list at a specified index.
+ */
+ final val Stloc = OpCode.Stloc
+
+ /**
+ * Allocates a certain number of bytes from the local dynamic memory pool and pushes the
+ * address (a transient pointer, type *) of the first allocated byte onto the evaluation stack.
+ */
+ final val Localloc = OpCode.Localloc
+
+ /**
+ * Transfers control from the filter clause of an exception back to the
+ * Common Language Infrastructure (CLI) exception handler.
+ */
+ final val Endfilter = OpCode.Endfilter
+
+ /**
+ * Indicates that an address currently atop the evaluation stack might not be aligned
+ * to the natural size of the immediately following ldind, stind, ldfld, stfld, ldobj,
+ * stobj, initblk, or cpblk instruction.
+ */
+ final val Unaligned = OpCode.Unaligned
+
+ /**
+ * Specifies that an address currently atop the evaluation stack might be volatile,
+ * and the results of reading that location cannot be cached or that multiple stores
+ * to that location cannot be suppressed.
+ */
+ final val Volatile = OpCode.Volatile
+
+ /**
+ * Performs a postfixed method call instruction such that the current method's stack
+ * frame is removed before the actual call instruction is executed.
+ */
+ final val Tailcall = OpCode.Tailcall
+
+ /**
+ * Initializes all the fields of the object at a specific address to a null reference
+ * or a 0 of the appropriate primitive type.
+ */
+ final val Initobj = OpCode.Initobj
+
+ /**
+ * Copies a specified number bytes from a source address to a destination address .
+ */
+ final val Cpblk = OpCode.Cpblk
+
+ /**
+ * Initializes a specified block of memory at a specific address to a given size
+ * and initial value.
+ */
+ final val Initblk = OpCode.Initblk
+
+ /**
+ * Rethrows the current exception.
+ */
+ final val Rethrow = OpCode.Rethrow
+
+ /**
+ * Pushes the size, in bytes, of a supplied value type onto the evaluation stack.
+ */
+ final val Sizeof = OpCode.Sizeof
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ParameterBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ParameterBuilder.scala
new file mode 100644
index 0000000000..d07a88bd0e
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ParameterBuilder.scala
@@ -0,0 +1,45 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: ParameterBuilder.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil.Type
+import ch.epfl.lamp.compiler.msil.ConstructorInfo
+import ch.epfl.lamp.compiler.msil.ParameterInfo
+import java.io.IOException
+
+/**
+ * Creates or associates parameter information.
+ * Parameter attributes need to consistent with the method signature.
+ * If you specify Out attributes for a parameter, you should ensure that
+ * the type of that method parameter is a ByRef type
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class ParameterBuilder(name: String, tpe: Type, attr: Int, pos: Int)
+ extends ParameterInfo(name, tpe, attr, pos)
+ with ICustomAttributeSetter
+ with Visitable
+{
+
+ //##########################################################################
+
+ /** Sets a custom attribute. */
+ def SetCustomAttribute(constr: ConstructorInfo, value: Array[byte]) {
+ addCustomAttribute(constr, value)
+ }
+
+ //##########################################################################
+
+ /** The apply method for a visitor */
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseParameterBuilder(this)
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala
new file mode 100644
index 0000000000..3da17e83ef
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala
@@ -0,0 +1,94 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies in MSIL
+ */
+
+// $Id: ILPrinterVisitor.java 8664 2006-09-12 16:48:03Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import java.io.FileWriter
+import java.io.BufferedWriter
+import java.io.PrintWriter
+import java.io.IOException
+import java.util.Iterator
+import java.util.HashMap
+import java.util.Arrays
+
+import ch.epfl.lamp.compiler.msil._
+import ch.epfl.lamp.compiler.msil.emit
+import ch.epfl.lamp.compiler.msil.util.Table
+
+/**
+ * The MSIL printer Vistor. It prints a complete
+ * assembly in a single file. Then this file can be compiled by ilasm.
+ *
+ * @author Nikolay Mihaylov
+ * @author Daniel Lorch
+ * @version 1.0
+ */
+final class SingleFileILPrinterVisitor(_fileName: String) extends ILPrinterVisitor {
+ var fileName: String = _fileName
+
+ out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)))
+
+ /**
+ * Visit an AssemblyBuilder
+ */
+ @throws(classOf[IOException])
+ def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) {
+ ILPrinterVisitor.currAssembly = assemblyBuilder
+
+ // first get the entryPoint
+ this.entryPoint = assemblyBuilder.EntryPoint
+
+ // all external assemblies
+ as = assemblyBuilder.getExternAssemblies()
+ Arrays.sort(as, assemblyNameComparator)
+
+ assemblyBuilder.generatedFiles.add(fileName)
+ printAssemblyBoilerplate()
+
+ // print each module
+ var m: Array[Module] = assemblyBuilder.GetModules()
+ nomembers = true
+ for(val i <- 0 until m.length) {
+ print(m(i).asInstanceOf[ModuleBuilder])
+ }
+
+ nomembers = false
+ for(val i <- 0 until m.length) {
+ print(m(i).asInstanceOf[ModuleBuilder])
+ }
+ // close out file
+ out.close()
+ ILPrinterVisitor.currAssembly = null
+ }
+
+ /**
+ * Visit a ModuleBuilder
+ */
+ @throws(classOf[IOException])
+ def caseModuleBuilder(module: ModuleBuilder) {
+ // print module declaration
+ currentModule = module
+ if (nomembers) {
+ print(".module \'"); print(module.Name); println("\'")
+ printAttributes(module)
+ }
+
+ if (!module.globalsCreated)
+ module.CreateGlobalFunctions()
+
+ var m: Array[MethodInfo] = module.GetMethods()
+ for(val i <- 0 until m.length) {
+ print(m(i).asInstanceOf[MethodBuilder])
+ }
+
+ var t: Array[Type] = module.GetTypes()
+ for(val i <- 0 until t.length) {
+ print(t(i).asInstanceOf[TypeBuilder])
+ }
+ currentModule = null
+ }
+
+} // class SingleFileILPrinterVisitor
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
new file mode 100644
index 0000000000..ca95a2b24d
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
@@ -0,0 +1,230 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: TypeBuilder.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import ch.epfl.lamp.compiler.msil._
+import java.util.HashMap
+import java.util.ArrayList
+import java.util.Iterator
+import java.io.IOException
+
+/**
+ * Defines and creates new instances of classes during runtime.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+class TypeBuilder (module: Module, attributes: int, fullName: String, baseType: Type, interfaces: Array[Type], declType: Type)
+ extends Type(module, attributes, fullName, baseType, interfaces, declType, 0)
+ with ICustomAttributeSetter
+ with Visitable
+{
+ import TypeBuilder._
+
+ //##########################################################################
+ // public members
+
+ /** 'Bakes' the type. */
+ def CreateType(): Type = {
+ fields = fieldBuilders.toArray(new Array[FieldInfo](fieldBuilders.size())).asInstanceOf[Array[FieldInfo]]
+ methods = methodBuilders.toArray(new Array[MethodInfo](methodBuilders.size())).asInstanceOf[Array[MethodInfo]]
+ constructors = constructorBuilders.toArray(new Array[ConstructorInfo](constructorBuilders.size())).asInstanceOf[Array[ConstructorInfo]]
+ nestedTypes = nestedTypeBuilders.toArray(new Array[Type](nestedTypeBuilders.size())).asInstanceOf[Array[Type]]
+
+ raw = false
+ if (DeclaringType == null)
+ Module.asInstanceOf[ModuleBuilder].addType(this)
+ return this
+ }
+
+ /**
+ * Adds a new field to the class, with the given name,
+ * attributes and field type.
+ */
+ def DefineField(name: String, `type`: Type, attrs: short): FieldBuilder = {
+ val field: FieldBuilder = new FieldBuilder(name, this, attrs, `type`)
+ fieldBuilders.add(field)
+ return field
+ }
+
+ /**
+ * Adds a new method to the class, with the given name and
+ * method signature.
+ */
+ def DefineMethod(name: String, attrs: short, returnType: Type, paramTypes: Array[Type]): MethodBuilder = {
+ val method = new MethodBuilder(name, this, attrs, returnType, paramTypes)
+ val methods = methodBuilders.iterator()
+ while(methods.hasNext()) {
+ val m = methods.next().asInstanceOf[MethodInfo]
+ if (methodsEqual(m, method))
+ throw new RuntimeException("["+ Assembly() +
+ "] Method has already been defined: " + m)
+ }
+ methodBuilders.add(method)
+ return method
+ }
+
+ /**
+ * Adds a new constructor to the class, with the given attributes
+ * and signature.
+ */
+ def DefineConstructor(attrs: short, callingConvention: short, paramTypes: Array[Type]): ConstructorBuilder = {
+ val constr = new ConstructorBuilder(this, attrs, paramTypes)
+ constructorBuilders.add(constr)
+ return constr
+ }
+
+ /**
+ * Defines a nested type given its name.
+ */
+ def DefineNestedType(name: String, attributes: int, baseType: Type, interfaces: Array[Type]): TypeBuilder = {
+ val nested = nestedTypeBuilders.iterator()
+ while(nested.hasNext()) {
+ val nt = nested.next().asInstanceOf[TypeBuilder]
+ if (nt.Name.equals(name)) {
+ val message = "Nested type " + name + " has already been defined: " + nt
+ throw new RuntimeException(message)
+ }
+ }
+ val t = new TypeBuilder(Module, attributes, name, baseType, interfaces, this)
+ nestedTypeBuilders.add(t)
+ return t
+ }
+
+ /** Get the field with the corresponding name. */
+ override def GetField(name: String): FieldInfo = {
+ testRaw(name)
+ return super.GetField(name)
+ }
+
+ /** Get all fields of the current Type. */
+ override def GetFields(): Array[FieldInfo] = {
+ testRaw("<GetFields>")
+ return super.GetFields()
+ }
+
+ /**
+ * Searches for a public instance constructor whose parameters
+ * match the types in the specified array.
+ */
+ override def GetConstructor(params: Array[Type]): ConstructorInfo = {
+ testRaw(".ctor" + types2String(params))
+ return super.GetConstructor(params)
+ }
+
+ /**
+ * Returns all the public constructors defined for the current Type.
+ */
+ override def GetConstructors(): Array[ConstructorInfo] = {
+ testRaw("<GetConstructors>")
+ return super.GetConstructors()
+ }
+
+ /**
+ * Searches for the specified public method whose parameters
+ * match the specified argument types.
+ */
+ override def GetMethod(name: String, params: Array[Type]): MethodInfo = {
+ testRaw(name + types2String(params))
+ return super.GetMethod(name, params)
+ }
+
+ /** Returns all the public methods of the current Type. */
+ override def GetMethods(): Array[MethodInfo] = {
+ testRaw("<GetMethods>")
+ return super.GetMethods()
+ }
+
+ /** Searches for the nested type with the specified name. */
+ override def GetNestedType(name: String): Type = {
+ testRaw(name)
+ return super.GetNestedType(name)
+ }
+
+ /** Returns all the types nested within the current Type. */
+ override def GetNestedTypes(): Array[Type] = {
+ testRaw("<GetNestedTypes>")
+ return super.GetNestedTypes()
+ }
+
+ /** Sets a custom attribute. */
+ def SetCustomAttribute(constr: ConstructorInfo, value: Array[byte]) {
+ addCustomAttribute(constr, value)
+ }
+
+ def setPosition(sourceLine: int, sourceFilename: String) {
+ this.sourceLine = sourceLine
+ this.sourceFilename = sourceFilename
+ }
+
+ def setSourceFilepath(sourceFilepath: String) {
+ this.sourceFilepath = sourceFilepath
+ }
+
+ //##########################################################################
+ // protected members
+
+ var sourceLine: Int = _
+ var sourceFilename: String = _
+ var sourceFilepath: String = _
+
+ var fieldBuilders = new ArrayList[FieldBuilder]()
+ var methodBuilders = new ArrayList[MethodBuilder]()
+ var constructorBuilders = new ArrayList[ConstructorBuilder]()
+ var nestedTypeBuilders = new ArrayList[TypeBuilder]()
+
+ // shows if the type is 'raw', i.e. still subject to changes
+ private var raw = true
+
+ // throws an exception if the type is 'raw',
+ // i.e. not finalized by call to CreateType
+ protected def testRaw(member: String) {
+ if (raw)
+ throw new RuntimeException
+ ("Not supported for TypeBuilder before CreateType(): " +
+ FullName + "::" + member)
+ }
+
+ //##########################################################################
+ // public members not part of the Reflection.Emit.TypeBuilder interface.
+
+ /** The apply method for a visitor. */
+ @throws(classOf[IOException])
+ def apply(v: Visitor) {
+ v.caseTypeBuilder(this)
+ }
+
+ //##########################################################################
+
+} // class TypeBuilder
+
+object TypeBuilder {
+ def types2String(types: Array[Type]): String = {
+ var s = new StringBuffer("(")
+ for(val i <- 0 until types.length) {
+ if (i > 0) s.append(", ")
+ s.append(types(i))
+ }
+ s.append(")")
+ return s.toString()
+ }
+
+ def methodsEqual(m1: MethodInfo, m2: MethodInfo): boolean = {
+ if (!m1.Name.equals(m2.Name))
+ return false
+ if (m1.ReturnType != m2.ReturnType)
+ return false
+ val p1 = m1.GetParameters()
+ val p2 = m2.GetParameters()
+ if (p1.length != p2.length)
+ return false
+ for(val i <- 0 until p1.length)
+ if (p1(i).ParameterType != p2(i).ParameterType)
+ return false
+ return true
+ }
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitable.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitable.scala
new file mode 100644
index 0000000000..7d065e0ae5
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitable.scala
@@ -0,0 +1,25 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: Visitable.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import java.io.IOException
+
+/**
+ * The Visitable interface
+ */
+trait Visitable {
+
+ //##########################################################################
+
+ /**
+ * the visitable method to apply a visitor
+ */
+ @throws(classOf[IOException])
+ def apply(v: Visitor): Unit
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitor.scala
new file mode 100644
index 0000000000..c35e8be317
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/Visitor.scala
@@ -0,0 +1,59 @@
+/*
+ * System.Reflection.Emit-like API for writing .NET assemblies to MSIL
+ */
+
+// $Id: Visitor.java 14655 2008-04-15 09:37:02Z lorch $
+
+package ch.epfl.lamp.compiler.msil.emit
+
+import java.io.IOException
+
+/**
+ * The Visitor interface to walk through the MSIL code Builder hierarchy.
+ */
+trait Visitor {
+
+ //##########################################################################
+
+ /** Visit an AssemblyBuilder */
+ @throws(classOf[IOException])
+ def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder): Unit
+
+ /** Visit a ModuleBuilder */
+ @throws(classOf[IOException])
+ def caseModuleBuilder(moduleBuilder: ModuleBuilder): Unit
+
+ /** Visit a TypeBuilder */
+ @throws(classOf[IOException])
+ def caseTypeBuilder(typeBuilder: TypeBuilder): Unit
+
+ /** Visit a FieldBuilder */
+ @throws(classOf[IOException])
+ def caseFieldBuilder(fieldBuilder: FieldBuilder): Unit
+
+ /** Visit a ConstructorBuilder */
+ @throws(classOf[IOException])
+ def caseConstructorBuilder(constructorBuilder: ConstructorBuilder): Unit
+
+ /** Visit a MethodBuilder */
+ @throws(classOf[IOException])
+ def caseMethodBuilder(methodBuilder: MethodBuilder): Unit
+
+ /** Visit a ParameterBuilder */
+ @throws(classOf[IOException])
+ def caseParameterBuilder(parameterBuilder: ParameterBuilder): Unit
+
+ /** Visit an ILGenerator */
+ @throws(classOf[IOException])
+ def caseILGenerator(iLGenerator: ILGenerator): Unit
+
+ /** Visit an OpCode */
+ @throws(classOf[IOException])
+ def caseOpCode(opCode: OpCode): Unit
+
+ /** Visit a LocalBuilder */
+ @throws(classOf[IOException])
+ def caseLocalBuilder(localBuilder: LocalBuilder): Unit
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/CustomAttributesTest.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/CustomAttributesTest.java
new file mode 100644
index 0000000000..5067489693
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/tests/CustomAttributesTest.java
@@ -0,0 +1,32 @@
+// $Id$
+
+package ch.epfl.lamp.compiler.msil.tests;
+
+import ch.epfl.lamp.compiler.msil.*;
+import ch.epfl.lamp.compiler.msil.util.Table;
+
+import java.io.PrintStream;
+
+public class CustomAttributesTest {
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ System.err.println("You must supply a filename!");
+ System.exit(1);
+ }
+
+ Assembly assem = Assembly.LoadFrom(args[0]);
+ Type.initMSCORLIB(assem);
+
+ testCustomAttributes();
+ }
+
+ public static void testCustomAttributes() {
+ Object[] attrs = Type.GetType("System.ObsoleteAttribute")
+ .GetCustomAttributes(false);
+ assert attrs != null;
+ for (int i = 0; i < attrs.length; i++) {
+ System.out.println("\t" + attrs[i]);
+ }
+ }
+
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/JavaTypeTest.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/JavaTypeTest.java
new file mode 100644
index 0000000000..0c2d12aa0f
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/tests/JavaTypeTest.java
@@ -0,0 +1,19 @@
+// $Id$
+
+package ch.epfl.lamp.compiler.msil.tests;
+
+import ch.epfl.lamp.compiler.msil.*;
+import ch.epfl.lamp.compiler.msil.util.VJSAssembly;
+
+public class JavaTypeTest {
+
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ System.err.println("usage: java test.JavaTypeTest classname");
+ System.exit(1);
+ }
+
+ Type type = VJSAssembly.VJSLIB.GetType(args[0]);
+ MembersTest.dumpType(System.out, type);
+ }
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/MembersTest.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/MembersTest.java
new file mode 100644
index 0000000000..4f20632ce3
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/tests/MembersTest.java
@@ -0,0 +1,101 @@
+// $Id$
+
+package ch.epfl.lamp.compiler.msil.tests;
+
+import ch.epfl.lamp.compiler.msil.*;
+import ch.epfl.lamp.compiler.msil.util.Table;
+
+import java.io.PrintStream;
+
+public class MembersTest {
+
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ System.err.println
+ ("usage: java test.MembersTest assembly [classname]");
+ System.exit(1);
+ }
+
+ Assembly mscorlib = Assembly.LoadFrom("mscorlib.dll");
+ Type.initMSCORLIB(mscorlib);
+ Assembly assem = Assembly.LoadFrom(args[0]);
+ if (args.length > 1) {
+ Type type = assem.GetType(args[1]);
+ if (type != null)
+ dumpMember(System.out, type);
+ else System.err.println("Cannot find type " + args[1]
+ + " in " + assem);
+ } else {
+ Type[] types = assem.GetTypes();
+ System.out.println("Number of types in assembly " + assem
+ + " -> " + types.length);
+ dumpCustomAttributes(System.out, "assembly: ", assem);
+ Module[] modules = assem.GetModules();
+ for (int i = 0; i < modules.length; i++) {
+ dumpCustomAttributes(System.out, "module " + modules[i] + ": ",
+ modules[i]);
+ }
+ dumpMembers(System.out, types);
+ }
+ }
+
+ public static final void dumpMember(PrintStream out, MemberInfo member) {
+ try {
+ if (member.MemberType() == MemberTypes.TypeInfo
+ || member.MemberType() == MemberTypes.NestedType) {
+ Type type = (Type)member;
+ dumpCustomAttributes(out, "", type);
+ out.print(TypeAttributes.accessModsToString(type.Attributes));
+ out.print(type.IsInterface() ? " interface " : " class ");
+ out.print(type);
+ if (type.BaseType() != null)
+ out.println(" extends " + type.BaseType());
+ Type[] ifaces = type.GetInterfaces();
+ if (ifaces.length > 0) {
+ out.print("\timplements ");
+ for (int i = 0; i < ifaces.length; i++) {
+ out.print(ifaces[i]);
+ if (i < (ifaces.length - 1))
+ out.print(", ");
+ }
+ out.println();
+ }
+ out.println("{");
+ int all = BindingFlags.Public | BindingFlags.DeclaredOnly// | BindingFlags.NonPublic
+ | BindingFlags.Instance | BindingFlags.Static;
+ dumpMembers(out, type.GetNestedTypes());
+ dumpMembers(out, type.GetFields(all));
+ dumpMembers(out, type.GetConstructors(all));
+ dumpMembers(out, type.GetMethods(all));
+ dumpMembers(out, type.GetProperties(all));
+ dumpMembers(out, type.GetEvents());
+ out.println("}");
+ } else {
+ dumpCustomAttributes(out, "", member);
+ out.print(MemberTypes.toString(member.MemberType()));
+ out.print(": "); out.print(member);
+ out.println();
+ }
+ } catch (Throwable e) {
+ String message = MemberTypes.toString(member.MemberType())
+ + ": " + member;
+ throw new RuntimeException(message, e);
+ }
+ }
+
+ public static void dumpCustomAttributes(PrintStream out,
+ String prefix,
+ ICustomAttributeProvider att)
+ {
+ Object[] attrs = att.GetCustomAttributes(false);
+ for (int j = 0; j < attrs.length; j++)
+ out.println(prefix + attrs[j]);
+ }
+
+ public static void dumpMembers(PrintStream out, MemberInfo[] members) {
+ for (int i = 0; i < members.length; i++) {
+ dumpMember(out, members[i]);
+ }
+ }
+
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/TableDump.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/TableDump.java
new file mode 100644
index 0000000000..0687af2f9f
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/tests/TableDump.java
@@ -0,0 +1,312 @@
+// $Id$
+
+package ch.epfl.lamp.compiler.msil.tests;
+
+import ch.epfl.lamp.compiler.msil.PEFile;
+import ch.epfl.lamp.compiler.msil.util.Table;
+import ch.epfl.lamp.compiler.msil.util.Table.*;
+
+import java.io.PrintStream;
+import java.io.FileNotFoundException;
+
+public class TableDump extends PEFile {
+
+ //##########################################################################
+
+ public TableDump(String filename) throws FileNotFoundException {
+ super(filename);
+ }
+
+ /***/
+ public void dump(PrintStream out) {
+ out.println("CLI RVA: " + CLI_RVA);
+ out.println("Optional header size: " + optHeaderSize);
+ out.println("Number of sections: " + numOfSections);
+ out.println();
+
+ for (int i = 0; i < sections.length; i++) {
+ sections[i].dump(out);
+ out.println();
+ }
+
+ out.println("MetaData Offset: 0x" + Integer.toHexString(posMetadata));
+ out.println("Number of streams: " + numOfStreams);
+
+ out.println("#~ stream"); Meta.dump(out); out.println();
+ out.println("#Strings stream"); Strings.dump(out); out.println();
+ if (US != null) {
+ out.println("#US stream"); US.dump(out); out.println();
+ }
+ out.println("#GUID stream"); GUID.dump(out); out.println();
+ out.println("#Blob stream"); Blob.dump(out); out.println();
+
+ out.println("Heap Sizes Vector = 0x0" + Integer.toHexString(heapSizes));
+ out.println();
+
+ for(int i = 0; i < Table.MAX_NUMBER; i++)
+ if(getTable(i).rows > 0) {
+ dump(out, getTable(i));
+ out.println();
+ }
+
+ }
+
+ /** Dumps the contents of this table. */
+ public void dump(PrintStream out, Table table) {
+ out.println("Table:" + " ID = 0x" + byte2hex(table.id));
+ out.println("\tname = " + table.getTableName());
+ out.println("\trows = " + table.rows);
+ //out.println("\tStart pos in file = 0x" + Long.toHexString(table.start));
+ for (int i = 1; i <= table.rows; i++)
+ dumpRow(out, table, i);
+ }
+
+ public void dumpIndex(PrintStream out, int tableSetId, int index) {
+ int tableId = Table.getTableId(tableSetId, index);
+ int row = Table.getTableIndex(tableSetId, index);
+ out.print(getTable(tableId).getTableName());
+ out.print('[');
+ out.print(getTable(tableId).isShort ? short2hex(row) : int2hex(row));
+ out.print(']');
+ }
+
+ public void dumpRow(PrintStream out, Table table, int row) {
+ table.readRow(row);
+ out.print(table.getTableName());
+ out.print("[" + short2hex(row) + "]: ");
+ dumpRow(out, table);
+ out.println();
+ }
+
+ /** Prints the current content of the fields of the class. */
+ public void dumpRow(PrintStream out, Table table) {
+ if (table instanceof ModuleDef) {
+ ModuleDef t = (ModuleDef)table;
+ out.print("Generation = 0x" + short2hex(t.Generation));
+ out.print("; Name = " + getString(t.Name));
+ //out.print("; Mvid = (" + bytes2hex(getGUID(Mvid)) + ")");
+ } else if (table instanceof TypeRef) {
+ TypeRef t = (TypeRef)table;
+ out.print("FullName = " + t.getFullName());
+ out.print("; ResolutionScope = 0x" + int2hex(t.ResolutionScope));
+ } else if (table instanceof TypeDef) {
+ TypeDef t = (TypeDef)table;
+ out.print("Flags = 0x"); out.print(int2hex(t.Flags));
+ out.print("; FullName = "); out.print(t.getFullName());
+ out.print("; Extends = ");
+ dumpIndex(out, Table._TypeDefOrRef, t.Extends);
+ out.print("; FieldList = "); out.print(t.FieldList);
+ out.print("; MethodList = "); out.print(t.MethodList);
+ } else if (table instanceof FieldTrans) {
+ FieldTrans t = (FieldTrans)table;
+ out.print("Field = "); out.print(t.Field);
+ } else if (table instanceof FieldDef) {
+ FieldDef t = (FieldDef)table;
+ out.print("Flags = 0x" + short2hex(t.Flags));
+ out.print("; Name = " + t.getName());
+ out.print("; Signature = (" +
+ bytes2hex(getBlob(t.Signature)) + ")");
+ } else if (table instanceof MethodTrans) {
+ MethodTrans t = (MethodTrans)table;
+ out.print("Method = "); out.print(t.Method);
+ } else if (table instanceof MethodDef) {
+ MethodDef t = (MethodDef)table;
+ out.print("Flags = 0x" + short2hex(t.Flags));
+ out.print("; Name = " + t.getName());
+ out.print("; ParamList = " + t.ParamList);
+ out.print("; Signature = (" +
+ bytes2hex(getBlob(t.Signature)) + ")");
+ } else if (table instanceof ParamDef) {
+ ParamDef t = (ParamDef)table;
+ out.print("Flags = 0x" + short2hex(t.Flags));
+ out.print("; Name = " + t.getName());
+ out.print("; Sequence = " + t.Sequence);
+ } else if (table instanceof InterfaceImpl) {
+ InterfaceImpl t = (InterfaceImpl)table;
+ out.print("Class = 0x" + short2hex(t.Class));// + " (ref to: ");
+ //TypeDef td = (TypeDef) getTable(TypeDef.ID);
+ //td.readRow(Class);
+ //td.dumpRow(out);
+ out.print("; Interface = 0x" + short2hex(t.Interface));
+ } else if (table instanceof MemberRef) {
+ MemberRef t = (MemberRef)table;
+ out.print("Name = " + t.getName());
+ out.print("; Signature = (" +
+ bytes2hex(getBlob(t.Signature)) + ")");
+ out.print("; Class = " + t.Class);
+ } else if (table instanceof Constant) {
+ Constant t = (Constant)table;
+ out.print("Parent = "); dumpIndex(out, Table._HasConstant, t.Parent);
+ out.print("; Type = 0x" + byte2hex(t.Type));
+ out.print("; Value = (" + bytes2hex(getBlob(t.Value)));
+ out.print("); Value = " + t.getValue());
+ } else if (table instanceof CustomAttribute) {
+ CustomAttribute t = (CustomAttribute)table;
+ //out.print("Parent = 0x" + int2hex(t.Parent));
+ out.print("Parent = ");
+ dumpIndex(out, Table._HasCustomAttribute, t.Parent);
+ //out.print("; Type = 0x" + short2hex(t.Type));
+ out.print("; Type = ");
+ dumpIndex(out, Table._CustomAttributeType, t.Type);
+ out.print("; Value = (" + bytes2hex(t.getValue()) + ")");
+ } else if (table instanceof FieldMarshal) {
+ FieldMarshal t = (FieldMarshal)table;
+ out.print("NativeType = (");
+ out.print(bytes2hex(getBlob(t.NativeType)) + ")");
+ } else if (table instanceof DeclSecurity) {
+ DeclSecurity t = (DeclSecurity)table;
+ out.print("Action = 0x" + short2hex(t.Action));
+ out.print("; PermissionSet = (" +
+ bytes2hex(getBlob(t.PermissionSet)) + ")");
+ } else if (table instanceof ClassLayout) {
+ ClassLayout t = (ClassLayout)table;
+ out.print("PackingSize = 0x" + short2hex(t.PackingSize));
+ out.print("; ClassSize = 0x" + int2hex(t.ClassSize));
+ out.print(": Parent = " + t.Parent + " (ref to: ");
+ dumpRow(out, this.TypeDef(t.Parent));
+ out.print(")");
+ } else if (table instanceof FieldLayout) {
+ FieldLayout t = (FieldLayout)table;
+ out.print("Offset = 0x" + int2hex(t.Offset));
+ out.print("; Field = (ref to: ");
+ dumpRow(out, this.FieldDef(t.Field));
+ out.print(")");
+ } else if (table instanceof StandAloneSig) {
+ StandAloneSig t = (StandAloneSig)table;
+ out.print("StandAloneSig: Signature = (" +
+ bytes2hex(getBlob(t.Signature)) + ")");
+ } else if (table instanceof EventMap) {
+ EventMap t = (EventMap)table;
+ out.print("Parent = 0x" + int2hex(t.Parent) + " (ref to: ");
+ dumpRow(out, this.TypeDef(t.Parent));
+ out.print("); EventList = 0x"); out.print(int2hex(t.EventList));
+ } else if (table instanceof EventDef) {
+ EventDef t = (EventDef)table;
+ out.print("EventFlags = 0x" + short2hex(t.EventFlags));
+ out.print("; Name = " + t.getName());
+ out.print("; EventType = 0x" + int2hex(t.EventType));
+ } else if (table instanceof PropertyMap) {
+ PropertyMap t = (PropertyMap)table;
+ out.print("Parent = " + t.Parent + " (ref to: ");
+ dumpRow(out, this.TypeDef(t.Parent));
+ out.print(")");
+ } else if (table instanceof PropertyDef) {
+ PropertyDef t = (PropertyDef)table;
+ out.print("Flags = 0x" + short2hex(t.Flags));
+ out.print("; Name = " + t.getName());
+ out.print("; Type = (" + bytes2hex(getBlob(t.Type)) + ")");
+ } else if (table instanceof MethodSemantics) {
+ MethodSemantics t = (MethodSemantics)table;
+ out.print("Semantics = 0x" + short2hex(t.Semantics));
+ out.print("; Method = 0x" + int2hex(t.Method) + " (ref to: ");
+ dumpRow(out, this.MethodDef(t.Method));
+ out.print("); Association = 0x" + int2hex(t.Association));
+ } else if (table instanceof MethodImpl) {
+ MethodImpl t = (MethodImpl)table;
+ out.print("Class = (ref to: ");
+ dumpRow(out, this.TypeDef(t.Class));
+ out.print(")");
+ } else if (table instanceof ModuleRef) {
+ ModuleRef t = (ModuleRef)table;
+ out.print("Name = " + t.getName());
+ } else if (table instanceof TypeSpec) {
+ TypeSpec t = (TypeSpec)table;
+ out.print("Signature = (" +
+ bytes2hex(getBlob(t.Signature)) + ")");
+ } else if (table instanceof ImplMap) {
+ ImplMap t = (ImplMap)table;
+ out.print("ImportName = " + getString(t.ImportName));
+ } else if (table instanceof FieldRVA) {
+ FieldRVA t = (FieldRVA)table;
+ out.print("RVA = 0x" + int2hex(t.RVA));
+ out.print("; Field = (ref to: ");
+ dumpRow(out, this.FieldDef(t.Field));
+ out.print(")");
+ } else if (table instanceof AssemblyDef) {
+ AssemblyDef t = (AssemblyDef)table;
+ out.print("Flags = 0x" + int2hex(t.Flags));
+ out.print(" ; Name = " + getString(t.Name));
+ out.print("; Culture = " + getString(t.Culture));
+ out.print(" ; Version = " + t.MajorVersion + ".");
+ out.print(t.MinorVersion + "." + t.BuildNumber);
+ out.print("." + t.RevisionNumber);
+ out.print("; HashAlgId = 0x" + int2hex(t.HashAlgId));
+ out.print("; PublicKey = (");
+ out.print(bytes2hex(getBlob(t.PublicKey)) + ")");
+ } else if (table instanceof AssemblyProcessor) {
+ AssemblyProcessor t = (AssemblyProcessor)table;
+ out.print("Processor = 0x" + int2hex(t.Processor));
+ } else if (table instanceof AssemblyOS) {
+ AssemblyOS t = (AssemblyOS)table;
+ out.print("!?!");
+ } else if (table instanceof AssemblyRef) {
+ AssemblyRef t = (AssemblyRef)table;
+ out.print("Flags = 0x" + int2hex(t.Flags));
+ out.print("; Name = " + getString(t.Name));
+ out.print("; Culture = " + getString(t.Culture));
+ out.print("; Version = " + t.MajorVersion + "." + t.MinorVersion);
+ out.print("." + t.BuildNumber + "." + t.RevisionNumber);
+ out.print("; PublicKeyOrToken = (" +
+ bytes2hex(getBlob(t.PublicKeyOrToken)) + ")");
+ out.print("; HashValue = (" +
+ bytes2hex(getBlob(t.HashValue)) + ")");
+ } else if (table instanceof AssemblyRefProcessor) {
+ AssemblyRefProcessor t = (AssemblyRefProcessor)table;
+ out.print("!?!");
+ } else if (table instanceof AssemblyRefOS) {
+ AssemblyRefOS t = (AssemblyRefOS)table;
+ out.print("!?!");
+ } else if (table instanceof FileDef) {
+ FileDef t = (FileDef)table;
+ out.print("Flags = 0x" + int2hex(t.Flags));
+ out.print("; Name = " + t.getName());
+ out.print("; HashValue = (" + bytes2hex(getBlob(t.HashValue)) +")");
+ } else if (table instanceof ExportedType) {
+ ExportedType t = (ExportedType)table;
+ out.print("FullName = " + t.getFullName());
+ } else if (table instanceof ManifestResource) {
+ ManifestResource t = (ManifestResource)table;
+ out.print("Name = " + getString(t.Name));
+ out.print("; Flags = 0x" + int2hex(t.Flags));
+ } else if (table instanceof NestedClass) {
+ NestedClass t = (NestedClass)table;
+ out.print(this.TypeDef(t.EnclosingClass).getFullName());
+ out.print("/");
+ out.print(this.TypeDef(t.NestedClass).getFullName());
+ } else
+ throw new RuntimeException("Unknown table " + table.getClass());
+ }
+
+ //##########################################################################
+
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ System.err.println("You must supply a filename!");
+ System.exit(1);
+ }
+
+ TableDump file = null;
+ try {
+ file = new TableDump(args[0]);
+ } catch (FileNotFoundException e) { e.printStackTrace(); }
+
+ if (args.length > 1) {
+ nextarg:
+ for (int i = 1; i < args.length; i++) {
+ String name = args[i];
+ for (int tableId = 0; tableId < Table.MAX_NUMBER; tableId++) {
+ Table table = file.getTable(tableId);
+ if ((table.rows > 0) && name.equals(table.getTableName())) {
+ file.dump(System.out, table);
+ System.out.println();
+ continue nextarg;
+ }
+ }
+ System.err.println("No such table: " + name);
+ }
+ } else
+ file.dump(System.out);
+ }
+
+ //##########################################################################
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/tests/Test.java b/src/msil/ch/epfl/lamp/compiler/msil/tests/Test.java
new file mode 100644
index 0000000000..d1c81f4fb5
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/tests/Test.java
@@ -0,0 +1,93 @@
+// $Id$
+
+package test;
+
+import ch.epfl.lamp.compiler.msil.*;
+import ch.epfl.lamp.compiler.msil.util.Table;
+
+import java.io.PrintStream;
+
+public class Test {
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ System.err.println("You must supply a filename!");
+ System.exit(1);
+ }
+
+ Assembly assem = Assembly.LoadFrom(args[0]);
+ Type.initMSCORLIB(assem);
+
+ //"System.Collections.ArrayList"
+ if (args.length >= 2) {
+ Type t = Type.GetType(args[1]);
+ dumpType(System.out, t);
+ } else {
+ dumpAssembly(assem);
+ }
+ }
+
+
+ public static void dumpAssembly(Assembly assem) {
+ Module[] modules = assem.GetModules();
+// System.out.println("Modules in assembly " + assem +
+// " (" + modules.length + ")");
+// for (int i = 0; i < modules.length; i++) {
+// System.out.println("\t" + modules[i]);
+// }
+
+ Type[] types = modules[0].GetTypes();
+// System.out.println("Types in assembly " + assem +
+// " (" + types.length + ")");
+ for (int i = 0; i < types.length; i++) {
+ System.out.println("#" + i + " -> " + types[i]);
+ types[i].completeType();
+ }
+ }
+
+ public static final void dumpType(PrintStream out, Type type) {
+ out.println("Type = " + type);
+ out.println("Name = " + type.Name);
+ out.println("Namespace = " + type.Namespace);
+ out.println("FullName = " + type.FullName);
+ out.println("Attributes = " + TypeAttributes.toString(type.Attributes));
+ out.println("BaseType = " + type.BaseType);
+ Type[] ifaces = type.GetInterfaces();
+ if (ifaces != null) {
+ for (int i = 0; i < ifaces.length; i++)
+ out.println("\timplements " + ifaces[i]);
+ }
+ out.println("Assembly = " + type.Assembly);
+ out.println("Module = " + type.Module);
+ out.println("DeclaringType = " + type.DeclaringType);
+ out.println("IsInterface = " + type.IsInterface);
+ out.println("IsAbstract = " + type.IsAbstract);
+
+ FieldInfo[] fields = type.GetFields(BindingFlags.Instance
+ | BindingFlags.Static
+ | BindingFlags.NonPublic);
+ out.println("\nFields (" + fields.length + "):");
+ for (int i = 0; i < fields.length; i++) {
+ out.println("\t" + fields[i]);
+ out.println("\t\tDeclaringType = " + fields[i].DeclaringType);
+ out.println("\t\tReflectedType = " + fields[i].ReflectedType);
+ }
+
+ ConstructorInfo[] constrs = type.GetConstructors();
+ out.println("\nConstructors (" + constrs.length + "):");
+ for (int i = 0; i < constrs.length; i++) {
+ out.println("\t" + constrs[i]);
+ }
+
+// MethodInfo[] methods = type.GetMethods(BindingFlags.Instance
+// | BindingFlags.Static
+// | BindingFlags.Public
+// | BindingFlags.NonPublic);
+ MethodInfo[] methods = type.GetMethods();
+ out.println("\nMethods (" + methods.length + "):");
+ for (int i = 0; i < methods.length; i++) {
+ out.println("\t" + methods[i]);
+ out.println("\t\tDeclaringType = " + methods[i].DeclaringType);
+ out.println("\t\tReflectedType = " + methods[i].ReflectedType);
+ }
+ }
+}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/PESection.java b/src/msil/ch/epfl/lamp/compiler/msil/util/PESection.java
new file mode 100644
index 0000000000..84f604af53
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/util/PESection.java
@@ -0,0 +1,58 @@
+/*
+ * System.Reflection-like API for acces to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil.util;
+
+import ch.epfl.lamp.compiler.msil.PEFile;
+
+import java.io.PrintStream;
+
+/** Describes a section from a PE/COFF file
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class PESection {
+
+ private final PEFile file;
+ private final long sectionStart;
+
+ public final String name;
+ public final int virtAddr;
+ public final int virtSize;
+ public final int realAddr;
+ public final int realSize;
+ public final int flags;
+
+ private static final byte[] buf = new byte[8];
+
+ public PESection(PEFile file) {
+ this.file = file;
+ sectionStart = file.pos();
+ file.read(buf);
+ int i;
+ for(i = 7; (i >= 0) && (0 == buf[i]); i--);
+ name = new String(buf, 0, i + 1);
+ virtSize = file.readInt();
+ virtAddr = file.readInt();
+ realSize = file.readInt();
+ realAddr = file.readInt();
+ file.skip(3 * PEFile.INT_SIZE);
+ flags = file.readInt();
+ }
+
+
+ public void dump(PrintStream out) {
+ out.println("Section name: " + name +
+ " (name.length=" + name.length() + ")");
+ out.println("Virtual Address: 0x" + PEFile.int2hex(virtAddr));
+ out.println("Virtual Size: 0x" + PEFile.int2hex(virtSize));
+ out.println("Real Address: 0x" + PEFile.int2hex(realAddr));
+ out.println("Real Size: 0x" + PEFile.int2hex(realSize));
+ out.println("Flags: 0x" + PEFile.int2hex(flags));
+ }
+
+} // class PESection
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/PEStream.java b/src/msil/ch/epfl/lamp/compiler/msil/util/PEStream.java
new file mode 100644
index 0000000000..4feb0f7b1e
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/util/PEStream.java
@@ -0,0 +1,200 @@
+/*
+ * System.Reflection-like API for acces to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil.util;
+
+import ch.epfl.lamp.compiler.msil.PEFile;
+import ch.epfl.lamp.compiler.msil.PEFile.Sig;
+
+import java.io.PrintStream;
+import java.io.IOException;
+
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * Implements support for CLI streams within a PE file.
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public final class PEStream implements Signature {
+
+ //##########################################################################
+ // Members
+
+ /** The name of the stream. */
+ public final String name;
+
+ /** The offset of the stream from the beginning of the file. */
+ public final int offset;
+
+ /** The size of the stream in bytes; shall be multiple of 4. */
+ public final int size;
+
+ private final PEFile file;
+
+ private final ByteBuffer buffer;
+
+ //##########################################################################
+
+ /** The PEStream class constructor.
+ * @param file - the PEFile to which this stream belongs
+ */
+ public PEStream(PEFile file) {
+ this.file = file;
+ offset = file.fromRVA(file.rvaMetadata + file.readInt());
+ size = file.readInt();
+ buffer = file.getBuffer(offset, size);
+
+ int i = 0;
+ byte [] _buf = new byte [16];
+ do {
+ _buf[i] = (byte) file.readByte();
+ i++;
+ } while(0 != _buf[i-1]);
+ name = new String(_buf, 0, i - 1);
+
+ file.align(PEFile.INT_SIZE, file.posMetadata);
+ //assert size % 4 == 0;
+ }
+
+ /** Move to the specified position in the stream. */
+ private void seek(int pos) {
+ try {
+ buffer.position(pos);
+ } catch (IllegalArgumentException e) {
+ System.err.println("\nSeek failed in file " + file
+ + " for position " + pos
+ + " of stream " + name + " (" + buffer + ")");
+ throw e;
+ }
+ }
+
+ /** Return a string from the specified position in the stream. */
+ public String getString(int pos) {
+ seek(pos);
+ buffer.mark();
+ int i;
+ for (i = 0; getByte() != 0; i++);
+ byte[] buf = new byte[i];
+ buffer.reset(); // go back to the marked position
+ buffer.get(buf);
+ try {
+ return new String(buf, "UTF-8");
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Read a byte from the stream. */
+ public int getByte() {
+ return (buffer.get() + 0x0100) & 0xff;
+ }
+
+ /** Return the GUID at the given position in the stream. */
+ public byte[] getGUID(int pos) {
+ seek(pos);
+ byte[] buf = new byte[32]; // 128-bit GUID
+ try {
+ buffer.get(buf);
+ } catch (Exception e) {
+ System.err.println();
+ System.err.println("PEStream.getBlob(): Exception for pos = " +
+ pos + " and buf.length = " + buf.length);
+ System.err.println("\tbuffer = " + buffer);
+ e.printStackTrace();
+ throw new RuntimeException();
+ }
+ return buf;
+ }
+
+ public int readLength() {
+ int length = getByte();
+ if ((length & 0x80) != 0) {
+ length = ((length & 0x7f) << 8) | getByte();
+ if ((length & 0x4000) != 0)
+ length = ((length & 0x3fff) << 16) | (getByte()<<8) | getByte();
+ }
+ return length;
+ }
+
+ /** Return a blob from the specified position in the stream. */
+ public byte[] getBlob(int pos) {
+ seek(pos);
+ // the length indicates the number of bytes
+ // AFTER the encoded size of the blob
+ int length = readLength();
+ byte[] buf = new byte[length];
+ buffer.get(buf);
+ return buf;
+ }
+
+ /***/
+ public Sig getSignature(int pos) {
+ seek(pos);
+ return file.newSignature(buffer);
+ }
+
+ /**
+ */
+ public Object getConstant(int type, int pos) {
+ Object val = null;
+ seek(pos);
+ int length = readLength(); // skip over the blob length field
+ switch (type) {
+ case ELEMENT_TYPE_BOOLEAN:
+ assert length == 1;
+ return buffer.get() == 0 ? Boolean.FALSE : Boolean.TRUE;
+ case ELEMENT_TYPE_CHAR:
+ assert length == 2 : "length == " + length;
+ return new Character(buffer.getChar());
+ case ELEMENT_TYPE_I1:
+ case ELEMENT_TYPE_U1:
+ assert length == 1;
+ return new Byte(buffer.get());
+ case ELEMENT_TYPE_I2:
+ case ELEMENT_TYPE_U2:
+ assert length == 2;
+ return new Short(buffer.getShort());
+ case ELEMENT_TYPE_I4:
+ case ELEMENT_TYPE_U4:
+ assert length == 4;
+ return new Integer(buffer.getInt());
+ case ELEMENT_TYPE_I8:
+ case ELEMENT_TYPE_U8:
+ assert length == 8;
+ return new Long(buffer.getLong());
+ case ELEMENT_TYPE_R4:
+ assert length == 4;
+ return new Float(buffer.getFloat());
+ case ELEMENT_TYPE_R8:
+ assert length == 8;
+ return new Double(buffer.getDouble());
+ case ELEMENT_TYPE_STRING:
+// length /= 2;
+// char[] chars = new char[length];
+// for (int i = 0; i < length; i++)
+// chars[i] = buffer.getChar();
+// val = new String(chars);
+ try {
+ return new String(getBlob(pos), "UTF-16LE");
+ } catch(java.io.UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ default: throw new RuntimeException("Illegal constant type: " + type);
+ }
+ }
+
+ public void dump(PrintStream out) {
+ out.println("Stream name: " + name + " (length " +
+ name.length() + " characters)");
+ out.println("Stream offset: 0x" + PEFile.int2hex(offset));
+ out.println("Stream size: 0x" + PEFile.int2hex(size));
+ }
+
+ //##########################################################################
+} // class PEStream
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/Signature.java b/src/msil/ch/epfl/lamp/compiler/msil/util/Signature.java
new file mode 100644
index 0000000000..ded2dd64a7
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/util/Signature.java
@@ -0,0 +1,119 @@
+/*
+ * System.Reflection-like API for acces to .NET assemblies (DLL & EXE)
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil.util;
+
+import ch.epfl.lamp.compiler.msil.Type;
+
+/**
+ * Signatures
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public interface Signature {
+
+ //##########################################################################
+
+ /** Marks end of a list. */
+ public static final int ELEMENT_TYPE_END = 0x00;
+ /** void */
+ public static final int ELEMENT_TYPE_VOID = 0x01;
+ /** boolean */
+ public static final int ELEMENT_TYPE_BOOLEAN = 0x02;
+ /** char */
+ public static final int ELEMENT_TYPE_CHAR = 0x03;
+ /** signed byte */
+ public static final int ELEMENT_TYPE_I1 = 0x04;
+ /** byte */
+ public static final int ELEMENT_TYPE_U1 = 0x05;
+ /** short */
+ public static final int ELEMENT_TYPE_I2 = 0x06;
+ /** unsigned short */
+ public static final int ELEMENT_TYPE_U2 = 0x07;
+ /** int */
+ public static final int ELEMENT_TYPE_I4 = 0x08;
+ /** unsigned int */
+ public static final int ELEMENT_TYPE_U4 = 0x09;
+ /** long */
+ public static final int ELEMENT_TYPE_I8 = 0x0a;
+ /** unsigned long */
+ public static final int ELEMENT_TYPE_U8 = 0x0b;
+ /** float */
+ public static final int ELEMENT_TYPE_R4 = 0x0c;
+ /** double */
+ public static final int ELEMENT_TYPE_R8 = 0x0d;
+ /** string */
+ public static final int ELEMENT_TYPE_STRING = 0x0e;
+ /** Followed by <type> token. */
+ public static final int ELEMENT_TYPE_PTR = 0x0f;
+ /** Followed by <type> token. */
+ public static final int ELEMENT_TYPE_BYREF = 0x10;
+ /** Followed by <type> token */
+ public static final int ELEMENT_TYPE_VALUETYPE = 0x11;
+ /** Followed by <type> token */
+ public static final int ELEMENT_TYPE_CLASS = 0x12;
+ /** <type> <rank> <boundsCount> <bound1> ... <loCount> <lo1> ... */
+ public static final int ELEMENT_TYPE_ARRAY = 0x14;
+ /***/
+ public static final int ELEMENT_TYPE_TYPEDBYREF = 0x16;
+ /** System.IntPtr */
+ public static final int ELEMENT_TYPE_I = 0x18;
+ /** System.UIntPtr */
+ public static final int ELEMENT_TYPE_U = 0x19;
+ /** Followed by full method signature. */
+ public static final int ELEMENT_TYPE_FNPTR = 0x1b;
+ /** System.Object. */
+ public static final int ELEMENT_TYPE_OBJECT = 0x1c;
+ /** Single-dim array with 0 lower bound. */
+ public static final int ELEMENT_TYPE_SZARRAY = 0x1d;
+ /** Required modifier : followed by a TypeDef or TypeRef token. */
+ public static final int ELEMENT_TYPE_CMOD_REQD = 0x1f;
+ /** Optional modifier : followed by a TypeDef or TypeRef token. */
+ public static final int ELEMENT_TYPE_CMOD_OPT = 0x20;
+ /** Implemented within the CLI. */
+ public static final int ELEMENT_TYPE_INTERNAL = 0x21;
+ /** Or'd with following element types. */
+ public static final int ELEMENT_TYPE_MODIFIER = 0x40;
+ /** Sentinel for varargs method signature. */
+ public static final int ELEMENT_TYPE_SENTINEL = 0x41;
+ /**Denotes a local variable that points at a pinned object. */
+ public static final int ELEMENT_TYPE_PINNED = 0x45;
+
+ //##########################################################################
+ // signature designators
+
+ public static final int HASTHIS = 0x20;
+ public static final int EXPLICITTHIS = 0x40;
+ public static final int DEFAULT = 0x00;
+ public static final int VARARG = 0x05;
+ public static final int SENTINEL = 0x41;
+ public static final int C = 0x01;
+ public static final int STDCALL = 0x02;
+ public static final int THISCALL = 0x03;
+ public static final int FASTCALL = 0x04;
+ public static final int FIELD = 0x06;
+ public static final int PROPERTY = 0x08;
+ public static final int LOCAL_SIG = 0x07;
+
+ //##########################################################################
+ // extra IDs used in the serialization format of named arguments
+ // to custom attributes. Reverse-engineered from compiled C# example
+
+ /** What follows is a string with the full name of the type. */
+ public static final int X_ELEMENT_TYPE_TYPE = 0x50;
+
+ /** What follows is a string with the full name of the enumeration type*/
+ public static final int X_ELEMENT_TYPE_ENUM = 0x55;
+
+ /** The named argument specifies a field. */
+ public static final int X_ELEMENT_KIND_FIELD = 0x53;
+
+ /** The named argument specifies a property. */
+ public static final int X_ELEMENT_KIND_PROPERTY = 0x54;
+
+ //##########################################################################
+} // interface Signature
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/Table.java b/src/msil/ch/epfl/lamp/compiler/msil/util/Table.java
new file mode 100644
index 0000000000..a4860c369f
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/util/Table.java
@@ -0,0 +1,1600 @@
+/*
+ * System.Reflection-like API for acces to .NET Assemblies
+ */
+
+// $Id$
+
+package ch.epfl.lamp.compiler.msil.util;
+
+import ch.epfl.lamp.compiler.msil.PEFile;
+import ch.epfl.lamp.compiler.msil.PEFile.Sig;
+
+import java.io.PrintStream;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+
+/**
+ * Represents a table in a .NET assembly
+ *
+ * @author Nikolay Mihaylov
+ * @version 1.0
+ */
+public abstract class Table {
+
+ //##########################################################################
+
+ public static final int MAX_NUMBER = 64;
+
+ public static final long VALID_TABLES_MASK = 0x03ff3fb7ff57L;
+
+ //##########################################################################
+ // fields and methods for handling predefined sets of tables
+
+ public static final int TABLE_SET_LENGTH = 12;
+
+ public static final int _TypeDefOrRef = 0;
+ public static final int _HasConstant = 1;
+ public static final int _HasCustomAttribute = 2;
+ public static final int _HasFieldMarshal = 3;
+ public static final int _HasDeclSecurity = 4;
+ public static final int _MemberRefParent = 5;
+ public static final int _HasSemantics = 6;
+ public static final int _MethodDefOrRef = 7;
+ public static final int _MemberForwarded = 8;
+ public static final int _Implementation = 9;
+ public static final int _CustomAttributeType = 10;
+ public static final int _ResolutionScope = 11;
+
+
+ public static final int[][] TableSet = new int[TABLE_SET_LENGTH][];
+ static {
+ TableSet[_TypeDefOrRef] =
+ new int[] {TypeDef.ID, TypeRef.ID, TypeSpec.ID};
+ TableSet[_HasConstant] =
+ new int[] {FieldDef.ID, ParamDef.ID, PropertyDef.ID};
+ TableSet[_HasCustomAttribute] =
+ new int[] {MethodDef.ID, FieldDef.ID, TypeRef.ID, TypeDef.ID,
+ ParamDef.ID, InterfaceImpl.ID, MemberRef.ID, ModuleDef.ID,
+ -1, PropertyDef.ID, EventDef.ID, -1, ModuleRef.ID,
+ TypeSpec.ID, AssemblyDef.ID, AssemblyRef.ID,
+ FileDef.ID, ExportedType.ID, ManifestResource.ID};
+ TableSet[_HasFieldMarshal] =
+ new int[] {FieldDef.ID, ParamDef.ID};
+ TableSet[_HasDeclSecurity] =
+ new int[] {TypeDef.ID, MethodDef.ID, AssemblyDef.ID};
+ TableSet[_MemberRefParent] =
+ new int[] {-1, TypeRef.ID, ModuleRef.ID, MethodDef.ID, TypeSpec.ID};
+ TableSet[_HasSemantics] =
+ new int[] {EventDef.ID, PropertyDef.ID};
+ TableSet[_MethodDefOrRef] =
+ new int[] {MethodDef.ID, MemberRef.ID};
+ TableSet[_MemberForwarded] =
+ new int[] {FieldDef.ID, MethodDef.ID};
+ TableSet[_Implementation] =
+ new int[] {FileDef.ID, AssemblyRef.ID, ExportedType.ID};
+ TableSet[_CustomAttributeType] =
+ new int[] {-1, -1, MethodDef.ID, MemberRef.ID, -1};
+ TableSet[_ResolutionScope] =
+ new int[] {ModuleDef.ID, ModuleRef.ID, AssemblyRef.ID, TypeRef.ID};
+ }
+
+ public static final int[] NoBits =
+ new int[] {2, 2, 5, 1, 2, 3, 1, 1, 1, 2, 3, 2};
+
+ public static int getMask(int tableSetId) {
+ return (1 << NoBits[tableSetId]) - 1;
+ }
+
+ public static int getTableId(int tableSet, int index) {
+ return TableSet[tableSet][index & getMask(tableSet)];
+ }
+
+ public static int getTableIndex(int tableSet, int index) {
+ return index >> NoBits[tableSet];
+ }
+
+ public static int encodeIndex(int index, int tableSetId, int tableId) {
+ int[] tableSet = TableSet[tableSetId];
+ for (int i = 0; i < tableSet.length; i++) {
+ if (tableSet[i] == tableId)
+ return (index << NoBits[tableSetId]) | i;
+ }
+ throw new RuntimeException("Cannot find table #" + tableId +
+ " in table set #" + tableSetId);
+ }
+
+ //##########################################################################
+
+ private static final String [] tableName = {
+ "Module", "TypeRef", "TypeDef", " FieldTrans",
+ "Field", "MethodTrans", "Method", "",
+ "Param", "InterfaceImpl", "MemberRef", "Constant",
+ "CustomAttribute", "FieldMarshal", "DeclSecurity","ClassLayout",
+ "FieldLayout", "StandAloneSig", "EventMap", "",
+ "Event", "PropertyMap", "", "Property",
+ "MethodSemantics", "MethodImpl", "ModuleRef", "TypeSpec",
+ "ImplMap", "FieldRVA", "", "",
+ "Assembly", "AssemblyProcessor","AssemblyOS", "AssemblyRef",
+ "AssemblyRefProcessor","AssemblyRefOS", "File", "ExportedType",
+ "ManifestResource", "NestedClass", "", "",
+ "", "", "", "",//0x28-0x2f
+ "", "", "", "",
+ "", "", "", "",//0x30-0x37
+ "", "", "", "",
+ "", "", "", "" //0x37-0x3f
+ };
+
+ /** Creates a table with the given id and number of rows.
+ */
+ public static Table newTable(PEFile file, int id, int rows) {
+ Table table = null;
+ switch(id) {
+ case ModuleDef.ID: table = new ModuleDef(file, rows); break;
+ case TypeRef.ID: table = new TypeRef(file, rows); break;
+ case TypeDef.ID: table = new TypeDef(file, rows); break;
+ case FieldTrans.ID: table = new FieldTrans(file, rows); break;
+ case FieldDef.ID: table = new FieldDef(file, rows); break;
+ case MethodTrans.ID: table = new MethodTrans(file, rows); break;
+ case MethodDef.ID: table = new MethodDef(file, rows); break;
+ case ParamDef.ID: table = new ParamDef(file, rows); break;
+ case InterfaceImpl.ID: table = new InterfaceImpl(file, rows); break;
+ case MemberRef.ID: table = new MemberRef(file, rows); break;
+ case Constant.ID: table = new Constant(file, rows); break;
+ case CustomAttribute.ID: table = new CustomAttribute(file, rows); break;
+ case FieldMarshal.ID: table = new FieldMarshal(file, rows); break;
+ case DeclSecurity.ID: table = new DeclSecurity(file, rows); break;
+ case ClassLayout.ID: table = new ClassLayout(file, rows); break;
+ case FieldLayout.ID: table = new FieldLayout(file, rows); break;
+ case StandAloneSig.ID: table = new StandAloneSig(file, rows); break;
+ case EventMap.ID: table = new EventMap(file, rows); break;
+ case EventDef.ID: table = new EventDef(file, rows); break;
+ case PropertyMap.ID: table = new PropertyMap(file, rows); break;
+ case PropertyDef.ID: table = new PropertyDef(file, rows); break;
+ case MethodSemantics.ID: table = new MethodSemantics(file, rows); break;
+ case MethodImpl.ID: table = new MethodImpl(file, rows); break;
+ case ModuleRef.ID: table = new ModuleRef(file, rows); break;
+ case TypeSpec.ID: table = new TypeSpec(file, rows); break;
+ case ImplMap.ID: table = new ImplMap(file, rows); break;
+ case FieldRVA.ID: table = new FieldRVA(file, rows); break;
+ case AssemblyDef.ID: table = new AssemblyDef(file, rows); break;
+ case AssemblyProcessor.ID: table = new AssemblyProcessor(file, rows); break;
+ case AssemblyOS.ID: table = new AssemblyOS(file, rows); break;
+ case AssemblyRef.ID: table = new AssemblyRef(file, rows); break;
+ case AssemblyRefProcessor.ID:
+ table = new AssemblyRefProcessor(file, rows); break;
+ case AssemblyRefOS.ID: table = new AssemblyRefOS(file, rows); break;
+ case FileDef.ID: table = new FileDef(file, rows); break;
+ case ExportedType.ID: table = new ExportedType(file, rows); break;
+ case ManifestResource.ID: table = new ManifestResource(file, rows); break;
+ case NestedClass.ID: table = new NestedClass(file, rows); break;
+ default:
+ table = new Empty(id);
+ }
+// System.out.println("created table " + table.getName() + " with "
+// + table.rows + " rows");
+ return table;
+ }
+
+
+ //##########################################################################
+ // public fields
+
+ /** Number of rows in the table. */
+ public final int rows;
+
+ /** Table ID as specified in Partition II. */
+ public final int id;
+
+ /** The file to which the table belongs. */
+ protected final PEFile file;
+
+ /** Memory mapped buffer wrapping the table. */
+ protected ByteBuffer buffer;
+
+ /**
+ * specified wheter a new memory-mapped byte buffer should be created
+ * for this table.
+ */
+ protected boolean newMapping = false;
+
+ /** Tells wheter the table is indexed by 2-byte (short) integer
+ * or by 4-byte integer. */
+ public final boolean isShort;
+
+ private int rowSize = -1;
+
+ // the starting position of the table relative to the beginning of the file
+ private long start = -1;
+
+ // the number of the row who can be accessed via the fields of the table
+ private int currentRow = 0;
+
+ //##########################################################################
+
+ protected Table(PEFile file, int id, int rows) {
+ this.file = file;
+ this.id = id;
+ this.rows = rows;//file.readInt();
+ this.isShort = rows < (1 << 16);
+// assert ((1L << id) & VALID_TABLES_MASK) != 0
+// : "Table does not have a vaid ID: " + byte2hex(id);
+ }
+
+ /**
+ * Additional table initialization.
+ * @return the starting position of the next table in the stream.
+ */
+ public final long init(long start) {
+ if (rows < 1)
+ return start;
+ if (this.start == -1)
+ this.start = start;
+ else throw new RuntimeException
+ ("Cannot re-initialize table \'" + getTableName() + "\'");
+ rowSize = getRowSize();
+ int size = rows * rowSize();
+ buffer = this.newMapping ? file.mapBuffer(start, size)
+ : file.getBuffer(start, size);
+ return start + size;
+ }
+
+
+ public final String getTableName() {
+ return 0 <= id && id < MAX_NUMBER ? tableName[id] : "<NoTable>";
+ }
+
+ /**
+ * @return the size of the row in bytes
+ */
+ public final int rowSize() {
+ return rowSize;
+ }
+
+ /**
+ * if the underlying buffer is memory-mapped, load its contents into memory
+ */
+ public void load() {
+ if (buffer instanceof MappedByteBuffer)
+ ((MappedByteBuffer)buffer).load();
+ }
+
+ /***/
+ public final int readByte() {
+ return (buffer.get() + 0x100) & 0xff;
+ }
+
+ /***/
+ public final int readShort() {
+ return (buffer.getShort() + 0x10000) & 0xffff;
+ }
+
+ /***/
+ public final int readInt() {
+ return buffer.getInt();
+ }
+
+ /***/
+ public final int readStringIndex() {
+ return file.StringIsShort ? readShort() : readInt();
+ }
+
+ /***/
+ public final int readBlobIndex() {
+ return file.BlobIsShort ? readShort() : readInt();
+ }
+
+ /***/
+ public final int readGUIDIndex() {
+ return file.GUIDIsShort ? readShort() : readInt();
+ }
+
+ /***/
+ public final int readTableIndex(int tableId) {
+ return file.getTable(tableId).isShort ? readShort() : readInt();
+ }
+
+ /***/
+ public final int readTableSetIndex(int tableSetId) {
+ return file.indexSize[tableSetId] == 2 ? readShort() : readInt();
+ }
+
+ /** Read the specified row and populate the fields of the instance. */
+ public final void readRow(int row) {
+ seekRow(row);
+ int lastSeek = buffer.position();
+ populateFields();
+ int rowSizeRead = (int) (buffer.position() - lastSeek);
+ if (rowSizeRead != rowSize())
+ throw new RuntimeException("Table ID=0x" + PEFile.byte2hex(id) +
+ ": read row size = " + rowSizeRead +
+ "; expected row size = " + rowSize());
+ currentRow = row;
+ }
+
+ /** Seeks in the file the position of the specified row. */
+ protected final void seekRow(int row) {
+ assert row > 0 && row <= rows
+ : "Index " + row + " is not within the table with #rows = " + rows;
+ buffer.position((row - 1)* rowSize());
+ }
+
+ public final int currentRow() { return currentRow; }
+
+ public final void nextRow() { readRow(currentRow() + 1); }
+
+ //##########################################################################
+ // abstract members
+
+ /** Assigns values to the fields of the class. */
+ protected abstract void populateFields();
+
+ /** Returns the size of a row in bytes. */
+ protected abstract int getRowSize();
+
+ //##########################################################################
+ // a table with 0 rows
+
+ private static final class Empty extends Table {
+ public Empty(int id) {
+ super(null, id, 0);
+ }
+ protected int getRowSize() { return 0; }
+ protected void populateFields() {
+ throw new RuntimeException("Table 0x" + PEFile.byte2hex(id));
+ }
+ }
+
+ //##########################################################################
+ // table Module; ID=0x00; p115, 21.27
+
+ public static final class ModuleDef extends Table {
+ public static final int ID = 0x00;
+
+ /** 2-byte value; reserved - shall be 0. */
+ public int Generation;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into #GUID; used to distinguish between
+ * two version of the same module. */
+ public int Mvid;
+
+ /** Index into #GUID; reserved - shall be 0. */
+ public int EncId;
+
+ /** Index into #GUID; reseved - shall be 0. */
+ public int EncBaseId;
+
+ public ModuleDef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Generation = readShort();
+ Name = readStringIndex();
+ Mvid = readGUIDIndex();
+ EncId = readGUIDIndex();
+ EncBaseId = readGUIDIndex();
+ }
+
+ protected int getRowSize() {
+ return 2 + file.getStringIndexSize() + 3*file.getGUIDIndexSize();
+ }
+
+ public String getName() {
+ return file.getString(Name);
+ }
+
+ } // class ModuleDef
+
+ //##########################################################################
+ // table TypeRef; ID=0x01; p125, 21.35
+
+ public static final class TypeRef extends Table {
+ public static final int ID = 0x1;
+
+ /** A ResolutionScope coded index. */
+ public int ResolutionScope;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into #String. */
+ public int Namespace;
+
+ public TypeRef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ ResolutionScope = readTableSetIndex(_ResolutionScope);
+ Name = readStringIndex();
+ Namespace = readStringIndex();
+ }
+
+ protected int getRowSize() {
+ return file.getTableSetIndexSize(_ResolutionScope) +
+ 2 * file.getStringIndexSize();
+ }
+
+ public String getFullName() {
+ String namespace = file.getString(Namespace);
+ return namespace.length() == 0 ? file.getString(Name)
+ : namespace + "." + file.getString(Name);
+ }
+
+ } // class TypeRef
+
+ //##########################################################################
+ // table TypeDef; ID=0x02; p120, 21.34
+
+ public static final class TypeDef extends Table {
+ public static final int ID = 0x02;
+
+ /** 4-byte bitmask of type TypeAttributes (22.1.14). */
+ public int Flags;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into #String. */
+ public int Namespace;
+
+ /** TypeDefOrRef coded index. */
+ public int Extends;
+
+ /** Index into Field table.
+ */
+ public int FieldList;
+
+ /** Index into Method table. */
+ public int MethodList;
+
+
+ public TypeDef(PEFile file, int rows) {
+ super(file, ID, rows);
+ this.newMapping = true;
+ }
+
+ public String getFullName() {
+ String namespace = file.getString(Namespace);
+ return namespace.length() == 0 ? file.getString(Name)
+ : namespace + "." + file.getString(Name);
+ }
+
+ protected void populateFields() {
+ Flags = readInt();
+ Name = readStringIndex();
+ Namespace = readStringIndex();
+ Extends = readTableSetIndex(_TypeDefOrRef);
+ FieldList = readTableIndex(FieldDef.ID);
+ MethodList = readTableIndex(MethodDef.ID);
+ }
+
+ protected int getRowSize() {
+ return 4 + 2*file.getStringIndexSize() +
+ file.getTableSetIndexSize(_TypeDefOrRef) +
+ file.getTableIndexSize(FieldDef.ID) +
+ file.getTableIndexSize(MethodDef.ID);
+ }
+
+ } // class TypeDef
+
+ //##########################################################################
+ // Table FieldTrans; ID=0x03; undocumented
+
+ /**
+ * Undocumented table. Appears to be used for translating the Field entry
+ * in the TypeDef(0x02) table into the real entry in the Fields(0x06) table
+ */
+ public static final class FieldTrans extends Table {
+ public static final int ID = 0x03;
+
+ public int Field;
+
+ public FieldTrans(PEFile file, int rows) {
+ super(file, ID, rows);
+ newMapping = true;
+ }
+
+ protected void populateFields() {
+ Field = readTableIndex(FieldDef.ID);
+ }
+
+ protected int getRowSize() {
+ return file.getTableIndexSize(FieldDef.ID);
+ }
+
+ }
+
+ //##########################################################################
+ // table Field; ID=0x04; p102, 21.15
+
+ public static final class FieldDef extends Table {
+ public static final int ID = 0x04;
+
+ /** 2-byte bitmask of type FieldAttributes (22.1.5). */
+ public int Flags;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into #Blob. */
+ public int Signature;
+
+ public FieldDef(PEFile file, int rows) {
+ super(file, ID, rows);
+ newMapping = true;
+ }
+
+ protected void populateFields() {
+ Flags = readShort();
+ Name = readStringIndex();
+ Signature = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return 2 + file.getStringIndexSize() + file.getBlobIndexSize();
+ }
+
+ public String getName() { return file.getString(Name); }
+
+ public Sig getSignature() { return file.getSignature(Signature); }
+
+ } //class FieldDef
+
+ //##########################################################################
+ // Table MethodTrans; ID=0x05; undocumented
+
+ /**
+ * Undocumented table. Appears to be used for translating the Method entry
+ * in the TypeDef(0x02) table into the real entry in the Methods(0x06) table
+ */
+ public static final class MethodTrans extends Table {
+ public static final int ID = 0x05;
+
+ public int Method;
+
+ public MethodTrans(PEFile file, int rows) {
+ super(file, ID, rows);
+ newMapping = true;
+ }
+
+ protected void populateFields() {
+ Method = readTableIndex(FieldDef.ID);
+ }
+
+ protected int getRowSize() {
+ return file.getTableIndexSize(MethodDef.ID);
+ }
+
+ }
+
+ //##########################################################################
+ // table MethodDef; ID=0x06; p110, 21.24
+
+ public static final class MethodDef extends Table {
+ public static final int ID = 0x06;
+
+ /** 4-byte constant. */
+ public int RVA;
+
+ /** 2-byte bitmask of type MethodImplAttributes (22.1.10). */
+ public int ImplFlags;
+
+ /** 2-byte bitmask of type MethodAttributes (22.1.9). */
+ public int Flags;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into #Blob. */
+ public int Signature;
+
+ /** Index into Param Table. */
+ public int ParamList;
+
+ public MethodDef(PEFile file, int rows) {
+ super(file, ID, rows);
+ newMapping = true;
+ }
+
+ protected void populateFields() {
+ RVA = readInt();
+ ImplFlags = readShort();
+ Flags = readShort();
+ Name = readStringIndex();
+ Signature = readBlobIndex();
+ ParamList = readTableIndex(ParamDef.ID);
+ }
+
+ protected int getRowSize() {
+ return 8 + file.getStringIndexSize() + file.getBlobIndexSize() +
+ file.getTableIndexSize(ParamDef.ID);
+ }
+
+ public String getName() { return file.getString(Name); }
+
+ public Sig getSignature() { return file.getSignature(Signature); }
+ } // class Method
+
+ //##########################################################################
+ // table Param; ID=0x08; p116, 21.30
+
+ public static final class ParamDef extends Table {
+ public static final int ID = 0x08;
+
+ /** 2-byte bitmask of type ParamAttributes (22.1.12). */
+ public int Flags;
+
+ /** 2-byte constant. */
+ public int Sequence;
+
+ /** Index into #String. */
+ public int Name;
+
+ public ParamDef(PEFile file, int rows) {
+ super(file, ID, rows);
+ newMapping = true;
+ }
+
+ protected void populateFields() {
+ Flags = readShort();
+ Sequence = readShort();
+ Name = readStringIndex();
+ }
+
+ protected int getRowSize() { return 4 + file.getStringIndexSize(); }
+
+ public String getName() { return file.getString(Name); }
+
+ } // class Param
+
+ //##########################################################################
+ // table InterfaceImpl, ID=0x09; p107, 21.21
+
+ public static final class InterfaceImpl extends Table {
+ public static final int ID = 0x09;
+
+ /** Index into TypeDef table. */
+ public int Class;
+
+ /** Index into TypeDefOrRef table set. */
+ public int Interface;
+
+ public InterfaceImpl(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Class = readTableIndex(TypeDef.ID);
+ Interface = readTableSetIndex(_TypeDefOrRef);
+ }
+
+ protected int getRowSize() {
+ return file.getTableIndexSize(TypeDef.ID) +
+ file.getTableSetIndexSize(_TypeDefOrRef);
+ }
+
+ /** finds the index of the first entry
+ * @param targetIndex - index in the TypeDef table - the type to look for
+ * @return the index of the first interface for the given type;
+ * 0 if the type doesn't implement any interfaces
+ */
+
+ // binary search implementation
+// public int findType(int targetIndex) {
+// int l = 1, h = rows;
+// int classIndex;
+// while (l <= h) {
+// int mid = (l + h) / 2;
+// seekRow(mid);
+// classIndex = readTableIndex(TypeDef.ID);
+// if (targetIndex <= classIndex) h = mid - 1;
+// else l = mid + 1;
+// }
+// return (targetIndex == classIndex) ? h : 0;
+// }
+
+ //linear search implementation
+ public int findType(int targetIndex) {
+ for (int i = 1; i <= rows; i++) {
+ seekRow(i);
+ if (targetIndex == readTableIndex(TypeDef.ID))
+ return i;
+ }
+ return 0;
+ }
+
+ } // class InterfaceImpl
+
+ //##########################################################################
+ // table MemberRef; ID=0x0a; p109, 21.23
+
+ public static final class MemberRef extends Table {
+ public static final int ID = 0x0a;
+
+ /** Index into MemberRefParent table set. */
+ public int Class;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into #Blob. */
+ public int Signature;
+
+ public MemberRef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Class = readTableSetIndex(_MemberRefParent);
+ Name = readStringIndex();
+ Signature = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return file.getTableSetIndexSize(_MemberRefParent) +
+ file.getStringIndexSize() + file.getBlobIndexSize();
+ }
+
+ public String getName() {
+ return file.getString(Name);
+ }
+
+ public Sig getSignature() {
+ return file.getSignature(Signature);
+ }
+
+ } // class MemberRef
+
+ //##########################################################################
+ // table Constant; ID=0x0b; p95, 21.9
+
+ public static final class Constant extends Table {
+ public static final int ID = 0x0b;
+
+ /** 1-byte constant followed by 1-byte padding 0 (see 22.1.15). */
+ public int Type;
+
+ /** Index into HasConst table set. */
+ public int Parent;
+
+ /** Index into #Blob. */
+ public int Value;
+
+ public Constant(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Type = readShort();
+ Parent = readTableSetIndex(_HasConstant);
+ Value = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return 2 + file.getTableSetIndexSize(_HasConstant) +
+ file.getBlobIndexSize();
+ }
+
+ public Object getValue() {
+ if (Type == Signature.ELEMENT_TYPE_CLASS)
+ return null;
+ return file.Blob.getConstant(Type, Value);
+ }
+
+
+ } // class Constant
+
+ //##########################################################################
+ // table CustomAttribute; ID=0x0c; p95, 21.10
+
+ public static final class CustomAttribute extends Table {
+ public static final int ID = 0x0c;
+
+ /** Index into any metadata table, except the CustomAttribute itself;
+ * more precisely - index into HasCustomAttribute table set.
+ */
+ public int Parent;
+
+ /** Index into the CustomAttributeType table set. */
+ public int Type;
+
+ /** Index into #Blob. */
+ public int Value;
+
+ public CustomAttribute(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Parent = readTableSetIndex(_HasCustomAttribute);
+ Type = readTableSetIndex(_CustomAttributeType);
+ Value = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return file.getTableSetIndexSize(_HasCustomAttribute) +
+ file.getTableSetIndexSize(_CustomAttributeType) +
+ file.getBlobIndexSize();
+ }
+
+ public byte[] getValue() {
+ return Value == 0 ? null : file.getBlob(Value);
+ }
+ } // class CustomAttribute
+
+ //##########################################################################
+ // table FieldMarshal; ID=0x0d; p105, 21.17
+
+ public static final class FieldMarshal extends Table {
+ public static final int ID = 0x0d;
+
+ /** Index into HasFieldMarshal table set. */
+ public int Parent;
+
+ /** Index into #Blob. */
+ public int NativeType;
+
+ public FieldMarshal(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Parent = readTableSetIndex(_HasFieldMarshal);
+ NativeType = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return file.getTableSetIndexSize(_HasFieldMarshal) +
+ file.getBlobIndexSize();
+ }
+
+ } // class FieldMarshal
+
+ //##########################################################################
+ // table DeclSecurity; ID=0x0e; p97, 21.11
+
+ public static final class DeclSecurity extends Table {
+ public static final int ID = 0x0e;
+
+ /** 2-byte value. */
+ public int Action;
+
+ /** Index into HasDeclSecurity table set. */
+ public int Parent;
+
+ /** Index into #Blob. */
+ public int PermissionSet;
+
+ public DeclSecurity(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Action = readShort();
+ Parent = readTableSetIndex(_HasDeclSecurity);
+ PermissionSet = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return 2 + file.getTableSetIndexSize(_HasDeclSecurity) +
+ file.getBlobIndexSize();
+ }
+
+ } // class DeclSecurity
+
+ //##########################################################################
+ // table ClassLayout; ID=0x0f, p92, 21.8
+
+ public static final class ClassLayout extends Table {
+ public static final int ID = 0x0f;
+
+ /** 2-byte constant. */
+ public int PackingSize;
+
+ /** 4-byte constant. */
+ public int ClassSize;
+
+ /** Index into TypeDef table. */
+ public int Parent;
+
+ public ClassLayout(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ PackingSize = readShort();
+ ClassSize = readInt();
+ Parent = readTableIndex(TypeDef.ID);
+ }
+
+ protected int getRowSize() {
+ return 6 + file.getTableIndexSize(TypeDef.ID);
+ }
+
+ } // class ClassLayout
+
+ //##########################################################################
+ // table FieldLayout; ID=0x10; p104, 21.16
+
+ public static final class FieldLayout extends Table {
+ public static final int ID = 0x10;
+
+ /** 4-byte constant. */
+ public int Offset;
+
+ /** Index into the Field table. */
+ public int Field;
+
+ public FieldLayout(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Offset = readInt();
+ Field = readTableIndex(FieldDef.ID);
+ }
+
+ protected int getRowSize() {
+ return 4 + file.getTableIndexSize(FieldDef.ID);
+ }
+
+ } // class FieldLayout
+
+ //##########################################################################
+ // table StandAloneSig; ID=0x11; p119, 21.33
+
+ public static final class StandAloneSig extends Table {
+ public static final int ID = 0x11;
+
+ /** Index into #Blob. */
+ public int Signature;
+
+ public StandAloneSig(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Signature = readBlobIndex();
+ }
+
+ protected int getRowSize() { return file.getBlobIndexSize(); }
+
+ } // class StandAloneSig
+
+ //##########################################################################
+ // table EventMap; ID=0x12; p99, 21.12
+
+ public static final class EventMap extends Table {
+ public static final int ID = 0x12;
+
+ /** Index into the TypeDef table. */
+ public int Parent;
+
+ /** Index into the Event table. */
+ public int EventList;
+
+ public EventMap(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Parent = readTableIndex(TypeDef.ID);
+ EventList = readTableIndex(EventDef.ID);
+ }
+
+ protected int getRowSize() {
+ return file.getTableIndexSize(TypeDef.ID) +
+ file.getTableIndexSize(EventDef.ID);
+ }
+
+ } // class EventMap
+
+ //##########################################################################
+ // table Event; ID=0x14; p99, 21.13
+
+ public static final class EventDef extends Table {
+ public static final int ID = 0x14;
+
+ /** 2-byte bitmask of type EventAttribute (22.1.4). */
+ public int EventFlags;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into TypeDefOrRef table set. [This corresponds to the Type
+ * of the event; it is not the Type that owns the event]
+ */
+ public int EventType;
+
+ public EventDef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ EventFlags = readShort();
+ Name = readStringIndex();
+ EventType = readTableSetIndex(_TypeDefOrRef);
+ }
+
+ protected int getRowSize() {
+ return 2 + file.getStringIndexSize() +
+ file.getTableSetIndexSize(_TypeDefOrRef);
+ }
+
+ public String getName() { return file.getString(Name); }
+
+ } // class EventDef
+
+ //##########################################################################
+ // table PropertyMap; ID=0x15; p119, 21.32
+
+ public static final class PropertyMap extends Table {
+ public static final int ID = 0x15;
+
+ /** Index into the TypeDef table. */
+ public int Parent;
+
+ /** Index into the Property table. */
+ public int PropertyList;
+
+ public PropertyMap(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Parent = readTableIndex(TypeDef.ID);
+ PropertyList = readTableIndex(PropertyDef.ID);
+ }
+
+ protected int getRowSize() {
+ return file.getTableIndexSize(TypeDef.ID) +
+ file.getTableIndexSize(PropertyDef.ID);
+ }
+
+ } // class PropertyMap
+
+ //##########################################################################
+ // table Property; ID=0x17; p117, 21.31
+
+ public static final class PropertyDef extends Table {
+ public static final int ID = 0x17;
+
+ /** 2-byte bitmask of type PropertyAttributes (22.1.13). */
+ public int Flags;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into #Blob. (Indexes the signature in the #Blob) */
+ public int Type;
+
+ public PropertyDef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Flags = readShort();
+ Name = readStringIndex();
+ Type = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return 2 + file.getStringIndexSize() +
+ file.getBlobIndexSize();
+ }
+
+ public String getName() { return file.getString(Name); }
+
+ public Sig getSignature() { return file.getSignature(Type); }
+
+ } // class PropertyDef
+
+ //##########################################################################
+ // table MethodSemantics; ID=0x18; p114, 21.26
+
+ public static final class MethodSemantics extends Table {
+ public static final int ID = 0x18;
+
+ /** 2-byte bitmaks of type MethodSemanticsAttribute (22.1.11). */
+ public int Semantics;
+
+ /** Index into the Method table. */
+ public int Method;
+
+ /** Index into Event or Property table (HasSemantics table set). */
+ public int Association;
+
+ public MethodSemantics(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Semantics = readShort();
+ Method = readTableIndex(MethodDef.ID);
+ Association = readTableSetIndex(_HasSemantics);
+ }
+
+ protected int getRowSize() {
+ return 2 + file.getTableIndexSize(MethodDef.ID) +
+ file.getTableSetIndexSize(_HasSemantics);
+ }
+
+ public boolean isGetter() { return (Semantics & Getter) != 0; }
+ public boolean isSetter() { return (Semantics & Setter) != 0; }
+ public boolean isOther() { return (Semantics & Other) != 0; }
+ public boolean isAddOn() { return (Semantics & AddOn) != 0; }
+ public boolean isRemoveOn() { return (Semantics & RemoveOn) != 0; }
+ public boolean isFire() { return (Semantics & Fire) != 0; }
+
+ private static final short Setter = (short)0x0001;
+ private static final short Getter = (short)0x0002;
+ private static final short Other = (short)0x0004;
+ private static final short AddOn = (short)0x0008;
+ private static final short RemoveOn = (short)0x0010;
+ private static final short Fire = (short)0x0020;
+
+ } // class MethodSemantics
+
+
+ //##########################################################################
+ // table MethodImpl; ID=0x19; p113, 21.25
+
+ public static final class MethodImpl extends Table {
+ public static final int ID = 0x19;
+
+ /** Index into the TypeDef table. */
+ public int Class;
+
+ /** Index into MethodDefOrRef table set. */
+ public int MethodBody;
+
+ /** Index into MethodDefOrRef table set. */
+ public int MethodDeclaration;
+
+ public MethodImpl(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Class = readTableIndex(TypeDef.ID);
+ MethodBody = readTableSetIndex(_MethodDefOrRef);
+ MethodDeclaration = readTableSetIndex(_MethodDefOrRef);
+ }
+
+ protected int getRowSize() {
+ return file.getTableIndexSize(TypeDef.ID) +
+ 2 * file.getTableSetIndexSize(_MethodDefOrRef);
+ }
+
+ } // class MethodImpl
+
+ //##########################################################################
+ // table ModuleRef; ID=0x1a; p116, 21.28
+
+ public static final class ModuleRef extends Table {
+ public static final int ID = 0x1a;
+
+ /** Index into #String. */
+ public int Name;
+
+ public ModuleRef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Name = readStringIndex();
+ }
+
+ protected int getRowSize() { return file.getStringIndexSize(); }
+
+ public String getName() { return file.getString(Name); }
+
+ } // class ModuleRef
+
+ //##########################################################################
+ // table TypeSpec; ID=0x1b; p126, 21.36
+
+ public static final class TypeSpec extends Table {
+ public static final int ID = 0x1b;
+
+ /** Index into #Blob, where the blob is formatted
+ * as specified in 22.2.15
+ */
+ public int Signature;
+
+ public TypeSpec(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Signature = readBlobIndex();
+ }
+
+ protected int getRowSize() { return file.getBlobIndexSize(); }
+
+ public Sig getSignature() { return file.getSignature(Signature); }
+ } // class TypeSpec
+
+ //##########################################################################
+ // table ImplMap; ID=0x1c; p107, 21.20
+
+ public static final class ImplMap extends Table {
+ public static final int ID = 0x1c;
+
+ /** 2-byte bitmask of type PInvokeAttributes (22.1.7). */
+ public int MappingFlags;
+
+ /** Index into MemberForwarded table set. */
+ public int MemberForwarded;
+
+ /** Index into #String. */
+ public int ImportName;
+
+ /** Index into the ModuleRef table. */
+ public int ImportScope;
+
+ public ImplMap(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ MappingFlags = readShort();
+ MemberForwarded = readTableSetIndex(_MemberForwarded);
+ ImportName = readStringIndex();
+ ImportScope = readTableIndex(ModuleRef.ID);
+ }
+
+ protected int getRowSize() {
+ return 2 + file.getTableSetIndexSize(_MemberForwarded) +
+ file.getStringIndexSize() +
+ file.getTableIndexSize(ModuleRef.ID);
+ }
+
+ } // class ImplMap
+
+ //##########################################################################
+ // table FieldRVA; ID=0x1d; p106, 21.18
+
+ public static final class FieldRVA extends Table {
+ public static final int ID = 0x1d;
+
+ /** 4-byte constant. */
+ public int RVA;
+
+ /** Index into the Field table. */
+ public int Field;
+
+ public FieldRVA(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ RVA = readInt();
+ Field = readTableIndex(Table.FieldDef.ID);
+ }
+
+ protected int getRowSize() {
+ return 4 + file.getTableIndexSize(FieldDef.ID);
+ }
+
+ }
+
+ //##########################################################################
+ // table Assembly; ID=0x20; p90, 21.2
+
+ public static final class AssemblyDef extends Table {
+ public static final int ID = 0x20;
+
+ /** 4-byte constatnt of type AssemblyHashAlgorithm, clause 22.1.1 */
+ public int HashAlgId;
+
+ /** 2-byte constant */
+ public int MajorVersion;
+
+ /** 2-byte constant */
+ public int MinorVersion;
+
+ /** 2-byte constant */
+ public int BuildNumber;
+
+ /** 2-byte constant */
+ public int RevisionNumber;
+
+ /** 4-byte constant */
+ public int Flags;
+
+ /** index into #Blob */
+ public int PublicKey;
+
+ /** index into #String */
+ public int Name;
+
+ /** index into #String */
+ public int Culture;
+
+ public AssemblyDef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ HashAlgId = readInt();
+ MajorVersion = readShort();
+ MinorVersion = readShort();
+ BuildNumber = readShort();
+ RevisionNumber = readShort();
+ Flags = readInt();
+ PublicKey = readBlobIndex();
+ Name = readStringIndex();
+ Culture = readStringIndex();
+ }
+
+ protected int getRowSize() {
+ return 16 + file.getBlobIndexSize() + 2*file.getStringIndexSize();
+ }
+
+ } // class AssemblyDef
+
+ //##########################################################################
+ // table AssemblyProcessor; ID=0x21; p91, 21.4
+
+ public static final class AssemblyProcessor extends Table {
+ public static final int ID = 0x21;
+
+ /** 4-byte constant. */
+ public int Processor;
+
+ public AssemblyProcessor(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Processor = readInt();
+ }
+
+ protected int getRowSize() { return 4; }
+
+ }
+
+ //##########################################################################
+ // table AssemblyOS; ID = 0x22; p90, 21.3
+
+ public static final class AssemblyOS extends Table {
+ public static final int ID = 0x22;
+
+ /** 4-byte constant. */
+ public int OSPlatformID;
+
+ /** 4-byte constant. */
+ public int OSMajorVersion;
+
+ /** 4-byte constant. */
+ public int OSMinorVersion;
+
+ public AssemblyOS(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ OSPlatformID = readInt();
+ OSMajorVersion = readInt();
+ OSMinorVersion = readInt();
+ }
+
+ protected int getRowSize() { return 12; }
+
+ }
+
+ //##########################################################################
+ // table AssemblyRef; ID = 0x23; pp91, 21.5
+
+ public static final class AssemblyRef extends Table {
+ public static final int ID = 0x23;
+
+ /** 2-byte constant. */
+ public int MajorVersion;
+
+ /** 2-byte constant. */
+ public int MinorVersion;
+
+ /** 2-byte constant. */
+ public int BuildNumber;
+
+ /** 2-byte constant. */
+ public int RevisionNumber;
+
+ /** 4-byte bitmask of type AssemblyFlags (22.1.2). */
+ public int Flags;
+
+ /** index into #Blob. */
+ public int PublicKeyOrToken;
+
+ /** index into #String. */
+ public int Name;
+
+ /** index into #String. */
+ public int Culture;
+
+ /** index into #Blob. */
+ public int HashValue;
+
+ public AssemblyRef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ MajorVersion = readShort();
+ MinorVersion = readShort();
+ BuildNumber = readShort();
+ RevisionNumber = readShort();
+ Flags = readInt();
+ PublicKeyOrToken = readBlobIndex();
+ Name = readStringIndex();
+ Culture = readStringIndex();
+ HashValue = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return 12 + 2*file.getBlobIndexSize() + 2*file.getStringIndexSize();
+ }
+
+ public String getName() { return file.getString(Name); }
+ }
+
+ //##########################################################################
+ // table AssemblyRefProcessor; ID=0x24; p92, 21.7
+
+ public static final class AssemblyRefProcessor extends Table {
+ public static final int ID = 0x24;
+
+ /** 4-byte constant. */
+ public int Processor;
+
+ /** Index into the AssemblyRef table. */
+ public int AssemblyRef;
+
+ public AssemblyRefProcessor(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Processor = readInt();
+ AssemblyRef = readTableIndex(Table.AssemblyRef.ID);
+ }
+
+ protected int getRowSize() {
+ return 4 + file.getTableIndexSize(Table.AssemblyRef.ID);
+ }
+
+ } // class AssemblyRefProcessor
+
+ //##########################################################################
+ // table AssemblyRefOS; ID=0x25; p92, 21.6
+
+ public static final class AssemblyRefOS extends Table {
+ public static final int ID = 0x25;
+
+ /** 4-byte constant. */
+ public int OSPlatformId;
+
+ /** 4-byte constant. */
+ public int OSMajorVersion;
+
+ /** 4-byte constant. */
+ public int OSMinorVersion;
+
+ /** Index into the AssemblyRef table. */
+ public int AssemblyRef;
+
+ public AssemblyRefOS(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ OSPlatformId = readInt();
+ OSMajorVersion = readInt();
+ OSMinorVersion = readInt();
+ AssemblyRef = readTableIndex(Table.AssemblyRef.ID);
+ }
+
+ protected int getRowSize() {
+ return 12 + file.getTableIndexSize(Table.AssemblyRef.ID);
+ }
+
+ } // class AssemblyRefOS
+
+ //##########################################################################
+ // table File; ID=0x26; p106, 21.19
+
+ public static final class FileDef extends Table {
+ public static final int ID = 0x26;
+
+ /** 4-byte bitmask of type FileAttributes (22.1.6). */
+ public int Flags;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into #Blob. */
+ public int HashValue;
+
+ public FileDef(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Flags = readInt();
+ Name = readStringIndex();
+ HashValue = readBlobIndex();
+ }
+
+ protected int getRowSize() {
+ return 4 + file.getStringIndexSize() + file.getBlobIndexSize();
+ }
+
+ public String getName() {
+ return file.getString(Name);
+ }
+
+ } // class FileDef
+
+ //##########################################################################
+ // table ExportedType; ID=0x27; p100, 21.14
+
+ public static final class ExportedType extends Table {
+ public static final int ID = 0x27;
+
+ /** 4-byte bitmask of type TypeAttribute (22.1.6). */
+ public int Flags;
+
+ /** 4-byte index into a TypeDef table of
+ * another module in this assembly.
+ */
+ public int TypeDefId;
+
+ /** Index into #String. */
+ public int TypeName;
+
+ /** Index into #Stream. */
+ public int TypeNamespace;
+
+ /** Index into one of two tables as follows:
+ * - 'File' table, where that entry says which module
+ * in the current assembly holds the TypeDef
+ * - 'ExportedType' table, where that entry is
+ * the enclosing Type of the current nested Type
+ */
+ public int Implementation;
+
+ public ExportedType(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Flags = readInt();
+ TypeDefId = readInt();
+ TypeName = readStringIndex();
+ TypeNamespace = readStringIndex();
+ Implementation = readTableSetIndex(_Implementation);
+ }
+
+ protected int getRowSize() {
+ return 8 + 2*file.getStringIndexSize() +
+ file.getTableSetIndexSize(_Implementation);
+ }
+
+ public String getFullName() {
+ String namespace = file.getString(TypeNamespace);
+ return namespace.length() == 0 ? file.getString(TypeName)
+ : namespace + "." + file.getString(TypeName);
+ }
+
+ } // class ExportedType
+
+ //##########################################################################
+ // table ManifestResource; ID=0x28; p108, 21.22
+
+ public static final class ManifestResource extends Table {
+ public static final int ID = 0x28;
+
+ /** 4-byte constant. */
+ public int Offset;
+
+ /** 4-byte bitmask of type ManifestResourceAttributes (22.1.8). */
+ public int Flags;
+
+ /** Index into #String. */
+ public int Name;
+
+ /** Index into the Implementation table set. */
+ public int Implementation;
+
+ public ManifestResource(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ Offset = readInt();
+ Flags = readInt();
+ Name = readStringIndex();
+ Implementation = readTableSetIndex(_Implementation);
+ }
+
+ protected int getRowSize() {
+ return 8 + file.getStringIndexSize() +
+ file.getTableSetIndexSize(_Implementation);
+ }
+
+ } // class ManifestResource
+
+ //##########################################################################
+ // table NestedClass; ID=0x29; p116, 21.29
+
+ public static final class NestedClass extends Table {
+ public static final int ID = 0x29;
+
+ /** Index into the TypeDef table. */
+ public int NestedClass;
+
+ /** Index into the TypeDef table. */
+ public int EnclosingClass;
+
+ public NestedClass(PEFile file, int rows) { super(file, ID, rows); }
+
+ protected void populateFields() {
+ NestedClass = readTableIndex(TypeDef.ID);
+ EnclosingClass = readTableIndex(TypeDef.ID);
+ }
+
+ protected int getRowSize() {
+ return 2 * file.getTableIndexSize(TypeDef.ID);
+ }
+
+ } // class NestedClass
+
+ //##########################################################################
+
+} // class Table
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/VJSAssembly.java b/src/msil/ch/epfl/lamp/compiler/msil/util/VJSAssembly.java
new file mode 100644
index 0000000000..8722aafa27
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/util/VJSAssembly.java
@@ -0,0 +1,294 @@
+// $Id: VJSAssembly.java 125 2005-04-05 09:16:50Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.util;
+
+import java.lang.reflect.*;
+import java.util.HashMap;
+
+import ch.epfl.lamp.compiler.msil.*;
+
+/**
+ * Represents the Microsoft vjslib.dll assembly.
+ */
+public final class VJSAssembly extends Assembly {
+
+ private VJSAssembly(AssemblyName an) { super(an); }
+
+ protected void loadModules() {
+ VJSLIB_DLL.init();
+ addModule("vjslib.dll", VJSLIB_DLL);
+ }
+
+ public static final Assembly VJSLIB;
+ private static final VJSModule VJSLIB_DLL;
+
+ static {
+ AssemblyName an = new AssemblyName();
+ an.Name = "vjslib";
+ an.Version = new Version(1, 0, 3300, 0);
+ an.SetPublicKeyToken(new byte [] {(byte)0xB0, 0x3F, 0x5F, 0x7F,
+ 0x11, (byte)0xD5, 0x0A, 0x3A});
+ VJSLIB = new VJSAssembly(an);
+ VJSLIB_DLL = new VJSModule(VJSLIB);
+ }
+
+
+ //##########################################################################
+
+ private static final class VJSModule extends Module {
+
+ VJSModule(Assembly vjslib) {
+ super("vjslib", "vjslib.dll", "vjslib.dll", vjslib);
+ }
+
+ void init() {
+ addType("void", Type.GetType("System.Void"));
+ addType("boolean", Type.GetType("System.Boolean"));
+ addType("char", Type.GetType("System.Char"));
+ addType("float", Type.GetType("System.Single"));
+ addType("double", Type.GetType("System.Double"));
+ addType("byte", Type.GetType("System.SByte"));
+ addType("short", Type.GetType("System.Int16"));
+ addType("int", Type.GetType("System.Int32"));
+ addType("long", Type.GetType("System.Int64"));
+ addType("java.lang.Object", Type.GetType("System.Object"));
+ addType("java.lang.String", Type.GetType("System.String"));
+ }
+
+ public Type[] GetTypes() {
+ throw new RuntimeException("Operation not supported!");
+ }
+
+ public Type GetType(String name) {
+ // look it up in the typesMap
+ Type type = super.GetType(name);
+ if (type != null)
+ return type;
+ Class clazz = null;
+ try {
+ clazz = Class.forName(name);
+ } catch (ClassNotFoundException e) {}
+ return getType(clazz);
+ }
+
+ Type getType(Class clazz) {
+ if (clazz == null) return null;
+ Type type = null;
+ if (clazz.isArray()) {
+ Type elemType = getType(clazz.getComponentType());
+ type = super.GetType(elemType.FullName + "[]");
+ if (type != null)
+ return type;
+ type = Type.mkArray(elemType, 1);
+ } else {
+ type = super.GetType(clazz.getName());
+ if (type != null)
+ return type;
+ type = new JavaType(clazz);
+ }
+ return addType(type);
+ }
+
+ Type[] getTypes(Class [] classes) {
+ if (classes.length == 0) return Type.EmptyTypes;
+ Type [] types = new Type[classes.length];
+ for (int i = 0; i < classes.length; i++)
+ types[i] = getType(classes[i]);
+ return types;
+ }
+
+ } // class VJSModule
+
+ //##########################################################################
+
+ private static final class JavaType extends Type {
+
+ //######################################################################
+
+ private final Class clazz;
+
+ JavaType(Class clazz, int attrs, String name,
+ Type baseType, Type[] interfaces, Type declType)
+ {
+ super(VJSLIB_DLL, attrs, name, baseType, interfaces, declType, 0);
+ this.clazz = clazz;
+ }
+
+ JavaType(Class clazz, String name) {
+ super(VJSLIB_DLL,
+ translateTypeAttrs(clazz.getModifiers()),
+ name,
+ VJSLIB_DLL.getType(clazz.getSuperclass()),
+ null,
+ VJSLIB_DLL.getType(clazz.getDeclaringClass()),
+ 0);
+ this.clazz = clazz;
+ }
+
+ JavaType(Class clazz) {
+ this(clazz, clazz.getName());
+ }
+
+ //######################################################################
+ // lazy JavaType member loaders
+
+ protected void loadInterfaces() {
+ this.interfaces = VJSLIB_DLL.getTypes(clazz.getInterfaces());
+ }
+
+ protected void loadNestedTypes() {
+ Class [] nested = clazz.getDeclaredClasses();
+ this.nestedTypes = new Type[nested.length];
+ for (int i = 0; i < nested.length; i++) {
+ String name = nested[i].getName();
+ name = name.substring(name.lastIndexOf('$') + 1);
+ nestedTypes[i] = new JavaType(nested[i], name);
+ }
+ }
+
+ protected void loadFields() {
+ Field [] jfields = clazz.getDeclaredFields();
+ FieldInfo[] fields = new FieldInfo[jfields.length];
+ for (int i = 0; i < jfields.length; i++)
+ fields[i] = new JavaFieldInfo(jfields[i]);
+ this.fields = fields;
+ }
+
+ protected void loadMethods() {
+ Constructor[] jconstrs = clazz.getDeclaredConstructors();
+ this.constructors = new ConstructorInfo[jconstrs.length];
+ for (int i = 0; i < jconstrs.length; i++)
+ this.constructors[i] = new JavaConstructorInfo(jconstrs[i]);
+
+ Method[] jmethods = clazz.getDeclaredMethods();
+ this.methods = new MethodInfo[jmethods.length];
+ for (int i = 0; i < jmethods.length; i++)
+ this.methods[i] = JavaMethodInfo.getMethod(jmethods[i]);
+ }
+
+ //######################################################################
+ // type resolution methods
+
+
+ static int translateTypeAttrs(int mods) {
+ int attr = 0;
+
+ if (Modifier.isInterface(mods))
+ attr |= TypeAttributes.Interface;
+ else
+ attr |= TypeAttributes.Class;
+
+ if (Modifier.isAbstract(mods))
+ attr |= TypeAttributes.Abstract;
+
+ if (Modifier.isFinal(mods))
+ attr |= TypeAttributes.Sealed;
+
+ if (Modifier.isPublic(mods))
+ attr |= TypeAttributes.Public;
+ else
+ attr |= TypeAttributes.NotPublic;
+
+ return attr;
+ }
+
+ //######################################################################
+ } // class JavaType
+
+ //##########################################################################
+
+ private static final class JavaFieldInfo extends FieldInfo {
+ JavaFieldInfo(Field field) {
+ super(field.getName(),
+ VJSLIB_DLL.getType(field.getDeclaringClass()),
+ translateFieldAttrs(field.getModifiers()),
+ VJSLIB_DLL.getType(field.getType()));
+ }
+
+ //translate java modifiers into corresponding .NET Field attributes
+ static short translateFieldAttrs(int mods) {
+ short attr = 0;
+
+ if (Modifier.isFinal(mods))
+ attr |= FieldAttributes.InitOnly;
+
+ if (Modifier.isPublic(mods))
+ attr |= FieldAttributes.Public;
+ else if (Modifier.isProtected(mods))
+ attr |= FieldAttributes.FamORAssem;
+ else if (Modifier.isPrivate(mods))
+ attr |= FieldAttributes.Private;
+
+ if (Modifier.isStatic(mods))
+ attr |= FieldAttributes.Static;
+
+ return attr;
+ }
+
+ } // class JavaFieldInfo
+
+ //##########################################################################
+
+ private static final class JavaConstructorInfo extends ConstructorInfo {
+ JavaConstructorInfo(Constructor constr) {
+ super(VJSLIB_DLL.getType(constr.getDeclaringClass()),
+ JavaMethodInfo.translateMethodAttrs(constr.getModifiers()),
+ VJSLIB_DLL.getTypes(constr.getParameterTypes()));
+ }
+ }
+
+ //##########################################################################
+
+ private static final class JavaMethodInfo extends MethodInfo {
+
+ JavaMethodInfo(String name, Type declType, int attrs,
+ Type returnType, Type[] paramTypes) {
+ super(name, declType, declType, attrs, returnType, paramTypes);
+ }
+
+ static MethodInfo getMethod(Method method) {
+ String name = method.getName();
+ if (name.equals("toString"))
+ name = "ToString";
+ else if(name.equals("equals"))
+ name = "Equals";
+ else if (name.equals("hashCode"))
+ name = "GetHashCode";
+ return new JavaMethodInfo
+ (name, VJSLIB_DLL.getType(method.getDeclaringClass()),
+ translateMethodAttrs(method.getModifiers()),
+ VJSLIB_DLL.getType(method.getReturnType()),
+ VJSLIB_DLL.getTypes(method.getParameterTypes()));
+ }
+
+ static short translateMethodAttrs(int mods) {
+ short attr = 0;
+
+ if (Modifier.isAbstract(mods))
+ attr |= MethodAttributes.Abstract;
+
+ if (Modifier.isFinal(mods))
+ attr |= MethodAttributes.Final;
+
+ if (Modifier.isPublic(mods))
+ attr |= MethodAttributes.Public;
+ else if (Modifier.isProtected(mods))
+ attr |= MethodAttributes.FamORAssem;
+ else if (Modifier.isPrivate(mods))
+ attr |= MethodAttributes.Private;
+
+ if (Modifier.isStatic(mods))
+ attr |= MethodAttributes.Static;
+ else
+ attr |= MethodAttributes.Virtual;
+
+ //if (Modifier.isSynchronized(mods))
+ // attr |= MethodAttributes.Synchronized;
+
+ return attr;
+ }
+ } // class JavaMethodInfo
+
+ //##########################################################################
+
+} // class VJSAssembly
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/util/VJSAssembly.java2 b/src/msil/ch/epfl/lamp/compiler/msil/util/VJSAssembly.java2
new file mode 100644
index 0000000000..ada30ca7c9
--- /dev/null
+++ b/src/msil/ch/epfl/lamp/compiler/msil/util/VJSAssembly.java2
@@ -0,0 +1,294 @@
+// $Id: VJSAssembly.java 145 2005-05-06 07:55:25Z mihaylov $
+
+package ch.epfl.lamp.compiler.msil.util;
+
+import java.lang.reflect.*;
+import java.util.HashMap;
+
+import ch.epfl.lamp.compiler.msil.*;
+
+/**
+ * Represents the Microsoft vjslib.dll assembly.
+ */
+public final class VJSAssembly extends Assembly {
+
+ private VJSAssembly(AssemblyName an) { super(an); }
+
+ protected void loadModules() {
+ VJSLIB_DLL.init();
+ addModule("vjslib.dll", VJSLIB_DLL);
+ }
+
+ public static final Assembly VJSLIB;
+ private static final VJSModule VJSLIB_DLL;
+
+ static {
+ AssemblyName an = new AssemblyName();
+ an.Name = "vjslib";
+ an.Version = new Version(1, 0, 3300, 0);
+ an.SetPublicKeyToken(new byte [] {(byte)0xB0, 0x3F, 0x5F, 0x7F,
+ 0x11, (byte)0xD5, 0x0A, 0x3A});
+ VJSLIB = new VJSAssembly(an);
+ VJSLIB_DLL = new VJSModule(VJSLIB);
+ }
+
+
+ //##########################################################################
+
+ private static final class VJSModule extends Module {
+
+ VJSModule(Assembly vjslib) {
+ super("vjslib", "vjslib.dll", "vjslib.dll", vjslib);
+ }
+
+ void init() {
+ addType("void", Type.GetType("System.Void"));
+ addType("boolean", Type.GetType("System.Boolean"));
+ addType("char", Type.GetType("System.Char"));
+ addType("float", Type.GetType("System.Single"));
+ addType("double", Type.GetType("System.Double"));
+ addType("byte", Type.GetType("System.SByte"));
+ addType("short", Type.GetType("System.Int16"));
+ addType("int", Type.GetType("System.Int32"));
+ addType("long", Type.GetType("System.Int64"));
+ addType("java.lang.Object", Type.GetType("System.Object"));
+ addType("java.lang.String", Type.GetType("System.String"));
+ }
+
+ public Type[] GetTypes() {
+ throw new RuntimeException("Operation not supported!");
+ }
+
+ public Type GetType(String name) {
+ // look it up in the typesMap
+ Type type = super.GetType(name);
+ if (type != null)
+ return type;
+ Class clazz = null;
+ try {
+ clazz = Class.forName(name);
+ } catch (ClassNotFoundException e) {}
+ return getType(clazz);
+ }
+
+ Type getType(Class clazz) {
+ if (clazz == null) return null;
+ Type type = null;
+ if (clazz.isArray()) {
+ Type elemType = getType(clazz.getComponentType());
+ type = super.GetType(elemType.FullName + "[]");
+ if (type != null)
+ return type;
+ type = Type.mkArray(elemType, 1);
+ } else {
+ type = super.GetType(clazz.getName());
+ if (type != null)
+ return type;
+ type = new JavaType(clazz);
+ }
+ return addType(type);
+ }
+
+ Type[] getTypes(Class [] classes) {
+ if (classes.length == 0) return Type.EmptyTypes;
+ Type [] types = new Type[classes.length];
+ for (int i = 0; i < classes.length; i++)
+ types[i] = getType(classes[i]);
+ return types;
+ }
+
+ } // class VJSModule
+
+ //##########################################################################
+
+ private static final class JavaType extends Type {
+
+ //######################################################################
+
+ private final Class clazz;
+
+ JavaType(Class clazz, int attrs, String name,
+ Type baseType, Type[] interfaces, Type declType)
+ {
+ super(VJSLIB_DLL, attrs, name, baseType, interfaces, declType, 0);
+ this.clazz = clazz;
+ }
+
+ JavaType(Class clazz, String name) {
+ super(VJSLIB_DLL,
+ translateTypeAttrs(clazz.getModifiers()),
+ name,
+ VJSLIB_DLL.getType(clazz.getSuperclass()),
+ null,
+ VJSLIB_DLL.getType(clazz.getDeclaringClass()),
+ 0);
+ this.clazz = clazz;
+ }
+
+ JavaType(Class clazz) {
+ this(clazz, clazz.getName());
+ }
+
+ //######################################################################
+ // lazy JavaType member loaders
+
+ protected void loadInterfaces() {
+ this.interfaces = VJSLIB_DLL.getTypes(clazz.getInterfaces());
+ }
+
+ protected void loadNestedTypes() {
+ Class [] nested = clazz.getDeclaredClasses();
+ this.nestedTypes = new Type[nested.length];
+ for (int i = 0; i < nested.length; i++) {
+ String name = nested[i].getName();
+ name = name.substring(name.lastIndexOf('$') + 1);
+ nestedTypes[i] = new JavaType(nested[i], name);
+ }
+ }
+
+ protected void loadFields() {
+ Field [] jfields = clazz.getDeclaredFields();
+ FieldInfo[] fields = new FieldInfo[jfields.length];
+ for (int i = 0; i < jfields.length; i++)
+ fields[i] = new JavaFieldInfo(jfields[i]);
+ this.fields = fields;
+ }
+
+ protected void loadMethods() {
+ Constructor[] jconstrs = clazz.getDeclaredConstructors();
+ this.constructors = new ConstructorInfo[jconstrs.length];
+ for (int i = 0; i < jconstrs.length; i++)
+ this.constructors[i] = new JavaConstructorInfo(jconstrs[i]);
+
+ Method[] jmethods = clazz.getDeclaredMethods();
+ this.methods = new MethodInfo[jmethods.length];
+ for (int i = 0; i < jmethods.length; i++)
+ this.methods[i] = JavaMethodInfo.getMethod(jmethods[i]);
+ }
+
+ //######################################################################
+ // type resolution methods
+
+
+ static int translateTypeAttrs(int mods) {
+ int attr = 0;
+
+ if (Modifier.isInterface(mods))
+ attr |= TypeAttributes.Interface;
+ else
+ attr |= TypeAttributes.Class;
+
+ if (Modifier.isAbstract(mods))
+ attr |= TypeAttributes.Abstract;
+
+ if (Modifier.isFinal(mods))
+ attr |= TypeAttributes.Sealed;
+
+ if (Modifier.isPublic(mods))
+ attr |= TypeAttributes.Public;
+ else
+ attr |= TypeAttributes.NotPublic;
+
+ return attr;
+ }
+
+ //######################################################################
+ } // class JavaType
+
+ //##########################################################################
+
+ private static final class JavaFieldInfo extends FieldInfo {
+ JavaFieldInfo(Field field) {
+ super(field.getName(),
+ VJSLIB_DLL.getType(field.getDeclaringClass()),
+ translateFieldAttrs(field.getModifiers()),
+ VJSLIB_DLL.getType(field.getType()));
+ }
+
+ //translate java modifiers into corresponding .NET Field attributes
+ static short translateFieldAttrs(int mods) {
+ short attr = 0;
+
+ if (Modifier.isFinal(mods))
+ attr |= FieldAttributes.InitOnly;
+
+ if (Modifier.isPublic(mods))
+ attr |= FieldAttributes.Public;
+ else if (Modifier.isProtected(mods))
+ attr |= FieldAttributes.FamORAssem;
+ else if (Modifier.isPrivate(mods))
+ attr |= FieldAttributes.Private;
+
+ if (Modifier.isStatic(mods))
+ attr |= FieldAttributes.Static;
+
+ return attr;
+ }
+
+ } // class JavaFieldInfo
+
+ //##########################################################################
+
+ private static final class JavaConstructorInfo extends ConstructorInfo {
+ JavaConstructorInfo(Constructor constr) {
+ super(VJSLIB_DLL.getType(constr.getDeclaringClass()),
+ JavaMethodInfo.translateMethodAttrs(constr.getModifiers()),
+ VJSLIB_DLL.getTypes(constr.getParameterTypes()));
+ }
+ }
+
+ //##########################################################################
+
+ private static final class JavaMethodInfo extends MethodInfo {
+
+ JavaMethodInfo(String name, Type declType, int attrs,
+ Type returnType, Type[] paramTypes) {
+ super(name, declType, declType, attrs, returnType, paramTypes);
+ }
+
+ static MethodInfo getMethod(Method method) {
+ String name = method.getName();
+ if (name.equals("toString"))
+ name = "ToString";
+ else if(name.equals("equals"))
+ name = "Equals";
+ else if (name.equals("hashCode"))
+ name = "GetHashCode";
+ return new JavaMethodInfo
+ (name, VJSLIB_DLL.getType(method.getDeclaringClass()),
+ translateMethodAttrs(method.getModifiers()),
+ VJSLIB_DLL.getType(method.getReturnType()),
+ VJSLIB_DLL.getTypes(method.getParameterTypes()));
+ }
+
+ static short translateMethodAttrs(int mods) {
+ short attr = 0;
+
+ if (Modifier.isAbstract(mods))
+ attr |= MethodAttributes.Abstract;
+
+ if (Modifier.isFinal(mods))
+ attr |= MethodAttributes.Final;
+
+ if (Modifier.isPublic(mods))
+ attr |= MethodAttributes.Public;
+ else if (Modifier.isProtected(mods))
+ attr |= MethodAttributes.FamORAssem;
+ else if (Modifier.isPrivate(mods))
+ attr |= MethodAttributes.Private;
+
+ if (Modifier.isStatic(mods))
+ attr |= MethodAttributes.Static;
+ else
+ attr |= MethodAttributes.Virtual;
+
+ //if (Modifier.isSynchronized(mods))
+ // attr |= MethodAttributes.Synchronized;
+
+ return attr;
+ }
+ } // class JavaMethodInfo
+
+ //##########################################################################
+
+} // class VJSAssembly