From c915a9f990af22aaec07edac54a33e0bf49c28ef Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 9 Jan 2024 17:04:29 +0000 Subject: [PATCH] Add experimental NativeAOT-LLVM support --- crates/bindings-csharp/Codegen/Module.cs | 31 ++++++++++++++---- crates/bindings-csharp/Runtime/Module.cs | 2 -- crates/bindings-csharp/Runtime/RawBindings.cs | 8 ++++- crates/bindings-csharp/Runtime/bindings.c | 9 ++++-- .../Runtime/build/SpacetimeDB.Runtime.props | 18 ++++++++++- .../Runtime/build/SpacetimeDB.Runtime.targets | 32 +++++++++++++++++-- .../project/csharp/StdbModule._csproj | 2 -- crates/cli/src/tasks/csharp.rs | 7 +++- .../StdbModule.csproj | 2 -- modules/sdk-test-cs/StdbModule.csproj | 2 -- .../StdbModule.csproj | 1 - 11 files changed, 90 insertions(+), 24 deletions(-) diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 769e1ebed4..ba8b2da6fe 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -286,26 +286,43 @@ class {r.Name}: IReducer {{ // #nullable enable + using static SpacetimeDB.RawBindings; using SpacetimeDB.Module; using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; using static SpacetimeDB.Runtime; using System.Diagnostics.CodeAnalysis; static class ModuleRegistration {{ {string.Join("\n", addReducers.Select(r => r.Class))} -#pragma warning disable CA2255 - // [ModuleInitializer] - doesn't work because assemblies are loaded lazily; - // might make use of it later down the line, but for now assume there is only one - // module so we can use `Main` instead. - +#if EXPERIMENTAL_WASM_AOT + // In AOT mode we're building a library. + // Main method won't be called automatically, so we need to export it as a preinit function. + [UnmanagedCallersOnly(EntryPoint = ""__preinit__10_init_csharp"")] +#else // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. - [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(SpacetimeDB.Module.FFI))] + [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(FFI))] +#endif public static void Main() {{ {string.Join("\n", addReducers.Select(r => $"FFI.RegisterReducer(new {r.Name}());"))} {string.Join("\n", tableNames.Select(t => $"FFI.RegisterTable({t}.MakeTableDesc());"))} }} -#pragma warning restore CA2255 + +// Exports only work from the main assembly, so we need to generate forwarding methods. +#if EXPERIMENTAL_WASM_AOT + [UnmanagedCallersOnly(EntryPoint = ""__describe_module__"")] + public static Buffer __describe_module__() => FFI.__describe_module__(); + + [UnmanagedCallersOnly(EntryPoint = ""__call_reducer__"")] + public static Buffer __call_reducer__( + uint id, + Buffer caller_identity, + Buffer caller_address, + ulong timestamp, + Buffer args + ) => FFI.__call_reducer__(id, caller_identity, caller_address, timestamp, args); +#endif }} " ); diff --git a/crates/bindings-csharp/Runtime/Module.cs b/crates/bindings-csharp/Runtime/Module.cs index 7dc4fcb460..d4897e8af3 100644 --- a/crates/bindings-csharp/Runtime/Module.cs +++ b/crates/bindings-csharp/Runtime/Module.cs @@ -276,7 +276,6 @@ public static void RegisterReducer(IReducer reducer) bool anonymous = false ) => module.SetTypeRef(typeRef, type, anonymous); - // [UnmanagedCallersOnly(EntryPoint = "__describe_module__")] public static RawBindings.Buffer __describe_module__() { // replace `module` with a temporary internal module that will register ModuleDef, AlgebraicType and other internal types @@ -308,7 +307,6 @@ private static byte[] Consume(this RawBindings.Buffer buffer) return result; } - // [UnmanagedCallersOnly(EntryPoint = "__call_reducer__")] public static RawBindings.Buffer __call_reducer__( uint id, RawBindings.Buffer caller_identity, diff --git a/crates/bindings-csharp/Runtime/RawBindings.cs b/crates/bindings-csharp/Runtime/RawBindings.cs index 113566934e..07b58d9445 100644 --- a/crates/bindings-csharp/Runtime/RawBindings.cs +++ b/crates/bindings-csharp/Runtime/RawBindings.cs @@ -12,7 +12,13 @@ public static partial class RawBindings // For now this must match the name of the `.c` file (`bindings.c`). // In the future C# will allow to specify Wasm import namespace in // `LibraryImport` directly. - const string StdbNamespace = "bindings"; + const string StdbNamespace = +#if EXPERIMENTAL_WASM_AOT + "spacetime_7.0" +#else + "bindings" +#endif + ; // This custom marshaller takes care of checking the status code // returned from the host and throwing an exception if it's not 0. diff --git a/crates/bindings-csharp/Runtime/bindings.c b/crates/bindings-csharp/Runtime/bindings.c index 368c723502..5aae9f9f53 100644 --- a/crates/bindings-csharp/Runtime/bindings.c +++ b/crates/bindings-csharp/Runtime/bindings.c @@ -1,3 +1,4 @@ +#ifndef EXPERIMENTAL_WASM_AOT #include // #include // #include @@ -111,6 +112,7 @@ EXPORT(Buffer, __call_reducer__, (uint32_t id, Buffer caller_identity, Buffer caller_address, uint64_t timestamp, Buffer args), &id, &caller_identity, &caller_address, ×tamp, &args); +#endif // Shims to avoid dependency on WASI in the generated Wasm file. @@ -208,9 +210,10 @@ int32_t WASI_NAME(fd_write)(__wasi_fd_t fd, const __wasi_ciovec_t* iovs, // Note: this will produce ugly broken output, but there's not much we can // do about it until we have proper line-buffered WASI writer in the core. // It's better than nothing though. - _console_log_imp((LogLevel){fd == STDERR_FILENO ? /*WARN*/ 1 : /*INFO*/ 2}, - CSTR("wasi"), CSTR(__FILE__), __LINE__, iovs[i].buf, - iovs[i].buf_len); + // _console_log_imp((LogLevel){fd == STDERR_FILENO ? /*WARN*/ 1 : /*INFO*/ + // 2}, + // CSTR("wasi"), CSTR(__FILE__), __LINE__, iovs[i].buf, + // iovs[i].buf_len); *retptr0 += iovs[i].buf_len; } return 0; diff --git a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.props b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.props index 25dda52d70..d9b880e907 100644 --- a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.props +++ b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.props @@ -4,10 +4,26 @@ true full true - false false true false + + Library + Shared + $(DefineConstants);EXPERIMENTAL_WASM_AOT + false + false + spacetime_7.0 + https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json + + + + + Exe + + false + + diff --git a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets index 5a1144449c..a109b1d8af 100644 --- a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets +++ b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets @@ -1,6 +1,33 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_WasmNativeFileForLinking Include="@(NativeFileReference)" /> @@ -9,7 +36,7 @@ - + 20 @@ -22,6 +49,7 @@ https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$(WasiSdkVersion)/wasi-sdk-$(WasiSdkVersion).0$(WasiSdkFilenameSuffix).tar.gz $([System.IO.Path]::Combine($([System.Environment]::GetFolderPath(SpecialFolder.UserProfile)), '.wasi-sdk', "wasi-sdk-$(WasiSdkVersion)")) + $(WasiSdkRoot) $([System.IO.Path]::Combine($(WasiSdkRoot), 'share', 'wasi-sysroot')) $([System.IO.Path]::Combine($(WasiSdkRoot), 'bin', 'clang')) $(WasiClang).exe diff --git a/crates/cli/src/subcommands/project/csharp/StdbModule._csproj b/crates/cli/src/subcommands/project/csharp/StdbModule._csproj index a77d464bc0..eb550105bb 100644 --- a/crates/cli/src/subcommands/project/csharp/StdbModule._csproj +++ b/crates/cli/src/subcommands/project/csharp/StdbModule._csproj @@ -1,8 +1,6 @@ - - Exe net8.0 wasi-wasm enable diff --git a/crates/cli/src/tasks/csharp.rs b/crates/cli/src/tasks/csharp.rs index 76c1271754..7cdd5c411f 100644 --- a/crates/cli/src/tasks/csharp.rs +++ b/crates/cli/src/tasks/csharp.rs @@ -60,7 +60,12 @@ pub(crate) fn build_csharp(project_path: &Path, build_debug: bool) -> anyhow::Re cmd!("dotnet", "publish", "-c", config_name).dir(project_path).run()?; // check if file exists - let mut output_path = project_path.join(format!("bin/{config_name}/net8.0/wasi-wasm/AppBundle/StdbModule.wasm")); + let subdir = if std::env::var_os("EXPERIMENTAL_WASM_AOT").map_or(false, |v| v == "1") { + "publish" + } else { + "AppBundle" + }; + let mut output_path = project_path.join(format!("bin/{config_name}/net8.0/wasi-wasm/{subdir}/StdbModule.wasm")); if !output_path.exists() { // check for the old .NET 7 path for projects that haven't migrated yet output_path = project_path.join(format!("bin/{config_name}/net7.0/StdbModule.wasm")); diff --git a/modules/sdk-test-connect-disconnect-cs/StdbModule.csproj b/modules/sdk-test-connect-disconnect-cs/StdbModule.csproj index 7cf0f29373..c8a53d2a2a 100644 --- a/modules/sdk-test-connect-disconnect-cs/StdbModule.csproj +++ b/modules/sdk-test-connect-disconnect-cs/StdbModule.csproj @@ -1,8 +1,6 @@ - - Exe net8.0 wasi-wasm enable diff --git a/modules/sdk-test-cs/StdbModule.csproj b/modules/sdk-test-cs/StdbModule.csproj index e39f3a5212..1662a04f8e 100644 --- a/modules/sdk-test-cs/StdbModule.csproj +++ b/modules/sdk-test-cs/StdbModule.csproj @@ -1,8 +1,6 @@ - - Exe net8.0 wasi-wasm enable diff --git a/modules/spacetimedb-quickstart-cs/StdbModule.csproj b/modules/spacetimedb-quickstart-cs/StdbModule.csproj index 3939f4d5c3..0d2476bf57 100644 --- a/modules/spacetimedb-quickstart-cs/StdbModule.csproj +++ b/modules/spacetimedb-quickstart-cs/StdbModule.csproj @@ -2,7 +2,6 @@ - Exe net8.0 wasi-wasm enable