Files
RobustToolbox/Robust.Shared/Utility/ILGeneratorExt.cs
2022-02-05 19:31:58 +01:00

192 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
namespace Robust.Shared.Utility
{
public static class ILGeneratorExt
{
public static RobustILGenerator GetRobustGen(this DynamicMethod dynamicMethod) =>
new(dynamicMethod.GetILGenerator());
public static RobustILGenerator GetRobustGen(this ILGenerator generator) => new (generator);
}
public sealed class RobustILGenerator
{
private ILGenerator _generator;
private List<(object, object?)> _log = new();
private List<(Type, int)> _locals = new();
public RobustILGenerator(ILGenerator generator)
{
_generator = generator;
}
public string[] GetStringLog()
{
var full = _locals.Select(e => $"LOCAL: {e.Item1} at {e.Item2}").ToList();
full.Add("===== CODE =====");
full.AddRange(_log.Select(e => $"{e.Item1} - {e.Item2}"));
return full.ToArray();
}
private void Log(object opcode, object? arg = null)
{
_log.Add((opcode, arg));
}
public LocalBuilder DeclareLocal(Type localType)
{
return DeclareLocal(localType, false);
}
public LocalBuilder DeclareLocal(Type localType, bool pinned)
{
var loc = _generator.DeclareLocal(localType, pinned);
_locals.Add((localType, loc.LocalIndex));
return loc;
}
public void ThrowException([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type excType)
{
//this just calls emit
_generator.ThrowException(excType);
}
public Label DefineLabel()
{
var label = _generator.DefineLabel();
//Log("DefineLabel", label);
return label;
}
public void MarkLabel(Label loc)
{
_generator.MarkLabel(loc);
Log("MarkLabel", loc.GetHashCode());
}
public void Emit(OpCode opcode)
{
_generator.Emit(opcode);
Log(opcode);
}
public void Emit(OpCode opcode, byte arg)
{
_generator.Emit(opcode, arg);
Log(opcode, arg);
}
public void Emit(OpCode opcode, sbyte arg)
{
_generator.Emit(opcode, arg);
Log(opcode, arg);
}
public void Emit(OpCode opcode, short arg)
{
_generator.Emit(opcode, arg);
Log(opcode, arg);
}
public void Emit(OpCode opcode, int arg)
{
_generator.Emit(opcode, arg);
Log(opcode, arg);
}
public void Emit(OpCode opcode, MethodInfo meth)
{
_generator.Emit(opcode, meth);
Log(opcode, meth);
}
// public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention,
// Type? returnType, Type[]? parameterTypes, Type[]? optionalParameterTypes)
// {
// }
//
// public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes)
// {
// }
//
public void EmitCall(OpCode opcode, MethodInfo methodInfo, params Type[]? optionalParameterTypes)
{
_generator.EmitCall(opcode, methodInfo, optionalParameterTypes);
Log(opcode, methodInfo);
}
public void Emit(OpCode opcode, SignatureHelper signature)
{
_generator.Emit(opcode, signature);
Log(opcode, signature);
}
public void Emit(OpCode opcode, ConstructorInfo con)
{
_generator.Emit(opcode, con);
Log(opcode, con);
}
public void Emit(OpCode opcode, Type cls)
{
_generator.Emit(opcode, cls);
Log(opcode, cls);
}
public void Emit(OpCode opcode, long arg)
{
_generator.Emit(opcode, arg);
Log(opcode, arg);
}
public void Emit(OpCode opcode, float arg)
{
_generator.Emit(opcode, arg);
Log(opcode, arg);
}
public void Emit(OpCode opcode, double arg)
{
_generator.Emit(opcode, arg);
Log(opcode, arg);
}
public void Emit(OpCode opcode, Label label)
{
_generator.Emit(opcode, label);
Log(opcode, label.GetHashCode());
}
public void Emit(OpCode opcode, Label[] labels)
{
_generator.Emit(opcode, labels);
Log(opcode, labels);
}
public void Emit(OpCode opcode, FieldInfo field)
{
_generator.Emit(opcode, field);
Log(opcode, field);
}
public void Emit(OpCode opcode, string str)
{
_generator.Emit(opcode, str);
Log(opcode, str);
}
public void Emit(OpCode opcode, LocalBuilder local)
{
_generator.Emit(opcode, local);
Log(opcode, local);
}
}
}