Skip to content

[NativeAOT-LLVM] Delegates marshalling is broken in some scenarios #2624

@maxkatz6

Description

@maxkatz6

Running SkiaSharp from NativeAOT-LLVM I noticed that it always fails on DllImports with managed delegates.

dotnet.native.js:59 
 Uncaught 
RuntimeError: null function or function signature mismatch
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_ThunkBlocks__GetNewThunksBlock (dotnet.native.wasm:0x1ea0c5)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_ThunksHeap___ctor (dotnet.native.wasm:0x132e2a)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_ThunksHeap__CreateThunksHeap (dotnet.native.wasm:0x1a9576)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_InteropServices_PInvokeMarshal__AllocateThunk (dotnet.native.wasm:0xef0c0)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_CompilerServices_ConditionalWeakTable_2_CreateValueCallback<System___Canon__System___Canon>__InvokeOpenStaticThunk (dotnet.native.wasm:0xef030)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_CompilerServices_ConditionalWeakTable_2<System___Canon__System___Canon>__GetValueLocked (dotnet.native.wasm:0x685ee)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_CompilerServices_ConditionalWeakTable_2<System___Canon__System___Canon>__GetValue (dotnet.native.wasm:0x225430)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_InteropServices_PInvokeMarshal__GetFunctionPointerForDelegate (dotnet.native.wasm:0x15c542)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_InteropServices_Marshal__GetFunctionPointerForDelegate (dotnet.native.wasm:0x127a9e)
    at dotnet.native.wasm.S_P_CoreLib_System_Runtime_InteropServices_Marshal__GetFunctionPointerForDelegate_0<System___Canon> (dotnet.native.wasm:0xe40e5)

And more stacktrace:

$S_P_CoreLib_System_Runtime_ThunkBlocks__GetNewThunksBlock | @ | dotnet.native.wasm:0x1ea0c5
-- | -- | --
  | $S_P_CoreLib_System_Runtime_ThunksHeap___ctor | @ | dotnet.native.wasm:0x132e2a
  | $S_P_CoreLib_System_Runtime_ThunksHeap__CreateThunksHeap | @ | dotnet.native.wasm:0x1a9576
  | $S_P_CoreLib_System_Runtime_InteropServices_PInvokeMarshal__AllocateThunk | @ | dotnet.native.wasm:0xef0c0
  | $S_P_CoreLib_System_Runtime_CompilerServices_ConditionalWeakTable_2_CreateValueCallback<System___Canon__System___Canon>__InvokeOpenStaticThunk | @ | dotnet.native.wasm:0xef030
  | $S_P_CoreLib_System_Runtime_CompilerServices_ConditionalWeakTable_2<System___Canon__System___Canon>__GetValueLocked | @ | dotnet.native.wasm:0x685ee
  | $S_P_CoreLib_System_Runtime_CompilerServices_ConditionalWeakTable_2<System___Canon__System___Canon>__GetValue | @ | dotnet.native.wasm:0x225430
  | $S_P_CoreLib_System_Runtime_InteropServices_PInvokeMarshal__GetFunctionPointerForDelegate | @ | dotnet.native.wasm:0x15c542
  | $S_P_CoreLib_System_Runtime_InteropServices_Marshal__GetFunctionPointerForDelegate | @ | dotnet.native.wasm:0x127a9e
  | $S_P_CoreLib_System_Runtime_InteropServices_Marshal__GetFunctionPointerForDelegate_0<System___Canon> | @ | dotnet.native.wasm:0xe40e5
  | $Internal_CompilerGenerated__Module___<ManagedToNative>SkiaSharp_SkiaSharp_SKManagedStreamDelegates | @ | dotnet.native.wasm:0x153ecf
  | $SkiaSharp_SkiaSharp_SkiaApi__sk_managedstream_set_procs | @ | dotnet.native.wasm:0x118892
  | $SkiaSharp_SkiaSharp_SKAbstractManagedStream___cctor | @ | dotnet.native.wasm:0xd5767
  | $S_P_CoreLib_System_Runtime_CompilerServices_ClassConstructorRunner__EnsureClassConstructorRun | @ | dotnet.native.wasm:0x214632
  | $S_P_CoreLib_System_Runtime_CompilerServices_ClassConstructorRunner__CheckStaticClassConstructionReturnNonGCStaticBase | @ | dotnet.native.wasm:0x967cc
  | $__GetNonGCStaticBase_SkiaSharp_SkiaSharp_SKAbstractManagedStream | @ | dotnet.native.wasm:0x250838
  | $SkiaSharp_SkiaSharp_SKAbstractManagedStream___ctor_0 | @ | dotnet.native.wasm:0x120169
  | $SkiaSharp_SkiaSharp_SKManagedStream___ctor_0 | @ | dotnet.native.wasm:0x1200a5
  | $naot_llvm_demo_Program__Main_d__0__MoveNext | @ | dotnet.native.wasm:0x5c3c3

The same delegates are properly marshalled with plain NativeAOT on desktop, as well as Mono WASM. This issue might be or might not be related to mono/SkiaSharp#1931.

Workaround - rewrite SkiaSharp to use function pointers instead (I am working on it right now).

Minimal repro (only SkiaSharp Bitmap decoding + HttpClient for demo):
naot-llvm-demo.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-NativeAOT-LLVMLLVM generation for Native AOT compilation (including Web Assembly)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions