Please add this method to `ClassConstructionRunner` to make `ReadOnlySpan` returning methods compile
lucabol opened this issue · comments
In zerolib/System/Runtime/CompilerServices/ClassConstructorRunner.cs
add to class ClassConstructorRunner
the following method to make the compiler happy when returing ReadOnlySpan
from a function. No idea why it is needed, but it works if you add it.
private static unsafe object CheckStaticClassConstructionReturnGCStaticBase(ref StaticClassConstructionContext context, object gcStaticBase)
{
CheckStaticClassConstruction(ref context);
return gcStaticBase;
}
Unfortunately, you have not made that class partial
so it cannot be added from 'the outside' as I am doing elsewhere. Generally, it is extremely useful to mark everything as partial
as you have done almost always, so one doesn't need to modify the code for zerolib
to experiment or fix issues.
btw I would not have thought partial
would end up being so useful when we put it in ... I tought it too primitive ... goes to show my lack of foresight :-)
btw2 let me know if you prefer PRs and I'll try to figure out the github arcana to PR just changes in the zerolib
directory.
I don't think this is about returning a ReadOnlySpan from a function.
This would only be needed if you have a static field that has GC references in it (either a static fields that is a reference type, or a valuetype that contains a reference type field).
Just adding this helper will not fix the issues with that. A lot more is needed to support statics with GC-tracked fields. These are not allocated within the .data segment like normal statics so even if you add this, you'll likely see access violations at runtime.
Yep, I just discover it. It is enough to have a static byte buffer, even if you are not using it to trigger an exception in `RhpAssignRef'. See semi-minimal repo at bottom.
In zerolib
how do you recommend creating the sort of global byte buffers used in system programming? A struct with a fixed byte[]
field? Or malloc
it from the start of main, but then can I store it in a static
field or do I need to pass it on to each function? Anything else?
I shall try a few of those options.
A.B();
class A {
static int i = 0;
static byte[] buffer = new byte[1024];
public static void B() {
int x = i;
Console.WriteLine(x);
}
}
fyi I found an example on how you have done it in the codebase as StdInBuffer
. I wonder if C# 12 inline array attribute would work as well ... I admit I am not sure what the difference would be vs the StdInBuffer
pattern ...
And InlineArray
works (in my one test), but I had to patch the MemoryMarshal
class as it is not partial
.
I am leaving the code here in case you want to add it to zerolib
. Basically you just need to add the attribute and one method to MemoryMarshal
that the compiler wants.
using System.Runtime.CompilerServices;
namespace System.Runtime.CompilerServices
{
public sealed class InlineArrayAttribute : Attribute
{
public InlineArrayAttribute(int size) { }
}
}
namespace System.Runtime.InteropServices
{
public static partial class MemoryMarshal
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static Span<T> CreateSpan<T>(ref T reference, int length) => new Span<T>(Unsafe.AsPointer(ref reference), length);
}
}
Yeah, InlineArray and MemoryMarshal.CreateSpan sound like reasonable additions to zerolib
Superseeded by #181