Added pools, IndexedFishMap, IndexedFishSet, fixed bugs related to FishTable.Remove, added Preview.png, various smaller additions, some refactoring too
This commit is contained in:
@@ -3,9 +3,12 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Cecil.Rocks;
|
||||
using Mono.Collections.Generic;
|
||||
using Verse;
|
||||
using CallSite = Mono.Cecil.CallSite;
|
||||
@@ -334,8 +337,8 @@ public static class CecilExtensions
|
||||
|
||||
public static void ReplaceBodyWith(this ILProcessor ilProcessor, MethodInfo replacement)
|
||||
{
|
||||
var oldBody = ilProcessor.Body;
|
||||
var module = oldBody.Method.Module;
|
||||
var targetBody = ilProcessor.Body;
|
||||
var module = targetBody.Method.Module;
|
||||
|
||||
if (replacement.IsGenericMethod)
|
||||
replacement = replacement.GetGenericMethodDefinition();
|
||||
@@ -348,26 +351,40 @@ public static class CecilExtensions
|
||||
|
||||
var newMethodReference = module.ImportReference(replacement);
|
||||
var newBody = newMethodReference.Resolve().Body;
|
||||
|
||||
newBody.SimplifyMacros();
|
||||
MethodBodyRocks.ComputeOffsets(newBody);
|
||||
|
||||
oldBody.Instructions.Clear();
|
||||
var targetInstructions = targetBody.instructions;
|
||||
targetInstructions.Clear();
|
||||
|
||||
foreach (var instruction in newBody.instructions)
|
||||
{
|
||||
oldBody.Instructions.Add(new(instruction.OpCode, instruction.Operand switch
|
||||
targetInstructions.Add(new(instruction.OpCode, instruction.Operand switch
|
||||
{
|
||||
FieldReference field => module.ImportReference(field, newMethodReference),
|
||||
MethodReference method => module.ImportReference(method, newMethodReference),
|
||||
TypeReference type => module.ImportReference(type, newMethodReference),
|
||||
ParameterReference parameter => targetBody.GetParameter(parameter.Index),
|
||||
_ => instruction.Operand
|
||||
}));
|
||||
}
|
||||
|
||||
MethodBodyRocks.ComputeOffsets(targetBody);
|
||||
|
||||
foreach (var instruction in targetInstructions)
|
||||
{
|
||||
if (instruction.Operand is Instruction operand)
|
||||
instruction.Operand = targetInstructions.First(ti => ti.Offset == operand.Offset);
|
||||
}
|
||||
|
||||
oldBody.Variables.Clear();
|
||||
targetBody.Variables.Clear();
|
||||
foreach (var variable in newBody.Variables)
|
||||
oldBody.Variables.Add(new(module.ImportReference(variable.VariableType, newMethodReference)));
|
||||
targetBody.Variables.Add(new(module.ImportReference(variable.VariableType, newMethodReference)));
|
||||
|
||||
oldBody.MaxStackSize = newBody.MaxStackSize;
|
||||
targetBody.MaxStackSize = newBody.MaxStackSize;
|
||||
|
||||
oldBody.ExceptionHandlers.Clear();
|
||||
targetBody.ExceptionHandlers.Clear();
|
||||
foreach (var exceptionHandler in newBody.ExceptionHandlers)
|
||||
{
|
||||
var handler = new ExceptionHandler(exceptionHandler.HandlerType)
|
||||
@@ -382,10 +399,13 @@ public static class CecilExtensions
|
||||
if (exceptionHandler.CatchType is { } catchType)
|
||||
handler.CatchType = module.ImportReference(catchType, newMethodReference);
|
||||
|
||||
oldBody.ExceptionHandlers.Add(handler);
|
||||
targetBody.ExceptionHandlers.Add(handler);
|
||||
}
|
||||
|
||||
oldBody.Method.ImplAttributes = newBody.Method.ImplAttributes;
|
||||
targetBody.Method.ImplAttributes = newBody.Method.ImplAttributes;
|
||||
|
||||
targetBody.OptimizeMacros();
|
||||
newBody.OptimizeMacros();
|
||||
}
|
||||
|
||||
public static MethodDefinition GetMethod(this ILProcessor ilProcessor) => ilProcessor.Body.Method;
|
||||
@@ -533,6 +553,7 @@ public static class CecilExtensions
|
||||
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
|
||||
$"Argument is of invalid type: {instruction?.GetType().FullName ?? "NULL"}");
|
||||
|
||||
[SuppressMessage("Maintainability", "CA1508")]
|
||||
private static Instruction CreateInstruction(OpCode opCode, object operand)
|
||||
=> operand switch
|
||||
{
|
||||
@@ -554,6 +575,7 @@ public static class CecilExtensions
|
||||
ParameterDefinition parameter => Instruction.Create(opCode, parameter),
|
||||
_ => ThrowHelper.ThrowArgumentException<Instruction>(nameof(operand),
|
||||
// ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract
|
||||
$"Operand for OpCode {opCode} is of invalid type: {operand?.GetType().FullName ?? "NULL"}")
|
||||
$"Operand for OpCode {opCode} is of invalid type: {
|
||||
operand?.GetType().FullName ?? operand?.GetType().Name ?? "NULL"}")
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2022 bradson
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v.2.0.If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
using FisheryLib.Collections;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
namespace FisheryLib.Cecil;
|
||||
|
||||
public static class InstructionExtensions
|
||||
{
|
||||
public static bool LoadsArgument(this Instruction instruction, int index)
|
||||
=> instruction.LoadsArgument() && GetLoadArgumentIndex(instruction) == index;
|
||||
|
||||
public static bool LoadsArgument(this Instruction instruction) => LoadArgumentOpcodes.Contains(instruction.OpCode);
|
||||
|
||||
private static int GetLoadArgumentIndex(Instruction instruction)
|
||||
{
|
||||
var opCode = instruction.OpCode;
|
||||
return opCode == OpCodes.Ldarg_0 ? 0
|
||||
: opCode == OpCodes.Ldarg_1 ? 1
|
||||
: opCode == OpCodes.Ldarg_2 ? 2
|
||||
: opCode == OpCodes.Ldarg_3 ? 3
|
||||
: instruction.Operand is ParameterDefinition parameterDefinition ? parameterDefinition.Index
|
||||
: Convert.Type<object, int>(instruction.Operand);
|
||||
}
|
||||
|
||||
public static readonly FishSet<OpCode> LoadArgumentOpcodes =
|
||||
[
|
||||
OpCodes.Ldarg, OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3, OpCodes.Ldarg_S,
|
||||
OpCodes.Ldarga, OpCodes.Ldarga_S
|
||||
];
|
||||
}
|
||||
@@ -58,6 +58,8 @@ public static class ReflectionExtensions
|
||||
private static T? TryGetNamed<T>(this IList<T> memberInfos, string name, Func<T, string> nameGetter)
|
||||
where T : class
|
||||
{
|
||||
Guard.IsNotNull(memberInfos);
|
||||
|
||||
for (var i = 0; i < memberInfos.Count; i++)
|
||||
{
|
||||
if (nameGetter(memberInfos[i]) == name)
|
||||
@@ -69,6 +71,8 @@ public static class ReflectionExtensions
|
||||
|
||||
public static TypeReference[] GetTypeReferences(this Type[] types, ModuleDefinition module)
|
||||
{
|
||||
Guard.IsNotNull(types);
|
||||
|
||||
var result = new TypeReference[types.Length];
|
||||
for (var i = types.Length; i-- > 0;)
|
||||
result[i] = module.ImportReference(types[i]);
|
||||
@@ -77,8 +81,14 @@ public static class ReflectionExtensions
|
||||
}
|
||||
|
||||
public static bool IsGeneric(this TypeReference type)
|
||||
=> type.ContainsGenericParameter || type.HasGenericParameters || type.IsGenericInstance;
|
||||
{
|
||||
Guard.IsNotNull(type);
|
||||
return type.ContainsGenericParameter || type.HasGenericParameters || type.IsGenericInstance;
|
||||
}
|
||||
|
||||
public static bool IsGeneric(this Type type)
|
||||
=> type.ContainsGenericParameters || type.IsGenericType || type.IsConstructedGenericType;
|
||||
{
|
||||
Guard.IsNotNull(type);
|
||||
return type.ContainsGenericParameters || type.IsGenericType || type.IsConstructedGenericType;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user