diff --git a/1.3/Assemblies/1Fishery.dll b/1.3/Assemblies/1Fishery.dll index a26c4b7..bfc5879 100644 Binary files a/1.3/Assemblies/1Fishery.dll and b/1.3/Assemblies/1Fishery.dll differ diff --git a/1.4/Assemblies/1Fishery.dll b/1.4/Assemblies/1Fishery.dll index 46ac14d..6fbb1f3 100644 Binary files a/1.4/Assemblies/1Fishery.dll and b/1.4/Assemblies/1Fishery.dll differ diff --git a/Source/FisheryLib/Convert.cs b/Source/FisheryLib/Convert.cs index 40c8fe8..fe164e9 100644 --- a/Source/FisheryLib/Convert.cs +++ b/Source/FisheryLib/Convert.cs @@ -9,11 +9,21 @@ using System.Runtime.CompilerServices; namespace FisheryLib; public static class Convert { + [Obsolete("Renamed to Convert.Type for clarity")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe TTo To(TFrom from) where TFrom : IConvertible + => Type(from); + + [Obsolete("Renamed to Convert.Type for clarity")] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe TTo To(TFrom from, IFormatProvider provider) where TFrom : IConvertible + => Type(from, provider); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe TTo Type(TFrom from) where TFrom : IConvertible => FunctionPointers.Convert.To.Default(from, CultureInfo.InvariantCulture); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe TTo To(TFrom from, IFormatProvider provider) where TFrom : IConvertible + public static unsafe TTo Type(TFrom from, IFormatProvider provider) where TFrom : IConvertible => FunctionPointers.Convert.To.Default(from, provider); } \ No newline at end of file diff --git a/Source/FisheryLib/FishTranspiler.cs b/Source/FisheryLib/FishTranspiler.cs index 9c3e999..bb8c282 100644 --- a/Source/FisheryLib/FishTranspiler.cs +++ b/Source/FisheryLib/FishTranspiler.cs @@ -92,13 +92,10 @@ public static class FishTranspiler public CodeInstruction WithLabelsAndBlocks(CodeInstruction instruction) => WithLabels(instruction.labels).WithBlocks(instruction.blocks); - public int GetIndex() => Operand is LocalVariableInfo info ? info.LocalIndex - : Operand is ushort ushortVar ? ushortVar - : Operand is byte byteVar ? byteVar - : Operand is int intVar ? intVar - : OpCode.TryGetIndex() is { } index ? index - : Operand is IConvertible convertible ? convertible.ToInt32(CultureInfo.InvariantCulture) - : Operand as int? ?? ThrowHelper.ThrowArgumentException($"{OpCode} has operand {Operand}. This is not a supported index."); + public int GetIndex() + => OpCode.TryGetIndex() + ?? TryGetIndexFromOperand(Operand) + ?? ThrowHelper.ThrowArgumentException($"{OpCode} has operand {Operand}. This is not a supported index."); public bool LoadsLocalVariable(MethodBase method, Type localType) => OpCode.LoadsLocalVariable() @@ -639,6 +636,21 @@ public static class FishTranspiler /// The index of the local variable public static Container StoreLocalVariable(int index) => new(GetStoreLocalOpCode(index), GetOperandFromIndex(index)); + /// + /// Declares a local variable of the specified type, optionally pinning the object referred + /// to by the variable. Then returns an instruction matching that of StoreLocalVariable. + /// + /// A System.Type object that represents the type of the local variable + /// The ILGenerator used for the instruction stream + /// True to pin the object in memory; otherwise, false + public static Container NewLocalVariable(Type localType, ILGenerator generator, bool pinned = false) + { + Guard.IsNotNull(localType); + Guard.IsNotNull(generator); + + return StoreLocalVariable(generator.DeclareLocal(localType, pinned)); + } + /// /// Pushes a supplied value of type int32 onto the evaluation stack as an int32. /// @@ -886,6 +898,22 @@ public static class FishTranspiler return new(fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fieldInfo); } + [Obsolete("Use FishTranspiler.PropertyGetter instead")] + public static Container CallPropertyGetter(Type type, string name, bool forceNoCallvirt = false) + => PropertyGetter(type, name, forceNoCallvirt); + + [Obsolete("Use FishTranspiler.PropertyGetter instead")] + public static Container CallPropertyGetter(PropertyInfo propertyInfo, bool forceNoCallvirt = false) + => PropertyGetter(propertyInfo, forceNoCallvirt); + + [Obsolete("Use FishTranspiler.PropertySetter instead")] + public static Container CallPropertySetter(Type type, string name, bool forceNoCallvirt = false) + => PropertySetter(type, name, forceNoCallvirt); + + [Obsolete("Use FishTranspiler.PropertySetter instead")] + public static Container CallPropertySetter(PropertyInfo propertyInfo, bool forceNoCallvirt = false) + => PropertySetter(propertyInfo, forceNoCallvirt); + /// /// Calls the property getter indicated by the passed arguments. /// @@ -893,7 +921,7 @@ public static class FishTranspiler /// The name of the property /// force a Call OpCode instead of using Callvirt where appropriate /// No property found for the specified type and name - public static Container CallPropertyGetter(Type type, string name, bool forceNoCallvirt = false) + public static Container PropertyGetter(Type type, string name, bool forceNoCallvirt = false) { Guard.IsNotNull(type); Guard.IsNotNullOrEmpty(name); @@ -910,7 +938,7 @@ public static class FishTranspiler /// The PropertyInfo /// force a Call OpCode instead of using Callvirt where appropriate /// No property getter found for the specified property info - public static Container CallPropertyGetter(PropertyInfo propertyInfo, bool forceNoCallvirt = false) + public static Container PropertyGetter(PropertyInfo propertyInfo, bool forceNoCallvirt = false) { Guard.IsNotNull(propertyInfo); @@ -927,7 +955,7 @@ public static class FishTranspiler /// The name of the property /// force a Call OpCode instead of using Callvirt where appropriate /// No property found with specified type and name - public static Container CallPropertySetter(Type type, string name, bool forceNoCallvirt = false) + public static Container PropertySetter(Type type, string name, bool forceNoCallvirt = false) { Guard.IsNotNull(type); Guard.IsNotNullOrEmpty(name); @@ -944,7 +972,7 @@ public static class FishTranspiler /// The PropertyInfo /// force a Call OpCode instead of using Callvirt where appropriate /// No property setter found for the specified property info - public static Container CallPropertySetter(PropertyInfo propertyInfo, bool forceNoCallvirt = false) + public static Container PropertySetter(PropertyInfo propertyInfo, bool forceNoCallvirt = false) { Guard.IsNotNull(propertyInfo); @@ -1748,12 +1776,9 @@ public static class FishTranspiler { if (previousCode is not null && predicate(previousCode) && code.IsStloc() && code.opcode is var opcode) { - yield return opcode.TryGetIndex() as object - ?? (code.operand is LocalBuilder builder ? builder - : code.operand is byte index ? index - : code.operand is ushort unsigned ? unsigned - : ushort.TryParse(code.operand?.ToString(), out var parsedNumber) ? parsedNumber - : ThrowHelper.ThrowNotSupportedException($"{code.opcode} returned {code.operand?.ToString() ?? "null"}.")); + yield return opcode.TryGetIndex() + ?? TryGetIndexFromOperand(code.operand) + ?? ThrowHelper.ThrowNotSupportedException($"{code.opcode} returned {code.operand?.ToString() ?? "null"}."); } previousCode = code; } @@ -1765,7 +1790,7 @@ public static class FishTranspiler Guard.IsNotNull(predicate); foreach (var operand in GetLocalOperandsOrIndices(codes, predicate)) - yield return operand is LocalBuilder builder ? builder.LocalIndex : (int)operand; + yield return (int)operand; } public static IEnumerable GetLocalIndices(MethodBase method, Predicate predicate) @@ -2332,8 +2357,21 @@ public static class FishTranspiler public static IList GetLocalVariables(this MethodBase method) => method.GetMethodBody().LocalVariables; + public static int? TryGetIndexFromOperand(object? obj) + => obj is LocalVariableInfo info ? info.LocalIndex + : obj is byte @byte ? @byte + : obj is ushort @ushort ? @ushort + : obj is int @int ? @int + : obj is not string and IConvertible convertible ? convertible.ToInt32(CultureInfo.InvariantCulture) + : int.TryParse(obj?.ToString(), out var parsedNumber) ? parsedNumber + : null; + public static bool CompareOperands(object? lhs, object? rhs) - => (lhs is LocalVariableInfo lhInfo ? lhInfo.LocalIndex : lhs) == (rhs is LocalVariableInfo rhInfo ? rhInfo.LocalIndex : rhs); + => TryGetIndexFromOperand(lhs) is int lhIndex && TryGetIndexFromOperand(rhs) is int rhIndex + ? lhIndex == rhIndex + : lhs is null + ? rhs is null + : lhs.Equals(rhs); public static void Emit(this ILGenerator generator, Container fishTranspiler) { diff --git a/Source/FisheryLib/Fishery.cs b/Source/FisheryLib/Fishery.cs index 14adb40..619ada2 100644 --- a/Source/FisheryLib/Fishery.cs +++ b/Source/FisheryLib/Fishery.cs @@ -10,10 +10,12 @@ global using HarmonyLib; global using FisheryLib.Utility.Diagnostics; global using CodeInstructions = System.Collections.Generic.IEnumerable; using System.Security; +using System.Diagnostics; [assembly: AllowPartiallyTrustedCallers] [assembly: SecurityTransparent] [assembly: SecurityRules(SecurityRuleSet.Level2, SkipVerificationInFullTrust = true)] +[assembly: Debuggable(false, false)] /*namespace FisheryLib; public class Fishery : Harmony diff --git a/Source/FisheryLib/Fishery.csproj b/Source/FisheryLib/Fishery.csproj index d59304a..b254e5f 100644 --- a/Source/FisheryLib/Fishery.csproj +++ b/Source/FisheryLib/Fishery.csproj @@ -8,7 +8,6 @@ AnyCPU true false - bradson Copyright (c) 2022 bradson LICENSE diff --git a/Source/FisheryLib/FunctionPointers/Equals.cs b/Source/FisheryLib/FunctionPointers/Equals.cs index 84aae92..b7b4c73 100644 --- a/Source/FisheryLib/FunctionPointers/Equals.cs +++ b/Source/FisheryLib/FunctionPointers/Equals.cs @@ -85,10 +85,10 @@ public static class Equals type.IsValueType ? nameof(Methods.EquatableValueType) : nameof(Methods.EquatableReferenceType)) - .MakeGenericMethod(type)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer() + .MakeGenericMethod(type).GetFunctionPointer() : type.IsNullable(out var genericArgument) && genericArgument.IsAssignableTo(typeof(IEquatable<>), genericArgument) - ? GetMethod(nameof(Methods.Nullable)).MakeGenericMethod(genericArgument)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer() + ? GetMethod(nameof(Methods.Nullable)).MakeGenericMethod(genericArgument).GetFunctionPointer() : GetMethod( type.IsEnum ? Type.GetTypeCode(Enum.GetUnderlyingType(type)) @@ -105,7 +105,7 @@ public static class Equals _ => ThrowHelper.ThrowNotSupportedException() } : nameof(Methods.Object) - ).MakeGenericMethod(type)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer(); + ).MakeGenericMethod(type).GetFunctionPointer(); private static MethodInfo GetMethod(string name) => Array.Find(_equalsMethods, m => m.Name == name); @@ -117,6 +117,4 @@ public static class Equals => m.ReturnType == typeof(bool) && m.GetParameters().Length == 2) .ToArray(); - - //internal delegate bool EqualsDelegate(T x, T y); } \ No newline at end of file diff --git a/Source/FisheryLib/FunctionPointers/EqualsByRef.cs b/Source/FisheryLib/FunctionPointers/EqualsByRef.cs index 700d82f..00d7473 100644 --- a/Source/FisheryLib/FunctionPointers/EqualsByRef.cs +++ b/Source/FisheryLib/FunctionPointers/EqualsByRef.cs @@ -85,10 +85,10 @@ public static class EqualsByRef type.IsValueType ? nameof(Methods.EquatableValueType) : nameof(Methods.EquatableReferenceType)) - .MakeGenericMethod(type)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer() + .MakeGenericMethod(type).GetFunctionPointer() : type.IsNullable(out var genericArgument) && genericArgument.IsAssignableTo(typeof(IEquatable<>), genericArgument) - ? GetMethod(nameof(Methods.Nullable)).MakeGenericMethod(genericArgument)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer() + ? GetMethod(nameof(Methods.Nullable)).MakeGenericMethod(genericArgument).GetFunctionPointer() : GetMethod( type.IsEnum ? Type.GetTypeCode(Enum.GetUnderlyingType(type)) @@ -105,7 +105,7 @@ public static class EqualsByRef _ => ThrowHelper.ThrowNotSupportedException() } : nameof(Methods.Object) - ).MakeGenericMethod(type)/*.CreateDelegate(typeof(EqualsDelegate<>).MakeGenericType(type)).Method*/.GetFunctionPointer(); + ).MakeGenericMethod(type).GetFunctionPointer(); private static MethodInfo GetMethod(string name) => Array.Find(_equalsMethods, m => m.Name == name); @@ -117,6 +117,4 @@ public static class EqualsByRef => m.ReturnType == typeof(bool) && m.GetParameters().Length == 2) .ToArray(); - - //internal delegate bool EqualsDelegate(ref T x, ref T y); } \ No newline at end of file