refactor .NET-specific CodeProvider code into separate ILCodeProvider class

This commit is contained in:
Michael Becker 2021-04-29 23:02:32 -04:00
parent 60d72f91b5
commit 2c0d651756
No known key found for this signature in database
GPG Key ID: 98C333A81F18C22C
5 changed files with 456 additions and 367 deletions

View File

@ -33,7 +33,7 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable
/// <summary>
/// Gets the <see cref="CodeProviders.CSharpCodeProvider" />
/// </summary>
/// <value>The CS harp.</value>
/// <value>The C# code provider.</value>
public static CodeProviders.CSharpCodeProvider CSharp { get; } = new CodeProviders.CSharpCodeProvider();
public abstract string Title { get; }
@ -186,290 +186,5 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable
{
return GetMethodSignatureInternal(mi);
}
private static BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
public MethodInfo[] GetMethods(Type type)
{
MethodInfo[] meths = type.GetMethods(bindingFlags);
List<MethodInfo> list = new List<MethodInfo>();
for (int j = 0; j < meths.Length; j++)
{
if (meths[j].IsSpecialName && (meths[j].Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase) || meths[j].Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase)) && (type.GetProperty(meths[j].Name.Substring(4), bindingFlags) != null))
{
// we can be REASONABLY sure that this is a property setter / getter,
// and as we've already gotten all the properties, ignore it
continue;
}
list.Add(meths[j]);
}
return list.ToArray();
}
public FieldInfo[] GetFields(Type type, out List<string> AutoPropertyNames)
{
List<FieldInfo> list = new List<FieldInfo>();
AutoPropertyNames = new List<string>();
FieldInfo[] fields = type.GetFields(bindingFlags);
for (int j = 0; j < fields.Length; j++)
{
if (fields[j].Name.StartsWith("<", StringComparison.OrdinalIgnoreCase) && fields[j].Name.Contains(">"))
{
// might be a backing field
int k__backingfield_name_start = fields[j].Name.IndexOf('<');
int k__backingfield_name_end = fields[j].Name.IndexOf('>', k__backingfield_name_start);
string k__backingfield_name = fields[j].Name.Substring(k__backingfield_name_start + 1, k__backingfield_name_end - k__backingfield_name_start - 1);
PropertyInfo pi = type.GetProperty(k__backingfield_name, bindingFlags);
if (pi != null)
{
AutoPropertyNames.Add(pi.Name);
continue;
}
}
else
{
list.Add(fields[j]);
}
}
return list.ToArray();
}
public string GetILOpcodeStr(short opcode)
{
return GetILOpcodeStr((ILOpcode)opcode);
}
public string GetILOpcodeStr(ILOpcode opcode)
{
switch (opcode)
{
case ILOpcode.Add: return "add";
case ILOpcode.AddOvf: return "add.ovf";
case ILOpcode.AddOvfUn: return "add.ovf.un";
case ILOpcode.And: return "and";
case ILOpcode.ArgList: return "arglist";
case ILOpcode.Beq: return "beq <int32 (target)>";
case ILOpcode.BeqS: return "beq <int32 (target)>";
case ILOpcode.Bge: return "bge <int32 (target)>";
case ILOpcode.BgeS: return "bge.s <int8 (target)>";
case ILOpcode.BgeUn: return "bge.un <int32 (target)>";
case ILOpcode.BgeUnS: return "bge.un.s <int8 (target)>";
case ILOpcode.Bgt: return "bgt <int32 (target)>";
case ILOpcode.BgtS: return "bgt.s <int8 (target)>";
case ILOpcode.BgtUn: return "bgt.un <int32 (target)>";
case ILOpcode.BgtUnS: return "bgt.un.s <int8 (target)>";
case ILOpcode.Ble: return "ble <int32 (target)>";
case ILOpcode.BleS: return "ble.s <int8 (target)>";
case ILOpcode.BleUn: return "ble.un <int32 (target)>";
case ILOpcode.BleUnS: return "ble.un.s <int8 (target)>";
case ILOpcode.Blt: return "blt <int32 (target)>";
case ILOpcode.BltS: return "blt.s <int8 (target)>";
case ILOpcode.BltUn: return "blt.un <int32 (target)>";
case ILOpcode.BltUnS: return "blt.un.s <int8 (target)>";
case ILOpcode.BneUn: return "bne.un <int32 (target)>";
case ILOpcode.BneUnS: return "bne.un.s <int8 (target)>";
case ILOpcode.Box: return "box <typeTok>";
case ILOpcode.Br: return "br <int32 (target)>";
case ILOpcode.BrS: return "br.s <int8 (target)>";
case ILOpcode.Break: return "break";
case ILOpcode.BrFalse: return "brfalse <int32 (target)>";
case ILOpcode.BrFalseS: return "brfalse.s <int8 (target)>";
case ILOpcode.BrTrue: return "brtrue <int32 (target)>";
case ILOpcode.BrTrueS: return "brtrue.s <int8 (target)>";
case ILOpcode.Call: return "call <method>";
case ILOpcode.CallI: return "calli <callsitedescr>";
case ILOpcode.CallVirt: return "callvirt <method>";
case ILOpcode.CastClass: return "castclass <class>";
case ILOpcode.Ceq: return "ceq";
case ILOpcode.Cgt: return "cgt";
case ILOpcode.CgtUn: return "cgt.un";
case ILOpcode.CkFinite: return "ckfinite";
case ILOpcode.Clt: return "clt";
case ILOpcode.CltUn: return "clt.un";
case ILOpcode.Constrained: return "constrained <thisType>";
case ILOpcode.ConvI: return "conv.i";
case ILOpcode.ConvI1: return "conv.i1";
case ILOpcode.ConvI2: return "conv.i2";
case ILOpcode.ConvI4: return "conv.i4";
case ILOpcode.ConvI8: return "conv.i8";
case ILOpcode.ConvOvfI: return "conv.ovf.i";
case ILOpcode.ConvOvfIUn: return "conv.ovf.i.un";
case ILOpcode.ConvOvfI1: return "conv.ovf.i1";
case ILOpcode.ConvOvfI1Un: return "conv.ovf.i1.un";
case ILOpcode.ConvOvfI2: return "conv.ovf.i2";
case ILOpcode.ConvOvfI2Un: return "conv.ovf.i2.un";
case ILOpcode.ConvOvfI4: return "conv.ovf.i4";
case ILOpcode.ConvOvfI4Un: return "conv.ovf.i4.un";
case ILOpcode.ConvOvfI8: return "conv.ovf.i8";
case ILOpcode.ConvOvfI8Un: return "conv.ovf.i8.un";
case ILOpcode.ConvOvfU: return "conv.ovf.u";
case ILOpcode.ConvOvfUUn: return "conv.ovf.u.un";
case ILOpcode.ConvOvfU1: return "conv.ovf.u1";
case ILOpcode.ConvOvfU1Un: return "conv.ovf.u1.un";
case ILOpcode.ConvOvfU2: return "conv.ovf.u2";
case ILOpcode.ConvOvfU2Un: return "conv.ovf.u2.un";
case ILOpcode.ConvOvfU4: return "conv.ovf.u4";
case ILOpcode.ConvOvfU4Un: return "conv.ovf.u4.un";
case ILOpcode.ConvOvfU8: return "conv.ovf.u8";
case ILOpcode.ConvOvfU8Un: return "conv.ovf.u8.un";
case ILOpcode.ConvRUn: return "conv.r.un";
case ILOpcode.ConvR4: return "conv.r4";
case ILOpcode.ConvR8: return "conv.r8";
case ILOpcode.ConvU: return "conv.u";
case ILOpcode.ConvU1: return "conv.u1";
case ILOpcode.ConvU2: return "conv.u2";
case ILOpcode.ConvU4: return "conv.u4";
case ILOpcode.ConvU8: return "conv.u8";
case ILOpcode.CpBlk: return "cpblk";
case ILOpcode.CpObj: return "cpobj <typeTok>";
case ILOpcode.Div: return "div";
case ILOpcode.DivUn: return "div.un";
case ILOpcode.Dup: return "dup";
case ILOpcode.EndFault: return "endfault";
case ILOpcode.EndFilter: return "endfilter";
// case ILOpcode.EndFinally: return "endfinally"; // same as endfault?
case ILOpcode.InitBlk: return "initblk";
case ILOpcode.InitObj: return "initobj <typeTok>";
case ILOpcode.IsInst: return "isinst <class>";
case ILOpcode.Jmp: return "jmp";
case ILOpcode.LdArg: return "ldarg <uint16 (num)>";
case ILOpcode.LdArg0: return "ldarg.0";
case ILOpcode.LdArg1: return "ldarg.1";
case ILOpcode.LdArg2: return "ldarg.2";
case ILOpcode.LdArg3: return "ldarg.3";
case ILOpcode.LdArgS: return "ldarg.s <uint8 (num)>";
case ILOpcode.LdArgA: return "ldarg.a <uint16 (num)>";
case ILOpcode.LdArgAS: return "ldarg.a.s <uint8 (num)>";
case ILOpcode.LdCI4: return "ldc.i4 <int32 (num)>";
case ILOpcode.LdCI4_M1: return "ldc.i4.m1";
case ILOpcode.LdCI4_0: return "ldc.i4.0";
case ILOpcode.LdCI4_1: return "ldc.i4.1";
case ILOpcode.LdCI4_2: return "ldc.i4.2";
case ILOpcode.LdCI4_3: return "ldc.i4.3";
case ILOpcode.LdCI4_4: return "ldc.i4.4";
case ILOpcode.LdCI4_5: return "ldc.i4.5";
case ILOpcode.LdCI4_6: return "ldc.i4.6";
case ILOpcode.LdCI4_7: return "ldc.i4.7";
case ILOpcode.LdCI4_8: return "ldc.i4.8";
case ILOpcode.LdCI4S: return "ldc.i4.s <int8 (num)>";
case ILOpcode.LdCI8: return "ldc.i8 <int64 (num)>";
case ILOpcode.LdCR4: return "ldc.r4 <float32 (num)>";
case ILOpcode.LdCR8: return "ldc.r8 <float64 (num)>";
case ILOpcode.LdElem: return "ldelem <typeTok>";
case ILOpcode.LdElemI: return "ldelem.i";
case ILOpcode.LdElemI1: return "ldelem.i1";
case ILOpcode.LdElemU1: return "ldelem.u1";
case ILOpcode.LdElemI2: return "ldelem.i2";
case ILOpcode.LdElemU2: return "ldelem.u2";
case ILOpcode.LdElemI4: return "ldelem.i4";
case ILOpcode.LdElemU4: return "ldelem.u4";
case ILOpcode.LdElemI8: return "ldelem.i8";
case ILOpcode.LdElemR4: return "ldelem.r4";
case ILOpcode.LdElemR8: return "ldelem.r8";
case ILOpcode.LdElemRef: return "ldelem.ref";
case ILOpcode.LdElemA: return "ldelema <class>";
case ILOpcode.LdFld: return "ldfld <field>";
case ILOpcode.LdFldA: return "ldflda <field>";
case ILOpcode.LdFtn: return "ldftn <method>";
case ILOpcode.LdIndI: return "ldind.i";
case ILOpcode.LdIndI1: return "ldind.i1";
case ILOpcode.LdIndU1: return "ldind.u1";
case ILOpcode.LdIndI2: return "ldind.i2";
case ILOpcode.LdIndU2: return "ldind.u2";
case ILOpcode.LdIndI4: return "ldind.i4";
case ILOpcode.LdIndU4: return "ldind.u4";
case ILOpcode.LdIndI8: return "ldind.i8";
case ILOpcode.LdIndR4: return "ldind.r4";
case ILOpcode.LdIndR8: return "ldind.r8";
case ILOpcode.LdLen: return "ldlen";
case ILOpcode.LdLoc: return "ldloc <uint16 (indx)>";
case ILOpcode.LdLoc0: return "ldloc.0";
case ILOpcode.LdLoc1: return "ldloc.1";
case ILOpcode.LdLoc2: return "ldloc.2";
case ILOpcode.LdLoc3: return "ldloc.3";
case ILOpcode.LdLocS: return "ldloc.s <uint8 (indx)>";
case ILOpcode.LdLocA: return "ldloca <uint16 (indx)>";
case ILOpcode.LdLocAS: return "ldloca.s <uint8 (indx)>";
case ILOpcode.LdNull: return "ldnull";
case ILOpcode.LdObj: return "ldobj <typeTok>";
case ILOpcode.LdSFld: return "ldsfld <field>";
case ILOpcode.LdSFldA: return "ldsflda <field>";
case ILOpcode.LdStr: return "ldstr <string>";
case ILOpcode.LdToken: return "ldtoken <token>";
case ILOpcode.LdVirtFtn: return "ldvirtftn <method>";
case ILOpcode.Leave: return "leave <int32 (target)>";
case ILOpcode.LeaveS: return "leave <int8 (target)>";
case ILOpcode.LocAlloc: return "localloc";
case ILOpcode.MkRefAny: return "mkrefany <class>";
case ILOpcode.Mul: return "mul";
case ILOpcode.MulOvf: return "mul.ovf";
case ILOpcode.MulOvfUn: return "mul.ovf.un";
case ILOpcode.Neg: return "neg";
case ILOpcode.NewArr: return "newarr <etype>";
case ILOpcode.NewObj: return "newobj <ctor>";
case ILOpcode.No: return "no.{typecheck, rangecheck, nullcheck}";
case ILOpcode.Nop: return "nop";
case ILOpcode.Not: return "not";
case ILOpcode.Or: return "or";
case ILOpcode.Pop: return "pop";
case ILOpcode.Readonly: return "readonly.";
case ILOpcode.RefAnyType: return "refanytype";
case ILOpcode.RefAnyVal: return "refanyval <type>";
case ILOpcode.Rem: return "rem";
case ILOpcode.RemUn: return "rem.un";
case ILOpcode.Ret: return "ret";
case ILOpcode.Rethrow: return "rethrow";
case ILOpcode.Shl: return "shl";
case ILOpcode.Shr: return "shl";
case ILOpcode.ShrUn: return "shl";
case ILOpcode.SizeOf: return "sizeof <typeTok>";
case ILOpcode.StArg: return "starg <uint16 (num)>";
case ILOpcode.StArgS: return "starg.s <uint8 (num)>";
case ILOpcode.StElem: return "stelem <typeTok>";
case ILOpcode.StElemI: return "stelem.i";
case ILOpcode.StElemI1: return "stelem.i1";
case ILOpcode.StElemI2: return "stelem.i2";
case ILOpcode.StElemI4: return "stelem.i4";
case ILOpcode.StElemI8: return "stelem.i8";
case ILOpcode.StElemR4: return "stelem.r4";
case ILOpcode.StElemR8: return "stelem.r8";
case ILOpcode.StElemRef: return "stelem.ref";
case ILOpcode.StFld: return "stfld <field>";
case ILOpcode.StIndI: return "stind.i";
case ILOpcode.StIndI1: return "stind.i1";
case ILOpcode.StIndI2: return "stind.i2";
case ILOpcode.StIndI4: return "stind.i4";
case ILOpcode.StIndI8: return "stind.i8";
case ILOpcode.StIndR4: return "stind.r4";
case ILOpcode.StIndR8: return "stind.r8";
case ILOpcode.StIndRef: return "stind.ref";
case ILOpcode.StLoc: return "stloc <uint16 (indx)>";
case ILOpcode.StLoc0: return "stloc.0";
case ILOpcode.StLoc1: return "stloc.1";
case ILOpcode.StLoc2: return "stloc.2";
case ILOpcode.StLoc3: return "stloc.3";
case ILOpcode.StLocS: return "stloc.s <uint8 (indx)>";
case ILOpcode.StObj: return "stobj <typeTok>";
case ILOpcode.StSFld: return "stsfld <field>";
case ILOpcode.Sub: return "sub";
case ILOpcode.SubOvf: return "sub.ovf";
case ILOpcode.SubOvfUn: return "sub.ovf.un";
case ILOpcode.Switch: return "switch <uint32, int32, int32 (t1..tN)>";
case ILOpcode.Tail: return "tail.";
case ILOpcode.Throw: return "throw";
case ILOpcode.Unaligned: return "unaligned.(alignment)";
case ILOpcode.Unbox: return "unbox <typeTok>";
case ILOpcode.UnboxAny: return "unbox.any <typeTok>";
case ILOpcode.Volatile: return "volatile.";
case ILOpcode.Xor: return "xor";
}
return "<OPCODE:" + ((short)opcode).ToString("X").PadLeft(2, '0') + ">";
}
public string GetVariableName(MethodInfo mi, LocalVariableInfo localVariableInfo)
{
// TODO: read the PDB file (if exists) to get the local variable info
return "local_" + localVariableInfo.LocalIndex.ToString();
}
}
}

View File

@ -31,7 +31,7 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.Co
/// <summary>
/// Provides a <see cref="CodeProvider" /> that translates MSIL code into C#.
/// </summary>
public class CSharpCodeProvider : CodeProvider
public class CSharpCodeProvider : ILCodeProvider
{
public override string Title => "C#";
public override string CodeFileExtension => ".cs";
@ -191,84 +191,6 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.Co
return sb.ToString();
}
private int? OpcodeToLiteralInt(ILOpcode opcode)
{
switch (opcode)
{
case ILOpcode.LdCI4_0:
{
return 0;
}
case ILOpcode.LdCI4_1:
{
return 1;
}
case ILOpcode.LdCI4_2:
{
return 2;
}
case ILOpcode.LdCI4_3:
{
return 3;
}
case ILOpcode.LdCI4_4:
{
return 4;
}
case ILOpcode.LdCI4_5:
{
return 5;
}
case ILOpcode.LdCI4_6:
{
return 6;
}
case ILOpcode.LdCI4_7:
{
return 7;
}
case ILOpcode.LdCI4_8:
{
return 8;
}
case ILOpcode.LdCI4_M1:
{
return -1;
}
}
return null;
}
private ILOpcode PeekOpcode(Reader r)
{
int sz = 0;
ILOpcode opcode = ReadOpcode(r, out sz);
if (sz == 0)
return opcode;
r.Seek(-sz, SeekOrigin.Current);
return opcode;
}
private ILOpcode ReadOpcode(Reader r, out int size)
{
if (r.EndOfStream)
{
size = 0;
return ILOpcode.Nop;
}
byte bytecode_b = r.ReadByte();
short bytecode_s = bytecode_b;
size = 1;
if (bytecode_s == 0xFE)
{
bytecode_s = BitConverter.ToInt16(new byte[] { bytecode_b, r.ReadByte() }, 0);
size = 2;
}
return (ILOpcode)bytecode_s;
}
protected override string GetSourceCodeInternal(FieldInfo fi, int indentLevel)
{
StringBuilder sb = new StringBuilder();

View File

@ -0,0 +1,394 @@
//
// ILCodeProvider.cs
//
// Author:
// Michael Becker <alcexhim@gmail.com>
//
// Copyright (c) 2021 Mike Becker's Software
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Reflection;
using UniversalEditor.IO;
namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.CodeProviders
{
public abstract class ILCodeProvider : CodeProvider
{
protected int? OpcodeToLiteralInt(ILOpcode opcode)
{
switch (opcode)
{
case ILOpcode.LdCI4_0:
{
return 0;
}
case ILOpcode.LdCI4_1:
{
return 1;
}
case ILOpcode.LdCI4_2:
{
return 2;
}
case ILOpcode.LdCI4_3:
{
return 3;
}
case ILOpcode.LdCI4_4:
{
return 4;
}
case ILOpcode.LdCI4_5:
{
return 5;
}
case ILOpcode.LdCI4_6:
{
return 6;
}
case ILOpcode.LdCI4_7:
{
return 7;
}
case ILOpcode.LdCI4_8:
{
return 8;
}
case ILOpcode.LdCI4_M1:
{
return -1;
}
}
return null;
}
protected ILOpcode PeekOpcode(Reader r)
{
int sz = 0;
ILOpcode opcode = ReadOpcode(r, out sz);
if (sz == 0)
return opcode;
r.Seek(-sz, SeekOrigin.Current);
return opcode;
}
protected ILOpcode ReadOpcode(Reader r, out int size)
{
if (r.EndOfStream)
{
size = 0;
return ILOpcode.Nop;
}
byte bytecode_b = r.ReadByte();
short bytecode_s = bytecode_b;
size = 1;
if (bytecode_s == 0xFE)
{
bytecode_s = BitConverter.ToInt16(new byte[] { bytecode_b, r.ReadByte() }, 0);
size = 2;
}
return (ILOpcode)bytecode_s;
}
private static BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
public MethodInfo[] GetMethods(Type type)
{
MethodInfo[] meths = type.GetMethods(bindingFlags);
List<MethodInfo> list = new List<MethodInfo>();
for (int j = 0; j < meths.Length; j++)
{
if (meths[j].IsSpecialName && (meths[j].Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase) || meths[j].Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase)) && (type.GetProperty(meths[j].Name.Substring(4), bindingFlags) != null))
{
// we can be REASONABLY sure that this is a property setter / getter,
// and as we've already gotten all the properties, ignore it
continue;
}
list.Add(meths[j]);
}
return list.ToArray();
}
public FieldInfo[] GetFields(Type type, out List<string> AutoPropertyNames)
{
List<FieldInfo> list = new List<FieldInfo>();
AutoPropertyNames = new List<string>();
FieldInfo[] fields = type.GetFields(bindingFlags);
for (int j = 0; j < fields.Length; j++)
{
if (fields[j].Name.StartsWith("<", StringComparison.OrdinalIgnoreCase) && fields[j].Name.Contains(">"))
{
// might be a backing field
int k__backingfield_name_start = fields[j].Name.IndexOf('<');
int k__backingfield_name_end = fields[j].Name.IndexOf('>', k__backingfield_name_start);
string k__backingfield_name = fields[j].Name.Substring(k__backingfield_name_start + 1, k__backingfield_name_end - k__backingfield_name_start - 1);
PropertyInfo pi = type.GetProperty(k__backingfield_name, bindingFlags);
if (pi != null)
{
AutoPropertyNames.Add(pi.Name);
continue;
}
}
else
{
list.Add(fields[j]);
}
}
return list.ToArray();
}
public string GetILOpcodeStr(short opcode)
{
return GetILOpcodeStr((ILOpcode)opcode);
}
public string GetILOpcodeStr(ILOpcode opcode)
{
switch (opcode)
{
case ILOpcode.Add: return "add";
case ILOpcode.AddOvf: return "add.ovf";
case ILOpcode.AddOvfUn: return "add.ovf.un";
case ILOpcode.And: return "and";
case ILOpcode.ArgList: return "arglist";
case ILOpcode.Beq: return "beq <int32 (target)>";
case ILOpcode.BeqS: return "beq <int32 (target)>";
case ILOpcode.Bge: return "bge <int32 (target)>";
case ILOpcode.BgeS: return "bge.s <int8 (target)>";
case ILOpcode.BgeUn: return "bge.un <int32 (target)>";
case ILOpcode.BgeUnS: return "bge.un.s <int8 (target)>";
case ILOpcode.Bgt: return "bgt <int32 (target)>";
case ILOpcode.BgtS: return "bgt.s <int8 (target)>";
case ILOpcode.BgtUn: return "bgt.un <int32 (target)>";
case ILOpcode.BgtUnS: return "bgt.un.s <int8 (target)>";
case ILOpcode.Ble: return "ble <int32 (target)>";
case ILOpcode.BleS: return "ble.s <int8 (target)>";
case ILOpcode.BleUn: return "ble.un <int32 (target)>";
case ILOpcode.BleUnS: return "ble.un.s <int8 (target)>";
case ILOpcode.Blt: return "blt <int32 (target)>";
case ILOpcode.BltS: return "blt.s <int8 (target)>";
case ILOpcode.BltUn: return "blt.un <int32 (target)>";
case ILOpcode.BltUnS: return "blt.un.s <int8 (target)>";
case ILOpcode.BneUn: return "bne.un <int32 (target)>";
case ILOpcode.BneUnS: return "bne.un.s <int8 (target)>";
case ILOpcode.Box: return "box <typeTok>";
case ILOpcode.Br: return "br <int32 (target)>";
case ILOpcode.BrS: return "br.s <int8 (target)>";
case ILOpcode.Break: return "break";
case ILOpcode.BrFalse: return "brfalse <int32 (target)>";
case ILOpcode.BrFalseS: return "brfalse.s <int8 (target)>";
case ILOpcode.BrTrue: return "brtrue <int32 (target)>";
case ILOpcode.BrTrueS: return "brtrue.s <int8 (target)>";
case ILOpcode.Call: return "call <method>";
case ILOpcode.CallI: return "calli <callsitedescr>";
case ILOpcode.CallVirt: return "callvirt <method>";
case ILOpcode.CastClass: return "castclass <class>";
case ILOpcode.Ceq: return "ceq";
case ILOpcode.Cgt: return "cgt";
case ILOpcode.CgtUn: return "cgt.un";
case ILOpcode.CkFinite: return "ckfinite";
case ILOpcode.Clt: return "clt";
case ILOpcode.CltUn: return "clt.un";
case ILOpcode.Constrained: return "constrained <thisType>";
case ILOpcode.ConvI: return "conv.i";
case ILOpcode.ConvI1: return "conv.i1";
case ILOpcode.ConvI2: return "conv.i2";
case ILOpcode.ConvI4: return "conv.i4";
case ILOpcode.ConvI8: return "conv.i8";
case ILOpcode.ConvOvfI: return "conv.ovf.i";
case ILOpcode.ConvOvfIUn: return "conv.ovf.i.un";
case ILOpcode.ConvOvfI1: return "conv.ovf.i1";
case ILOpcode.ConvOvfI1Un: return "conv.ovf.i1.un";
case ILOpcode.ConvOvfI2: return "conv.ovf.i2";
case ILOpcode.ConvOvfI2Un: return "conv.ovf.i2.un";
case ILOpcode.ConvOvfI4: return "conv.ovf.i4";
case ILOpcode.ConvOvfI4Un: return "conv.ovf.i4.un";
case ILOpcode.ConvOvfI8: return "conv.ovf.i8";
case ILOpcode.ConvOvfI8Un: return "conv.ovf.i8.un";
case ILOpcode.ConvOvfU: return "conv.ovf.u";
case ILOpcode.ConvOvfUUn: return "conv.ovf.u.un";
case ILOpcode.ConvOvfU1: return "conv.ovf.u1";
case ILOpcode.ConvOvfU1Un: return "conv.ovf.u1.un";
case ILOpcode.ConvOvfU2: return "conv.ovf.u2";
case ILOpcode.ConvOvfU2Un: return "conv.ovf.u2.un";
case ILOpcode.ConvOvfU4: return "conv.ovf.u4";
case ILOpcode.ConvOvfU4Un: return "conv.ovf.u4.un";
case ILOpcode.ConvOvfU8: return "conv.ovf.u8";
case ILOpcode.ConvOvfU8Un: return "conv.ovf.u8.un";
case ILOpcode.ConvRUn: return "conv.r.un";
case ILOpcode.ConvR4: return "conv.r4";
case ILOpcode.ConvR8: return "conv.r8";
case ILOpcode.ConvU: return "conv.u";
case ILOpcode.ConvU1: return "conv.u1";
case ILOpcode.ConvU2: return "conv.u2";
case ILOpcode.ConvU4: return "conv.u4";
case ILOpcode.ConvU8: return "conv.u8";
case ILOpcode.CpBlk: return "cpblk";
case ILOpcode.CpObj: return "cpobj <typeTok>";
case ILOpcode.Div: return "div";
case ILOpcode.DivUn: return "div.un";
case ILOpcode.Dup: return "dup";
case ILOpcode.EndFault: return "endfault";
case ILOpcode.EndFilter: return "endfilter";
// case ILOpcode.EndFinally: return "endfinally"; // same as endfault?
case ILOpcode.InitBlk: return "initblk";
case ILOpcode.InitObj: return "initobj <typeTok>";
case ILOpcode.IsInst: return "isinst <class>";
case ILOpcode.Jmp: return "jmp";
case ILOpcode.LdArg: return "ldarg <uint16 (num)>";
case ILOpcode.LdArg0: return "ldarg.0";
case ILOpcode.LdArg1: return "ldarg.1";
case ILOpcode.LdArg2: return "ldarg.2";
case ILOpcode.LdArg3: return "ldarg.3";
case ILOpcode.LdArgS: return "ldarg.s <uint8 (num)>";
case ILOpcode.LdArgA: return "ldarg.a <uint16 (num)>";
case ILOpcode.LdArgAS: return "ldarg.a.s <uint8 (num)>";
case ILOpcode.LdCI4: return "ldc.i4 <int32 (num)>";
case ILOpcode.LdCI4_M1: return "ldc.i4.m1";
case ILOpcode.LdCI4_0: return "ldc.i4.0";
case ILOpcode.LdCI4_1: return "ldc.i4.1";
case ILOpcode.LdCI4_2: return "ldc.i4.2";
case ILOpcode.LdCI4_3: return "ldc.i4.3";
case ILOpcode.LdCI4_4: return "ldc.i4.4";
case ILOpcode.LdCI4_5: return "ldc.i4.5";
case ILOpcode.LdCI4_6: return "ldc.i4.6";
case ILOpcode.LdCI4_7: return "ldc.i4.7";
case ILOpcode.LdCI4_8: return "ldc.i4.8";
case ILOpcode.LdCI4S: return "ldc.i4.s <int8 (num)>";
case ILOpcode.LdCI8: return "ldc.i8 <int64 (num)>";
case ILOpcode.LdCR4: return "ldc.r4 <float32 (num)>";
case ILOpcode.LdCR8: return "ldc.r8 <float64 (num)>";
case ILOpcode.LdElem: return "ldelem <typeTok>";
case ILOpcode.LdElemI: return "ldelem.i";
case ILOpcode.LdElemI1: return "ldelem.i1";
case ILOpcode.LdElemU1: return "ldelem.u1";
case ILOpcode.LdElemI2: return "ldelem.i2";
case ILOpcode.LdElemU2: return "ldelem.u2";
case ILOpcode.LdElemI4: return "ldelem.i4";
case ILOpcode.LdElemU4: return "ldelem.u4";
case ILOpcode.LdElemI8: return "ldelem.i8";
case ILOpcode.LdElemR4: return "ldelem.r4";
case ILOpcode.LdElemR8: return "ldelem.r8";
case ILOpcode.LdElemRef: return "ldelem.ref";
case ILOpcode.LdElemA: return "ldelema <class>";
case ILOpcode.LdFld: return "ldfld <field>";
case ILOpcode.LdFldA: return "ldflda <field>";
case ILOpcode.LdFtn: return "ldftn <method>";
case ILOpcode.LdIndI: return "ldind.i";
case ILOpcode.LdIndI1: return "ldind.i1";
case ILOpcode.LdIndU1: return "ldind.u1";
case ILOpcode.LdIndI2: return "ldind.i2";
case ILOpcode.LdIndU2: return "ldind.u2";
case ILOpcode.LdIndI4: return "ldind.i4";
case ILOpcode.LdIndU4: return "ldind.u4";
case ILOpcode.LdIndI8: return "ldind.i8";
case ILOpcode.LdIndR4: return "ldind.r4";
case ILOpcode.LdIndR8: return "ldind.r8";
case ILOpcode.LdLen: return "ldlen";
case ILOpcode.LdLoc: return "ldloc <uint16 (indx)>";
case ILOpcode.LdLoc0: return "ldloc.0";
case ILOpcode.LdLoc1: return "ldloc.1";
case ILOpcode.LdLoc2: return "ldloc.2";
case ILOpcode.LdLoc3: return "ldloc.3";
case ILOpcode.LdLocS: return "ldloc.s <uint8 (indx)>";
case ILOpcode.LdLocA: return "ldloca <uint16 (indx)>";
case ILOpcode.LdLocAS: return "ldloca.s <uint8 (indx)>";
case ILOpcode.LdNull: return "ldnull";
case ILOpcode.LdObj: return "ldobj <typeTok>";
case ILOpcode.LdSFld: return "ldsfld <field>";
case ILOpcode.LdSFldA: return "ldsflda <field>";
case ILOpcode.LdStr: return "ldstr <string>";
case ILOpcode.LdToken: return "ldtoken <token>";
case ILOpcode.LdVirtFtn: return "ldvirtftn <method>";
case ILOpcode.Leave: return "leave <int32 (target)>";
case ILOpcode.LeaveS: return "leave <int8 (target)>";
case ILOpcode.LocAlloc: return "localloc";
case ILOpcode.MkRefAny: return "mkrefany <class>";
case ILOpcode.Mul: return "mul";
case ILOpcode.MulOvf: return "mul.ovf";
case ILOpcode.MulOvfUn: return "mul.ovf.un";
case ILOpcode.Neg: return "neg";
case ILOpcode.NewArr: return "newarr <etype>";
case ILOpcode.NewObj: return "newobj <ctor>";
case ILOpcode.No: return "no.{typecheck, rangecheck, nullcheck}";
case ILOpcode.Nop: return "nop";
case ILOpcode.Not: return "not";
case ILOpcode.Or: return "or";
case ILOpcode.Pop: return "pop";
case ILOpcode.Readonly: return "readonly.";
case ILOpcode.RefAnyType: return "refanytype";
case ILOpcode.RefAnyVal: return "refanyval <type>";
case ILOpcode.Rem: return "rem";
case ILOpcode.RemUn: return "rem.un";
case ILOpcode.Ret: return "ret";
case ILOpcode.Rethrow: return "rethrow";
case ILOpcode.Shl: return "shl";
case ILOpcode.Shr: return "shl";
case ILOpcode.ShrUn: return "shl";
case ILOpcode.SizeOf: return "sizeof <typeTok>";
case ILOpcode.StArg: return "starg <uint16 (num)>";
case ILOpcode.StArgS: return "starg.s <uint8 (num)>";
case ILOpcode.StElem: return "stelem <typeTok>";
case ILOpcode.StElemI: return "stelem.i";
case ILOpcode.StElemI1: return "stelem.i1";
case ILOpcode.StElemI2: return "stelem.i2";
case ILOpcode.StElemI4: return "stelem.i4";
case ILOpcode.StElemI8: return "stelem.i8";
case ILOpcode.StElemR4: return "stelem.r4";
case ILOpcode.StElemR8: return "stelem.r8";
case ILOpcode.StElemRef: return "stelem.ref";
case ILOpcode.StFld: return "stfld <field>";
case ILOpcode.StIndI: return "stind.i";
case ILOpcode.StIndI1: return "stind.i1";
case ILOpcode.StIndI2: return "stind.i2";
case ILOpcode.StIndI4: return "stind.i4";
case ILOpcode.StIndI8: return "stind.i8";
case ILOpcode.StIndR4: return "stind.r4";
case ILOpcode.StIndR8: return "stind.r8";
case ILOpcode.StIndRef: return "stind.ref";
case ILOpcode.StLoc: return "stloc <uint16 (indx)>";
case ILOpcode.StLoc0: return "stloc.0";
case ILOpcode.StLoc1: return "stloc.1";
case ILOpcode.StLoc2: return "stloc.2";
case ILOpcode.StLoc3: return "stloc.3";
case ILOpcode.StLocS: return "stloc.s <uint8 (indx)>";
case ILOpcode.StObj: return "stobj <typeTok>";
case ILOpcode.StSFld: return "stsfld <field>";
case ILOpcode.Sub: return "sub";
case ILOpcode.SubOvf: return "sub.ovf";
case ILOpcode.SubOvfUn: return "sub.ovf.un";
case ILOpcode.Switch: return "switch <uint32, int32, int32 (t1..tN)>";
case ILOpcode.Tail: return "tail.";
case ILOpcode.Throw: return "throw";
case ILOpcode.Unaligned: return "unaligned.(alignment)";
case ILOpcode.Unbox: return "unbox <typeTok>";
case ILOpcode.UnboxAny: return "unbox.any <typeTok>";
case ILOpcode.Volatile: return "volatile.";
case ILOpcode.Xor: return "xor";
}
return "<OPCODE:" + ((short)opcode).ToString("X").PadLeft(2, '0') + ">";
}
public string GetVariableName(MethodInfo mi, LocalVariableInfo localVariableInfo)
{
// TODO: read the PDB file (if exists) to get the local variable info
return "local_" + localVariableInfo.LocalIndex.ToString();
}
}
}

View File

@ -22,13 +22,15 @@
using System;
using System.Reflection;
using System.Text;
using UniversalEditor.Accessors;
using UniversalEditor.IO;
namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.CodeProviders
{
/// <summary>
/// Provides a <see cref="CodeProvider" /> that translates MSIL code into VB.NET.
/// </summary>
public class VisualBasicCodeProvider : CodeProvider
public class VisualBasicCodeProvider : ILCodeProvider
{
public override string Title => "VB.NET";
public override string CodeFileExtension => ".vb";
@ -185,7 +187,62 @@ namespace UniversalEditor.Plugins.Executable.UserInterface.Editors.Executable.Co
}
protected override string GetSourceCodeInternal(MethodInfo mi, int indentLevel)
{
throw new NotImplementedException();
StringBuilder sb = new StringBuilder();
string indentStr = new string('\t', indentLevel);
sb.Append(indentStr);
sb.Append(GetMethodSignature(mi));
MethodBody mb = mi.GetMethodBody();
if (mb != null)
{
sb.AppendLine();
sb.Append(GetBeginBlock(mi, indentLevel));
sb.AppendLine();
for (int i = 0; i < mb.LocalVariables.Count; i++)
{
sb.Append(new string('\t', indentLevel + 1));
sb.Append("Dim ");
sb.Append(GetVariableName(mi, mb.LocalVariables[i]));
sb.Append(" As ");
sb.Append(GetTypeName(mb.LocalVariables[i].LocalType));
sb.AppendLine();
}
if (mb.LocalVariables.Count > 0)
sb.AppendLine();
byte[] bytecode = mb.GetILAsByteArray();
MemoryAccessor ma = new MemoryAccessor(bytecode);
Reader r = new Reader(ma);
while (!r.EndOfStream)
{
int sz = 0;
ILOpcode opcode = ReadOpcode(r, out sz);
ILOpcode opcode2 = PeekOpcode(r);
sb.Append(new string('\t', indentLevel + 1));
if (opcode2 == ILOpcode.NewArr)
{
int? lit = OpcodeToLiteralInt(opcode);
sb.Append(String.Format("Dim X As **TYPE**() = New X({0})", lit.GetValueOrDefault(0)));
}
else
{
sb.AppendLine(GetILOpcodeStr(opcode));
continue;
}
}
sb.Append(GetEndBlock(mi, indentLevel));
}
else
{
sb.Append(';');
}
return sb.ToString();
}
protected override string GetMethodSignatureInternal(MethodInfo mi)

View File

@ -37,6 +37,7 @@
<Compile Include="Editors\Executable\ILOpcode.cs" />
<Compile Include="Editors\Executable\NonLayout\ExecutableEditor.cs" />
<Compile Include="Editors\Executable\NonLayout\ManagedAssemblyPanel.cs" />
<Compile Include="Editors\Executable\CodeProviders\ILCodeProvider.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Editors\" />