bflattened / bflat

C# as you know it but with Go-inspired tooling (small, selfcontained, and native executables)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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