1824 lines
38 KiB
C#
1824 lines
38 KiB
C#
/*
|
|
Copyright (C) 2002-2010 Jeroen Frijters
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
Jeroen Frijters
|
|
jeroen@frijters.net
|
|
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Xml.Serialization;
|
|
using IKVM.Reflection;
|
|
using IKVM.Reflection.Emit;
|
|
using Type = IKVM.Reflection.Type;
|
|
using System.Diagnostics;
|
|
using IKVM.Attributes;
|
|
using IKVM.Internal;
|
|
|
|
namespace IKVM.Internal.MapXml
|
|
{
|
|
sealed class CodeGenContext
|
|
{
|
|
private ClassLoaderWrapper classLoader;
|
|
private readonly Dictionary<string, object> h = new Dictionary<string, object>();
|
|
|
|
internal CodeGenContext(ClassLoaderWrapper classLoader)
|
|
{
|
|
this.classLoader = classLoader;
|
|
}
|
|
|
|
internal object this[string key]
|
|
{
|
|
get
|
|
{
|
|
object val;
|
|
h.TryGetValue(key, out val);
|
|
return val;
|
|
}
|
|
set { h[key] = value; }
|
|
}
|
|
|
|
internal ClassLoaderWrapper ClassLoader { get { return classLoader; } }
|
|
}
|
|
|
|
public abstract class Instruction
|
|
{
|
|
private int lineNumber = Root.LineNumber;
|
|
|
|
internal int LineNumber
|
|
{
|
|
get
|
|
{
|
|
return lineNumber;
|
|
}
|
|
}
|
|
|
|
internal abstract void Generate(CodeGenContext context, CodeEmitter ilgen);
|
|
|
|
public override string ToString()
|
|
{
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
sb.Append('<');
|
|
object[] attr = GetType().GetCustomAttributes(typeof(XmlTypeAttribute), false);
|
|
if (attr.Length == 1)
|
|
{
|
|
sb.Append(((XmlTypeAttribute)attr[0]).TypeName);
|
|
}
|
|
else
|
|
{
|
|
sb.Append(GetType().Name);
|
|
}
|
|
foreach (System.Reflection.FieldInfo field in GetType().GetFields())
|
|
{
|
|
if (!field.IsStatic)
|
|
{
|
|
object value = field.GetValue(this);
|
|
if (value != null)
|
|
{
|
|
attr = field.GetCustomAttributes(typeof(XmlAttributeAttribute), false);
|
|
if (attr.Length == 1)
|
|
{
|
|
sb.AppendFormat(" {0}=\"{1}\"", ((XmlAttributeAttribute)attr[0]).AttributeName, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sb.Append(" />");
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
|
|
[XmlType("ldstr")]
|
|
public sealed class Ldstr : Instruction
|
|
{
|
|
[XmlAttribute("value")]
|
|
public string Value;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldstr, Value);
|
|
}
|
|
}
|
|
|
|
[XmlType("ldnull")]
|
|
public sealed class Ldnull : Simple
|
|
{
|
|
public Ldnull() : base(OpCodes.Ldnull)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("call")]
|
|
public class Call : Instruction
|
|
{
|
|
public Call() : this(OpCodes.Call)
|
|
{
|
|
}
|
|
|
|
internal Call(OpCode opcode)
|
|
{
|
|
this.opcode = opcode;
|
|
}
|
|
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("type")]
|
|
public string type;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
private OpCode opcode;
|
|
|
|
internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
Debug.Assert(Name != null);
|
|
if(Name == ".ctor")
|
|
{
|
|
Debug.Assert(Class == null && type != null);
|
|
Type[] argTypes = context.ClassLoader.ArgTypeListFromSig(Sig);
|
|
ConstructorInfo ci = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null);
|
|
if(ci == null)
|
|
{
|
|
throw new InvalidOperationException("Missing .ctor: " + type + "..ctor" + Sig);
|
|
}
|
|
ilgen.Emit(opcode, ci);
|
|
}
|
|
else
|
|
{
|
|
Debug.Assert(Class == null ^ type == null);
|
|
if(Class != null)
|
|
{
|
|
Debug.Assert(Sig != null);
|
|
MethodWrapper method = context.ClassLoader.LoadClassByDottedName(Class).GetMethodWrapper(Name, Sig, false);
|
|
if(method == null)
|
|
{
|
|
throw new InvalidOperationException("method not found: " + Class + "." + Name + Sig);
|
|
}
|
|
method.Link();
|
|
// TODO this code is part of what Compiler.CastInterfaceArgs (in compiler.cs) does,
|
|
// it would be nice if we could avoid this duplication...
|
|
TypeWrapper[] argTypeWrappers = method.GetParameters();
|
|
for(int i = 0; i < argTypeWrappers.Length; i++)
|
|
{
|
|
if(argTypeWrappers[i].IsGhost)
|
|
{
|
|
CodeEmitterLocal[] temps = new CodeEmitterLocal[argTypeWrappers.Length + (method.IsStatic ? 0 : 1)];
|
|
for(int j = temps.Length - 1; j >= 0; j--)
|
|
{
|
|
TypeWrapper tw;
|
|
if(method.IsStatic)
|
|
{
|
|
tw = argTypeWrappers[j];
|
|
}
|
|
else
|
|
{
|
|
if(j == 0)
|
|
{
|
|
tw = method.DeclaringType;
|
|
}
|
|
else
|
|
{
|
|
tw = argTypeWrappers[j - 1];
|
|
}
|
|
}
|
|
if(tw.IsGhost)
|
|
{
|
|
tw.EmitConvStackTypeToSignatureType(ilgen, null);
|
|
}
|
|
temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType);
|
|
ilgen.Emit(OpCodes.Stloc, temps[j]);
|
|
}
|
|
for(int j = 0; j < temps.Length; j++)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldloc, temps[j]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if(opcode.Value == OpCodes.Call.Value)
|
|
{
|
|
method.EmitCall(ilgen);
|
|
}
|
|
else if(opcode.Value == OpCodes.Callvirt.Value)
|
|
{
|
|
method.EmitCallvirt(ilgen);
|
|
}
|
|
else if(opcode.Value == OpCodes.Newobj.Value)
|
|
{
|
|
method.EmitNewobj(ilgen);
|
|
}
|
|
else
|
|
{
|
|
// ldftn or ldvirtftn
|
|
ilgen.Emit(opcode, (MethodInfo)method.GetMethod());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Type[] argTypes;
|
|
if(Sig.StartsWith("("))
|
|
{
|
|
argTypes = context.ClassLoader.ArgTypeListFromSig(Sig);
|
|
}
|
|
else if(Sig == "")
|
|
{
|
|
argTypes = Type.EmptyTypes;
|
|
}
|
|
else
|
|
{
|
|
string[] types = Sig.Split(';');
|
|
argTypes = new Type[types.Length];
|
|
for(int i = 0; i < types.Length; i++)
|
|
{
|
|
argTypes[i] = StaticCompiler.GetTypeForMapXml(context.ClassLoader, types[i]);
|
|
}
|
|
}
|
|
MethodInfo mi = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null);
|
|
if(mi == null)
|
|
{
|
|
throw new InvalidOperationException("Missing method: " + type + "." + Name + Sig);
|
|
}
|
|
ilgen.Emit(opcode, mi);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[XmlType("callvirt")]
|
|
public sealed class Callvirt : Call
|
|
{
|
|
public Callvirt() : base(OpCodes.Callvirt)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("newobj")]
|
|
public sealed class NewObj : Call
|
|
{
|
|
public NewObj() : base(OpCodes.Newobj)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldftn")]
|
|
public sealed class Ldftn : Call
|
|
{
|
|
public Ldftn() : base(OpCodes.Ldftn)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldvirtftn")]
|
|
public sealed class Ldvirtftn : Call
|
|
{
|
|
public Ldvirtftn() : base(OpCodes.Ldvirtftn)
|
|
{
|
|
}
|
|
}
|
|
|
|
public abstract class Simple : Instruction
|
|
{
|
|
private OpCode opcode;
|
|
|
|
public Simple(OpCode opcode)
|
|
{
|
|
this.opcode = opcode;
|
|
}
|
|
|
|
internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.Emit(opcode);
|
|
}
|
|
}
|
|
|
|
[XmlType("dup")]
|
|
public sealed class Dup : Simple
|
|
{
|
|
public Dup() : base(OpCodes.Dup)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("pop")]
|
|
public sealed class Pop : Instruction
|
|
{
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.Emit(OpCodes.Pop);
|
|
}
|
|
}
|
|
|
|
public abstract class TypeOrTypeWrapperInstruction : Instruction
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("type")]
|
|
public string type;
|
|
|
|
internal TypeWrapper typeWrapper;
|
|
internal Type typeType;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
if(typeWrapper == null && typeType == null)
|
|
{
|
|
Debug.Assert(Class == null ^ type == null);
|
|
if(Class != null)
|
|
{
|
|
typeWrapper = context.ClassLoader.LoadClassByDottedName(Class);
|
|
}
|
|
else
|
|
{
|
|
typeType = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[XmlType("isinst")]
|
|
public sealed class IsInst : TypeOrTypeWrapperInstruction
|
|
{
|
|
public IsInst()
|
|
{
|
|
}
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
base.Generate(context, ilgen);
|
|
if(typeType != null)
|
|
{
|
|
ilgen.Emit(OpCodes.Isinst, typeType);
|
|
}
|
|
else
|
|
{
|
|
if(typeWrapper.IsGhost || typeWrapper.IsGhostArray)
|
|
{
|
|
ilgen.Emit(OpCodes.Dup);
|
|
typeWrapper.EmitInstanceOf(ilgen);
|
|
CodeEmitterLabel endLabel = ilgen.DefineLabel();
|
|
ilgen.EmitBrtrue(endLabel);
|
|
ilgen.Emit(OpCodes.Pop);
|
|
ilgen.Emit(OpCodes.Ldnull);
|
|
ilgen.MarkLabel(endLabel);
|
|
}
|
|
else
|
|
{
|
|
ilgen.Emit(OpCodes.Isinst, typeWrapper.TypeAsTBD);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[XmlType("castclass")]
|
|
public sealed class Castclass : TypeOrTypeWrapperInstruction
|
|
{
|
|
public Castclass()
|
|
{
|
|
}
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
base.Generate(context, ilgen);
|
|
if(typeType != null)
|
|
{
|
|
ilgen.Emit(OpCodes.Castclass, typeType);
|
|
}
|
|
else
|
|
{
|
|
typeWrapper.EmitCheckcast(ilgen);
|
|
}
|
|
}
|
|
}
|
|
|
|
[XmlType("castclass_impl")]
|
|
public sealed class Castclass_impl : Instruction
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
|
|
public Castclass_impl()
|
|
{
|
|
}
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.Emit(OpCodes.Castclass, context.ClassLoader.LoadClassByDottedName(Class).TypeAsBaseType);
|
|
}
|
|
}
|
|
|
|
public abstract class TypeInstruction : Instruction
|
|
{
|
|
[XmlAttribute("type")]
|
|
public string type;
|
|
|
|
private OpCode opcode;
|
|
private Type typeType;
|
|
|
|
internal TypeInstruction(OpCode opcode)
|
|
{
|
|
this.opcode = opcode;
|
|
}
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
if(typeType == null)
|
|
{
|
|
Debug.Assert(type != null);
|
|
typeType = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type);
|
|
}
|
|
ilgen.Emit(opcode, typeType);
|
|
}
|
|
}
|
|
|
|
[XmlType("ldobj")]
|
|
public sealed class Ldobj : TypeInstruction
|
|
{
|
|
public Ldobj() : base(OpCodes.Ldobj)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("unbox")]
|
|
public sealed class Unbox : TypeInstruction
|
|
{
|
|
public Unbox() : base(OpCodes.Unbox)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("box")]
|
|
public sealed class Box : TypeInstruction
|
|
{
|
|
public Box() : base(OpCodes.Box)
|
|
{
|
|
}
|
|
}
|
|
|
|
public abstract class Branch : Instruction
|
|
{
|
|
internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
CodeEmitterLabel l;
|
|
if(context[Name] == null)
|
|
{
|
|
l = ilgen.DefineLabel();
|
|
context[Name] = l;
|
|
}
|
|
else
|
|
{
|
|
l = (CodeEmitterLabel)context[Name];
|
|
}
|
|
Emit(ilgen, l);
|
|
}
|
|
|
|
internal abstract void Emit(CodeEmitter ilgen, CodeEmitterLabel label);
|
|
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
}
|
|
|
|
[XmlType("brfalse")]
|
|
public sealed class BrFalse : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBrfalse(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("brtrue")]
|
|
public sealed class BrTrue : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBrtrue(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("br")]
|
|
public sealed class Br : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBr(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("beq")]
|
|
public sealed class Beq : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBeq(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("bne_un")]
|
|
public sealed class Bne_Un : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBne_Un(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("bge_un")]
|
|
public sealed class Bge_Un : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBge_Un(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("ble_un")]
|
|
public sealed class Ble_Un : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBle_Un(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("blt")]
|
|
public sealed class Blt : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBlt(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("blt_un")]
|
|
public sealed class Blt_Un : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitBlt_Un(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("label")]
|
|
public sealed class BrLabel : Instruction
|
|
{
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
CodeEmitterLabel l;
|
|
if(context[Name] == null)
|
|
{
|
|
l = ilgen.DefineLabel();
|
|
context[Name] = l;
|
|
}
|
|
else
|
|
{
|
|
l = (CodeEmitterLabel)context[Name];
|
|
}
|
|
ilgen.MarkLabel(l);
|
|
}
|
|
}
|
|
|
|
[XmlType("stloc")]
|
|
public sealed class StLoc : Instruction
|
|
{
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("type")]
|
|
public string type;
|
|
|
|
private TypeWrapper typeWrapper;
|
|
private Type typeType;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
CodeEmitterLocal lb = (CodeEmitterLocal)context[Name];
|
|
if(lb == null)
|
|
{
|
|
if(typeWrapper == null && typeType == null)
|
|
{
|
|
Debug.Assert(Class == null ^ type == null);
|
|
if(type != null)
|
|
{
|
|
typeType = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type);
|
|
}
|
|
else
|
|
{
|
|
typeWrapper = context.ClassLoader.LoadClassByDottedName(Class);
|
|
}
|
|
}
|
|
lb = ilgen.DeclareLocal(typeType != null ? typeType : typeWrapper.TypeAsTBD);
|
|
context[Name] = lb;
|
|
}
|
|
ilgen.Emit(OpCodes.Stloc, lb);
|
|
}
|
|
}
|
|
|
|
[XmlType("ldloc")]
|
|
public sealed class LdLoc : Instruction
|
|
{
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldloc, (CodeEmitterLocal)context[Name]);
|
|
}
|
|
}
|
|
|
|
[XmlType("ldarga")]
|
|
public sealed class LdArga : Instruction
|
|
{
|
|
[XmlAttribute("argNum")]
|
|
public ushort ArgNum;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.EmitLdarga(ArgNum);
|
|
}
|
|
}
|
|
|
|
[XmlType("ldarg_s")]
|
|
public sealed class LdArg_S : Instruction
|
|
{
|
|
[XmlAttribute("argNum")]
|
|
public byte ArgNum;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.EmitLdarg(ArgNum);
|
|
}
|
|
}
|
|
|
|
[XmlType("ldarg_0")]
|
|
public sealed class LdArg_0 : Simple
|
|
{
|
|
public LdArg_0() : base(OpCodes.Ldarg_0)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldarg_1")]
|
|
public sealed class LdArg_1 : Simple
|
|
{
|
|
public LdArg_1() : base(OpCodes.Ldarg_1)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldarg_2")]
|
|
public sealed class LdArg_2 : Simple
|
|
{
|
|
public LdArg_2() : base(OpCodes.Ldarg_2)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldarg_3")]
|
|
public sealed class LdArg_3 : Simple
|
|
{
|
|
public LdArg_3() : base(OpCodes.Ldarg_3)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldind_i1")]
|
|
public sealed class Ldind_i1 : Simple
|
|
{
|
|
public Ldind_i1() : base(OpCodes.Ldind_I1)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldind_i2")]
|
|
public sealed class Ldind_i2 : Simple
|
|
{
|
|
public Ldind_i2() : base(OpCodes.Ldind_I2)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldind_i4")]
|
|
public sealed class Ldind_i4 : Simple
|
|
{
|
|
public Ldind_i4() : base(OpCodes.Ldind_I4)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldind_i8")]
|
|
public sealed class Ldind_i8 : Simple
|
|
{
|
|
public Ldind_i8() : base(OpCodes.Ldind_I8)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldind_r4")]
|
|
public sealed class Ldind_r4 : Simple
|
|
{
|
|
public Ldind_r4() : base(OpCodes.Ldind_R4)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldind_r8")]
|
|
public sealed class Ldind_r8 : Simple
|
|
{
|
|
public Ldind_r8() : base(OpCodes.Ldind_R8)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldind_ref")]
|
|
public sealed class Ldind_ref : Simple
|
|
{
|
|
public Ldind_ref() : base(OpCodes.Ldind_Ref)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("stind_i1")]
|
|
public sealed class Stind_i1 : Simple
|
|
{
|
|
public Stind_i1() : base(OpCodes.Stind_I1)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("stind_i2")]
|
|
public sealed class Stind_i2 : Simple
|
|
{
|
|
public Stind_i2() : base(OpCodes.Stind_I2)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("stind_i4")]
|
|
public sealed class Stind_i4 : Simple
|
|
{
|
|
public Stind_i4() : base(OpCodes.Stind_I4)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("stind_i8")]
|
|
public sealed class Stind_i8 : Simple
|
|
{
|
|
public Stind_i8()
|
|
: base(OpCodes.Stind_I8)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("stind_ref")]
|
|
public sealed class Stind_ref : Simple
|
|
{
|
|
public Stind_ref() : base(OpCodes.Stind_Ref)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ret")]
|
|
public sealed class Ret : Simple
|
|
{
|
|
public Ret() : base(OpCodes.Ret)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("throw")]
|
|
public sealed class Throw : Simple
|
|
{
|
|
public Throw() : base(OpCodes.Throw)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldflda")]
|
|
public sealed class Ldflda : Instruction
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
FieldWrapper fw = StaticCompiler.GetClassForMapXml(context.ClassLoader, Class).GetFieldWrapper(Name, Sig);
|
|
fw.Link();
|
|
ilgen.Emit(OpCodes.Ldflda, fw.GetField());
|
|
}
|
|
}
|
|
|
|
[XmlType("ldfld")]
|
|
public sealed class Ldfld : Instruction
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
FieldWrapper fw = StaticCompiler.GetClassForMapXml(context.ClassLoader, Class).GetFieldWrapper(Name, Sig);
|
|
fw.Link();
|
|
// we don't use fw.EmitGet because we don't want automatic unboxing and whatever
|
|
ilgen.Emit(OpCodes.Ldfld, fw.GetField());
|
|
}
|
|
}
|
|
|
|
[XmlType("ldsfld")]
|
|
public sealed class Ldsfld : Instruction
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("type")]
|
|
public string Type;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
if(Type != null)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldsfld, StaticCompiler.GetTypeForMapXml(context.ClassLoader, Type).GetField(Name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
|
|
}
|
|
else
|
|
{
|
|
FieldWrapper fw = StaticCompiler.GetClassForMapXml(context.ClassLoader, Class).GetFieldWrapper(Name, Sig);
|
|
fw.Link();
|
|
// we don't use fw.EmitGet because we don't want automatic unboxing and whatever
|
|
ilgen.Emit(OpCodes.Ldsfld, fw.GetField());
|
|
}
|
|
}
|
|
}
|
|
|
|
[XmlType("stfld")]
|
|
public sealed class Stfld : Instruction
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
FieldWrapper fw = StaticCompiler.GetClassForMapXml(context.ClassLoader, Class).GetFieldWrapper(Name, Sig);
|
|
fw.Link();
|
|
// we don't use fw.EmitSet because we don't want automatic unboxing and whatever
|
|
ilgen.Emit(OpCodes.Stfld, fw.GetField());
|
|
}
|
|
}
|
|
|
|
[XmlType("stsfld")]
|
|
public sealed class Stsfld : Instruction
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
FieldWrapper fw = StaticCompiler.GetClassForMapXml(context.ClassLoader, Class).GetFieldWrapper(Name, Sig);
|
|
fw.Link();
|
|
// we don't use fw.EmitSet because we don't want automatic unboxing and whatever
|
|
ilgen.Emit(OpCodes.Stsfld, fw.GetField());
|
|
}
|
|
}
|
|
|
|
[XmlType("ldc_i4")]
|
|
public sealed class Ldc_I4 : Instruction
|
|
{
|
|
[XmlAttribute("value")]
|
|
public int val;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.EmitLdc_I4(val);
|
|
}
|
|
}
|
|
|
|
[XmlType("ldc_i4_0")]
|
|
public sealed class Ldc_I4_0 : Simple
|
|
{
|
|
public Ldc_I4_0() : base(OpCodes.Ldc_I4_0)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldc_i4_1")]
|
|
public sealed class Ldc_I4_1 : Simple
|
|
{
|
|
public Ldc_I4_1() : base(OpCodes.Ldc_I4_1)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldc_i4_m1")]
|
|
public sealed class Ldc_I4_M1 : Simple
|
|
{
|
|
public Ldc_I4_M1() : base(OpCodes.Ldc_I4_M1)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_i")]
|
|
public sealed class Conv_I : Simple
|
|
{
|
|
public Conv_I() : base(OpCodes.Conv_I)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_i1")]
|
|
public sealed class Conv_I1 : Simple
|
|
{
|
|
public Conv_I1() : base(OpCodes.Conv_I1)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_u1")]
|
|
public sealed class Conv_U1 : Simple
|
|
{
|
|
public Conv_U1() : base(OpCodes.Conv_U1)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_i2")]
|
|
public sealed class Conv_I2 : Simple
|
|
{
|
|
public Conv_I2() : base(OpCodes.Conv_I2)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_u2")]
|
|
public sealed class Conv_U2 : Simple
|
|
{
|
|
public Conv_U2() : base(OpCodes.Conv_U2)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_i4")]
|
|
public sealed class Conv_I4 : Simple
|
|
{
|
|
public Conv_I4() : base(OpCodes.Conv_I4)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_u4")]
|
|
public sealed class Conv_U4 : Simple
|
|
{
|
|
public Conv_U4() : base(OpCodes.Conv_U4)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_i8")]
|
|
public sealed class Conv_I8 : Simple
|
|
{
|
|
public Conv_I8() : base(OpCodes.Conv_I8)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("conv_u8")]
|
|
public sealed class Conv_U8 : Simple
|
|
{
|
|
public Conv_U8() : base(OpCodes.Conv_U8)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldlen")]
|
|
public sealed class Ldlen : Simple
|
|
{
|
|
public Ldlen() : base(OpCodes.Ldlen)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("add")]
|
|
public sealed class Add : Simple
|
|
{
|
|
public Add() : base(OpCodes.Add)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("sub")]
|
|
public sealed class Sub : Simple
|
|
{
|
|
public Sub()
|
|
: base(OpCodes.Sub)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("mul")]
|
|
public sealed class Mul : Simple
|
|
{
|
|
public Mul() : base(OpCodes.Mul)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("and")]
|
|
public sealed class And : Simple
|
|
{
|
|
public And()
|
|
: base(OpCodes.And)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("or")]
|
|
public sealed class Or : Simple
|
|
{
|
|
public Or()
|
|
: base(OpCodes.Or)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("xor")]
|
|
public sealed class Xor : Simple
|
|
{
|
|
public Xor()
|
|
: base(OpCodes.Xor)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("not")]
|
|
public sealed class Not : Simple
|
|
{
|
|
public Not()
|
|
: base(OpCodes.Not)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("unaligned")]
|
|
public sealed class Unaligned : Instruction
|
|
{
|
|
[XmlAttribute("alignment")]
|
|
public int Alignment;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.EmitUnaligned((byte)Alignment);
|
|
}
|
|
}
|
|
|
|
[XmlType("cpblk")]
|
|
public sealed class Cpblk : Simple
|
|
{
|
|
public Cpblk() : base(OpCodes.Cpblk)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ceq")]
|
|
public sealed class Ceq : Simple
|
|
{
|
|
public Ceq() : base(OpCodes.Ceq)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("leave")]
|
|
public sealed class Leave : Branch
|
|
{
|
|
internal override void Emit(CodeEmitter ilgen, CodeEmitterLabel label)
|
|
{
|
|
ilgen.EmitLeave(label);
|
|
}
|
|
}
|
|
|
|
[XmlType("endfinally")]
|
|
public sealed class Endfinally : Simple
|
|
{
|
|
public Endfinally() : base(OpCodes.Endfinally)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("exceptionBlock")]
|
|
public sealed class ExceptionBlock : Instruction
|
|
{
|
|
public InstructionList @try;
|
|
public CatchBlock @catch;
|
|
public InstructionList @finally;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.BeginExceptionBlock();
|
|
@try.Generate(context, ilgen);
|
|
if(@catch != null)
|
|
{
|
|
Type type;
|
|
if(@catch.type != null)
|
|
{
|
|
type = StaticCompiler.GetTypeForMapXml(context.ClassLoader, @catch.type);
|
|
}
|
|
else
|
|
{
|
|
type = context.ClassLoader.LoadClassByDottedName(@catch.Class).TypeAsExceptionType;
|
|
}
|
|
ilgen.BeginCatchBlock(type);
|
|
@catch.Generate(context, ilgen);
|
|
}
|
|
if(@finally != null)
|
|
{
|
|
ilgen.BeginFinallyBlock();
|
|
@finally.Generate(context, ilgen);
|
|
}
|
|
ilgen.EndExceptionBlock();
|
|
}
|
|
}
|
|
|
|
public sealed class CatchBlock : InstructionList
|
|
{
|
|
[XmlAttribute("type")]
|
|
public string type;
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
}
|
|
|
|
[XmlType("conditional")]
|
|
public sealed class ConditionalInstruction : Instruction
|
|
{
|
|
[XmlAttribute("framework")]
|
|
public string framework;
|
|
public InstructionList code;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
if (Environment.Version.ToString().StartsWith(framework))
|
|
{
|
|
code.Generate(context, ilgen);
|
|
}
|
|
}
|
|
}
|
|
|
|
[XmlType("volatile")]
|
|
public sealed class Volatile : Simple
|
|
{
|
|
public Volatile() : base(OpCodes.Volatile)
|
|
{
|
|
}
|
|
}
|
|
|
|
[XmlType("ldelema")]
|
|
public sealed class Ldelema : Instruction
|
|
{
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldelema, context.ClassLoader.FieldTypeWrapperFromSig(Sig).TypeAsArrayType);
|
|
}
|
|
}
|
|
|
|
[XmlType("newarr")]
|
|
public sealed class Newarr : Instruction
|
|
{
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
ilgen.Emit(OpCodes.Newarr, context.ClassLoader.FieldTypeWrapperFromSig(Sig).TypeAsArrayType);
|
|
}
|
|
}
|
|
|
|
[XmlType("ldtoken")]
|
|
public sealed class Ldtoken : Instruction
|
|
{
|
|
[XmlAttribute("type")]
|
|
public string type;
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("method")]
|
|
public string Method;
|
|
[XmlAttribute("field")]
|
|
public string Field;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
if (!Validate())
|
|
{
|
|
return;
|
|
}
|
|
|
|
MemberInfo member = Resolve(context);
|
|
Type type = member as Type;
|
|
MethodInfo method = member as MethodInfo;
|
|
ConstructorInfo constructor = member as ConstructorInfo;
|
|
FieldInfo field = member as FieldInfo;
|
|
|
|
if (type != null)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldtoken, type);
|
|
}
|
|
else if (method != null)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldtoken, method);
|
|
}
|
|
else if (constructor != null)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldtoken, constructor);
|
|
}
|
|
else if (field != null)
|
|
{
|
|
ilgen.Emit(OpCodes.Ldtoken, field);
|
|
}
|
|
else
|
|
{
|
|
StaticCompiler.IssueMessage(Message.MapXmlUnableToResolveOpCode, ToString());
|
|
}
|
|
}
|
|
|
|
private bool Validate()
|
|
{
|
|
if (type != null && Class == null)
|
|
{
|
|
if (Method != null || Field != null || Sig != null)
|
|
{
|
|
StaticCompiler.IssueMessage(Message.MapXmlError, "not implemented: cannot use 'type' attribute with 'method' or 'field' attribute for ldtoken");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
else if (Class != null && type == null)
|
|
{
|
|
if (Method == null && Field == null)
|
|
{
|
|
if (Sig != null)
|
|
{
|
|
StaticCompiler.IssueMessage(Message.MapXmlError, "cannot specify 'sig' attribute without either 'method' or 'field' attribute for ldtoken");
|
|
}
|
|
return true;
|
|
}
|
|
if (Method != null && Field != null)
|
|
{
|
|
StaticCompiler.IssueMessage(Message.MapXmlError, "cannot specify both 'method' and 'field' attribute for ldtoken");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
StaticCompiler.IssueMessage(Message.MapXmlError, "must specify either 'type' or 'class' attribute for ldtoken");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private MemberInfo Resolve(CodeGenContext context)
|
|
{
|
|
if (type != null)
|
|
{
|
|
if (Class != null || Method != null || Field != null || Sig != null)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
return StaticCompiler.GetTypeForMapXml(context.ClassLoader, type);
|
|
}
|
|
else if (Class != null)
|
|
{
|
|
TypeWrapper tw = context.ClassLoader.LoadClassByDottedNameFast(Class);
|
|
if (tw == null)
|
|
{
|
|
return null;
|
|
}
|
|
else if (Method != null)
|
|
{
|
|
MethodWrapper mw = tw.GetMethodWrapper(Method, Sig, false);
|
|
if (mw == null)
|
|
{
|
|
return null;
|
|
}
|
|
return mw.GetMethod();
|
|
}
|
|
else if (Field != null)
|
|
{
|
|
FieldWrapper fw = tw.GetFieldWrapper(Field, Sig);
|
|
if (fw == null)
|
|
{
|
|
return null;
|
|
}
|
|
return fw.GetField();
|
|
}
|
|
else
|
|
{
|
|
return tw.TypeAsBaseType;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
[XmlType("runclassinit")]
|
|
public sealed class RunClassInit : Instruction
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
context.ClassLoader.LoadClassByDottedName(Class).EmitRunClassConstructor(ilgen);
|
|
}
|
|
}
|
|
|
|
[XmlType("exceptionMapping")]
|
|
public sealed class EmitExceptionMapping : Instruction
|
|
{
|
|
internal ExceptionMapping[] mapping;
|
|
|
|
internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
CompilerClassLoader.ExceptionMapEmitter emitter = new CompilerClassLoader.ExceptionMapEmitter(mapping);
|
|
emitter.Emit(context, ilgen);
|
|
}
|
|
}
|
|
|
|
public class InstructionList
|
|
{
|
|
[XmlElement(typeof(Ldstr))]
|
|
[XmlElement(typeof(Call))]
|
|
[XmlElement(typeof(Callvirt))]
|
|
[XmlElement(typeof(Ldftn))]
|
|
[XmlElement(typeof(Ldvirtftn))]
|
|
[XmlElement(typeof(Dup))]
|
|
[XmlElement(typeof(Pop))]
|
|
[XmlElement(typeof(IsInst))]
|
|
[XmlElement(typeof(Castclass))]
|
|
[XmlElement(typeof(Castclass_impl))]
|
|
[XmlElement(typeof(Ldobj))]
|
|
[XmlElement(typeof(Unbox))]
|
|
[XmlElement(typeof(Box))]
|
|
[XmlElement(typeof(BrFalse))]
|
|
[XmlElement(typeof(BrTrue))]
|
|
[XmlElement(typeof(Br))]
|
|
[XmlElement(typeof(Beq))]
|
|
[XmlElement(typeof(Bne_Un))]
|
|
[XmlElement(typeof(Bge_Un))]
|
|
[XmlElement(typeof(Ble_Un))]
|
|
[XmlElement(typeof(Blt))]
|
|
[XmlElement(typeof(Blt_Un))]
|
|
[XmlElement(typeof(BrLabel))]
|
|
[XmlElement(typeof(NewObj))]
|
|
[XmlElement(typeof(StLoc))]
|
|
[XmlElement(typeof(LdLoc))]
|
|
[XmlElement(typeof(LdArga))]
|
|
[XmlElement(typeof(LdArg_S))]
|
|
[XmlElement(typeof(LdArg_0))]
|
|
[XmlElement(typeof(LdArg_1))]
|
|
[XmlElement(typeof(LdArg_2))]
|
|
[XmlElement(typeof(LdArg_3))]
|
|
[XmlElement(typeof(Ldind_i1))]
|
|
[XmlElement(typeof(Ldind_i2))]
|
|
[XmlElement(typeof(Ldind_i4))]
|
|
[XmlElement(typeof(Ldind_i8))]
|
|
[XmlElement(typeof(Ldind_r4))]
|
|
[XmlElement(typeof(Ldind_r8))]
|
|
[XmlElement(typeof(Ldind_ref))]
|
|
[XmlElement(typeof(Stind_i1))]
|
|
[XmlElement(typeof(Stind_i2))]
|
|
[XmlElement(typeof(Stind_i4))]
|
|
[XmlElement(typeof(Stind_i8))]
|
|
[XmlElement(typeof(Stind_ref))]
|
|
[XmlElement(typeof(Ret))]
|
|
[XmlElement(typeof(Throw))]
|
|
[XmlElement(typeof(Ldnull))]
|
|
[XmlElement(typeof(Ldflda))]
|
|
[XmlElement(typeof(Ldfld))]
|
|
[XmlElement(typeof(Ldsfld))]
|
|
[XmlElement(typeof(Stfld))]
|
|
[XmlElement(typeof(Stsfld))]
|
|
[XmlElement(typeof(Ldc_I4))]
|
|
[XmlElement(typeof(Ldc_I4_0))]
|
|
[XmlElement(typeof(Ldc_I4_1))]
|
|
[XmlElement(typeof(Ldc_I4_M1))]
|
|
[XmlElement(typeof(Conv_I))]
|
|
[XmlElement(typeof(Conv_I1))]
|
|
[XmlElement(typeof(Conv_U1))]
|
|
[XmlElement(typeof(Conv_I2))]
|
|
[XmlElement(typeof(Conv_U2))]
|
|
[XmlElement(typeof(Conv_I4))]
|
|
[XmlElement(typeof(Conv_U4))]
|
|
[XmlElement(typeof(Conv_I8))]
|
|
[XmlElement(typeof(Conv_U8))]
|
|
[XmlElement(typeof(Ldlen))]
|
|
[XmlElement(typeof(ExceptionBlock))]
|
|
[XmlElement(typeof(Add))]
|
|
[XmlElement(typeof(Sub))]
|
|
[XmlElement(typeof(Mul))]
|
|
[XmlElement(typeof(And))]
|
|
[XmlElement(typeof(Or))]
|
|
[XmlElement(typeof(Xor))]
|
|
[XmlElement(typeof(Not))]
|
|
[XmlElement(typeof(Unaligned))]
|
|
[XmlElement(typeof(Cpblk))]
|
|
[XmlElement(typeof(Ceq))]
|
|
[XmlElement(typeof(ConditionalInstruction))]
|
|
[XmlElement(typeof(Volatile))]
|
|
[XmlElement(typeof(Ldelema))]
|
|
[XmlElement(typeof(Newarr))]
|
|
[XmlElement(typeof(Ldtoken))]
|
|
[XmlElement(typeof(Leave))]
|
|
[XmlElement(typeof(Endfinally))]
|
|
[XmlElement(typeof(RunClassInit))]
|
|
[XmlElement(typeof(EmitExceptionMapping))]
|
|
public Instruction[] invoke;
|
|
|
|
internal void Generate(CodeGenContext context, CodeEmitter ilgen)
|
|
{
|
|
if(invoke != null)
|
|
{
|
|
for(int i = 0; i < invoke.Length; i++)
|
|
{
|
|
if(invoke[i].LineNumber != -1)
|
|
{
|
|
ilgen.SetLineNumber((ushort)invoke[i].LineNumber);
|
|
}
|
|
invoke[i].Generate(context, ilgen);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void Emit(ClassLoaderWrapper loader, CodeEmitter ilgen)
|
|
{
|
|
Generate(new CodeGenContext(loader), ilgen);
|
|
}
|
|
}
|
|
|
|
public sealed class Throws
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
}
|
|
|
|
public sealed class Redirect
|
|
{
|
|
private int linenum = Root.LineNumber;
|
|
|
|
internal int LineNumber
|
|
{
|
|
get
|
|
{
|
|
return linenum;
|
|
}
|
|
}
|
|
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
[XmlAttribute("type")]
|
|
public string Type;
|
|
|
|
internal void Emit(ClassLoaderWrapper loader, CodeEmitter ilgen)
|
|
{
|
|
if(Type != "static" || Class == null || Name == null || Sig == null)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
Type[] redirParamTypes = loader.ArgTypeListFromSig(Sig);
|
|
for(int i = 0; i < redirParamTypes.Length; i++)
|
|
{
|
|
ilgen.EmitLdarg(i);
|
|
}
|
|
// HACK if the class name contains a comma, we assume it is a .NET type
|
|
if(Class.IndexOf(',') >= 0)
|
|
{
|
|
Type type = StaticCompiler.Universe.GetType(Class, true);
|
|
MethodInfo mi = type.GetMethod(Name, redirParamTypes);
|
|
if(mi == null)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
ilgen.Emit(OpCodes.Call, mi);
|
|
}
|
|
else
|
|
{
|
|
TypeWrapper tw = loader.LoadClassByDottedName(Class);
|
|
MethodWrapper mw = tw.GetMethodWrapper(Name, Sig, false);
|
|
if(mw == null)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
mw.Link();
|
|
mw.EmitCall(ilgen);
|
|
}
|
|
// TODO we may need a cast here (or a stack to return type conversion)
|
|
ilgen.Emit(OpCodes.Ret);
|
|
}
|
|
}
|
|
|
|
public sealed class Override
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
}
|
|
|
|
public sealed class ReplaceMethodCall
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
public InstructionList code;
|
|
}
|
|
|
|
public abstract class MethodBase
|
|
{
|
|
[XmlAttribute("attributes")]
|
|
public MethodAttributes MethodAttributes;
|
|
public InstructionList body;
|
|
[XmlElement("throws", typeof(Throws))]
|
|
public Throws[] throws;
|
|
[XmlElement("attribute")]
|
|
public Attribute[] Attributes;
|
|
[XmlElement("replace-method-call")]
|
|
public ReplaceMethodCall[] ReplaceMethodCalls;
|
|
public InstructionList prologue;
|
|
|
|
internal abstract MethodKey ToMethodKey(string className);
|
|
}
|
|
|
|
public abstract class MethodConstructorBase : MethodBase
|
|
{
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
[XmlAttribute("modifiers")]
|
|
public MapModifiers Modifiers;
|
|
[XmlElement("parameter")]
|
|
public Param[] Params;
|
|
public InstructionList alternateBody;
|
|
public Redirect redirect;
|
|
|
|
internal void Emit(ClassLoaderWrapper loader, CodeEmitter ilgen)
|
|
{
|
|
if(prologue != null)
|
|
{
|
|
prologue.Emit(loader, ilgen);
|
|
}
|
|
if(redirect != null)
|
|
{
|
|
redirect.Emit(loader, ilgen);
|
|
}
|
|
else
|
|
{
|
|
body.Emit(loader, ilgen);
|
|
}
|
|
}
|
|
}
|
|
|
|
public sealed class Method : MethodConstructorBase
|
|
{
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("nonullcheck")]
|
|
public bool NoNullCheck;
|
|
public InstructionList nonvirtualAlternateBody;
|
|
public Override @override;
|
|
|
|
internal override MethodKey ToMethodKey(string className)
|
|
{
|
|
return new MethodKey(className, Name, Sig);
|
|
}
|
|
}
|
|
|
|
public sealed class Constructor : MethodConstructorBase
|
|
{
|
|
internal override MethodKey ToMethodKey(string className)
|
|
{
|
|
return new MethodKey(className, StringConstants.INIT, Sig);
|
|
}
|
|
}
|
|
|
|
public sealed class ClassInitializer : MethodBase
|
|
{
|
|
internal override MethodKey ToMethodKey(string className)
|
|
{
|
|
return new MethodKey(className, StringConstants.CLINIT, StringConstants.SIG_VOID);
|
|
}
|
|
}
|
|
|
|
public sealed class Field
|
|
{
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
[XmlAttribute("modifiers")]
|
|
public MapModifiers Modifiers;
|
|
[XmlAttribute("constant")]
|
|
public string Constant;
|
|
[XmlElement("attribute")]
|
|
public Attribute[] Attributes;
|
|
}
|
|
|
|
public sealed class Property
|
|
{
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
public Method getter;
|
|
public Method setter;
|
|
[XmlElement("attribute")]
|
|
public Attribute[] Attributes;
|
|
}
|
|
|
|
public sealed class Interface
|
|
{
|
|
[XmlAttribute("class")]
|
|
public string Name;
|
|
[XmlElement("method")]
|
|
public Method[] Methods;
|
|
}
|
|
|
|
[Flags]
|
|
public enum MapModifiers
|
|
{
|
|
[XmlEnum("public")]
|
|
Public = Modifiers.Public,
|
|
[XmlEnum("protected")]
|
|
Protected = Modifiers.Protected,
|
|
[XmlEnum("private")]
|
|
Private = Modifiers.Private,
|
|
[XmlEnum("final")]
|
|
Final = Modifiers.Final,
|
|
[XmlEnum("interface")]
|
|
Interface = Modifiers.Interface,
|
|
[XmlEnum("static")]
|
|
Static = Modifiers.Static,
|
|
[XmlEnum("abstract")]
|
|
Abstract = Modifiers.Abstract,
|
|
[XmlEnum("ACC_BRIDGE")]
|
|
Bridge = Modifiers.Bridge,
|
|
[XmlEnum("ACC_SYNTHETIC")]
|
|
Synthetic = Modifiers.Synthetic,
|
|
}
|
|
|
|
public enum Scope
|
|
{
|
|
[XmlEnum("public")]
|
|
Public = 0,
|
|
[XmlEnum("private")]
|
|
Private = 1
|
|
}
|
|
|
|
public sealed class Element
|
|
{
|
|
[XmlText]
|
|
public string Value;
|
|
}
|
|
|
|
public sealed class Param
|
|
{
|
|
[XmlText]
|
|
public string Value;
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("sig")]
|
|
public string Sig; // optional (for object type args)
|
|
[XmlElement("element")]
|
|
public Element[] Elements;
|
|
[XmlElement("attribute")]
|
|
public Attribute[] Attributes;
|
|
}
|
|
|
|
public sealed class Attribute
|
|
{
|
|
[XmlAttribute("type")]
|
|
public string Type;
|
|
[XmlAttribute("class")]
|
|
public string Class;
|
|
[XmlAttribute("sig")]
|
|
public string Sig;
|
|
[XmlElement("parameter")]
|
|
public Param[] Params;
|
|
[XmlElement("property")]
|
|
public Param[] Properties;
|
|
[XmlElement("field")]
|
|
public Param[] Fields;
|
|
}
|
|
|
|
[XmlType("class")]
|
|
public sealed class Class
|
|
{
|
|
[XmlAttribute("name")]
|
|
public string Name;
|
|
[XmlAttribute("shadows")]
|
|
public string Shadows;
|
|
[XmlAttribute("modifiers")]
|
|
public MapModifiers Modifiers;
|
|
[XmlAttribute("scope")]
|
|
public Scope scope;
|
|
[XmlElement("constructor")]
|
|
public Constructor[] Constructors;
|
|
[XmlElement("method")]
|
|
public Method[] Methods;
|
|
[XmlElement("field")]
|
|
public Field[] Fields;
|
|
[XmlElement("property")]
|
|
public Property[] Properties;
|
|
[XmlElement("implements")]
|
|
public Interface[] Interfaces;
|
|
[XmlElement("clinit")]
|
|
public ClassInitializer Clinit;
|
|
[XmlElement("attribute")]
|
|
public Attribute[] Attributes;
|
|
}
|
|
|
|
public sealed class Assembly
|
|
{
|
|
[XmlElement("class")]
|
|
public Class[] Classes;
|
|
[XmlElement("attribute")]
|
|
public Attribute[] Attributes;
|
|
}
|
|
|
|
[XmlType("exception")]
|
|
public sealed class ExceptionMapping
|
|
{
|
|
[XmlAttribute]
|
|
public string src;
|
|
[XmlAttribute]
|
|
public string dst;
|
|
public InstructionList code;
|
|
}
|
|
|
|
[XmlRoot("root")]
|
|
public sealed class Root
|
|
{
|
|
internal static System.Xml.XmlTextReader xmlReader;
|
|
|
|
internal static int LineNumber
|
|
{
|
|
get
|
|
{
|
|
return xmlReader == null ? -1: xmlReader.LineNumber;
|
|
}
|
|
}
|
|
|
|
[XmlElement("assembly")]
|
|
public Assembly assembly;
|
|
public ExceptionMapping[] exceptionMappings;
|
|
}
|
|
}
|