diff --git a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Invocation/DefaultInvokers.cs b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Invocation/DefaultInvokers.cs index 4af10418..e22de72c 100644 --- a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Invocation/DefaultInvokers.cs +++ b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Invocation/DefaultInvokers.cs @@ -42,6 +42,11 @@ public static class DefaultInvokers /// Gets the method invoker that steps over any method by invoking it via System.Reflection. /// public static ReflectionInvoker ReflectionInvoke => ReflectionInvoker.Instance; + + /// + /// Gets the default shim for the type. + /// + public static StringInvoker StringShim => StringInvoker.Instance; /// /// Gets the method invoker that forwards any method that is not within the resolution scope of the current diff --git a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Invocation/StringInvoker.cs b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Invocation/StringInvoker.cs new file mode 100644 index 00000000..af93e9e1 --- /dev/null +++ b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Invocation/StringInvoker.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using AsmResolver.DotNet; +using Echo.Memory; +using Echo.Platforms.AsmResolver.Emulation.Dispatch; + +namespace Echo.Platforms.AsmResolver.Emulation.Invocation; + +/// +/// Implements a method invoker that shims methods from the class. +/// +public class StringInvoker : IMethodInvoker +{ + /// + /// Gets the singleton instance of the class. + /// + public static StringInvoker Instance { get; } = new(); + + /// + public InvocationResult Invoke(CilExecutionContext context, IMethodDescriptor method, IList arguments) + { + if ((!method.DeclaringType?.IsTypeOf("System", "String") ?? true) || method.Signature is null) + return InvocationResult.Inconclusive(); + + switch (method.Name?.Value) + { + case "FastAllocateString": + return InvokeFastAllocateString(context, arguments); + + default: + return InvocationResult.Inconclusive(); + } + } + + private static InvocationResult InvokeFastAllocateString(CilExecutionContext context, IList arguments) + { + var length = arguments[0]; + if (!length.IsFullyKnown) + throw new CilEmulatorException("Cannot allocate a string with an unknown length."); + + long address = context.Machine.Heap.AllocateString(length.AsSpan().I32, true); + var result = context.Machine.ValueFactory.RentNativeInteger(address); + + return InvocationResult.StepOver(result); + } +} \ No newline at end of file