From cf10cb72389531feeca0130260d8a169b6a54a3b Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 29 Apr 2019 19:20:28 -0400 Subject: [PATCH] [wasm] Add support for pinvokes in user assemblies. (#14253) The --pinvoke-libs=x argument to packager.exe can be used to generate pinvoke linking tables. 'x' is a list of library names used in DllImport declarations, i.e. --pinvoke-libs=libtest is used to link with [DllImport ("libtest")]. --- mcs/tools/wasm-tuner/tuner.cs | 18 +++++++++++++----- sdks/wasm/Makefile | 3 ++- sdks/wasm/driver.c | 4 ++++ sdks/wasm/hello.cs | 1 + sdks/wasm/packager.cs | 20 +++++++++++++++++++- 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/mcs/tools/wasm-tuner/tuner.cs b/mcs/tools/wasm-tuner/tuner.cs index 1069dade2e9..99c1f047941 100644 --- a/mcs/tools/wasm-tuner/tuner.cs +++ b/mcs/tools/wasm-tuner/tuner.cs @@ -118,19 +118,27 @@ public class WasmTuner } } + static string MapType (TypeReference t) { + if (t.Name == "Void") + return "void"; + else if (t.Name == "Double") + return "double"; + else if (t.Name == "Float") + return "float"; + else + return "int"; + } + static string GenPinvokeDecl (Pinvoke pinvoke) { var sb = new StringBuilder (); var method = pinvoke.Method; - if (method.ReturnType.Name != "Void") - sb.Append ("int"); - else - sb.Append ("void"); + sb.Append (MapType (method.ReturnType)); sb.Append ($" {pinvoke.EntryPoint} ("); int pindex = 0; foreach (var p in method.Parameters) { if (pindex > 0) sb.Append (","); - sb.Append ("int"); + sb.Append (MapType (method.Parameters [pindex].ParameterType)); pindex ++; } sb.Append (");"); diff --git a/sdks/wasm/Makefile b/sdks/wasm/Makefile index bce2d18fc3e..04899c6e9f6 100644 --- a/sdks/wasm/Makefile +++ b/sdks/wasm/Makefile @@ -124,6 +124,7 @@ bcl: tuner: $(MAKE) -C ../../mcs/tools/wasm-tuner PROFILE=wasm_tools + cp ../../mcs/class/lib/wasm_tools/wasm-tuner.exe* ../out/wasm-bcl/wasm_tools/wasm-tuner.exe* cil-strip: $(MAKE) -C ../../mcs/tools/cil-strip PROFILE=wasm_tools @@ -194,7 +195,7 @@ $(BROWSER_TEST)/.stamp-browser-test-suite: $(DRIVER_CONF)/.stamp-build packager. touch $@ build-aot-sample: packager.exe hello.exe - mono --debug packager.exe --emscripten-sdkdir=$(EMSCRIPTEN_SDKDIR) --mono-sdkdir=$(TOP)/sdks/out -appdir=bin/aot-sample --nobinding --builddir=obj/aot-sample --aot --template=runtime-tests.js hello.exe + mono --debug packager.exe --emscripten-sdkdir=$(EMSCRIPTEN_SDKDIR) --mono-sdkdir=$(TOP)/sdks/out -appdir=bin/aot-sample --nobinding --builddir=obj/aot-sample --aot --template=runtime-tests.js --pinvoke-libs=libfoo hello.exe ninja -v -C obj/aot-sample hello.exe: hello.cs diff --git a/sdks/wasm/driver.c b/sdks/wasm/driver.c index 459f80210f5..ec3bc302502 100644 --- a/sdks/wasm/driver.c +++ b/sdks/wasm/driver.c @@ -11,7 +11,11 @@ #include #include +#ifdef GEN_PINVOKE +#include "pinvoke-table.h" +#else #include "pinvoke-tables-default.h" +#endif #ifdef CORE_BINDINGS void core_initialize_internals (); diff --git a/sdks/wasm/hello.cs b/sdks/wasm/hello.cs index 3ca0a7bd8f9..6ed67f0f4d8 100644 --- a/sdks/wasm/hello.cs +++ b/sdks/wasm/hello.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; public class HelloWorld { diff --git a/sdks/wasm/packager.cs b/sdks/wasm/packager.cs index 9ade48b017f..8561dae96b3 100644 --- a/sdks/wasm/packager.cs +++ b/sdks/wasm/packager.cs @@ -127,6 +127,7 @@ class Driver { Console.WriteLine ("\t--profile=x Enable the 'x' mono profiler."); Console.WriteLine ("\t--aot-assemblies=x List of assemblies to AOT in AOT+INTERP mode."); Console.WriteLine ("\t--link-mode=sdkonly|all Set the link type used for AOT. (EXPERIMENTAL)"); + Console.WriteLine ("\t--pinvoke-libs=x DllImport libraries used."); Console.WriteLine ("\t\t 'sdkonly' only link the Core libraries."); Console.WriteLine ("\t\t 'all' link Core and User assemblies. (default)"); @@ -348,10 +349,12 @@ class Driver { bool build_wasm = false; bool enable_lto = false; bool link_icalls = false; + bool gen_pinvoke = false; var il_strip = false; var runtimeTemplate = "runtime.js"; var assets = new List (); var profilers = new List (); + var pinvoke_libs = ""; var copyTypeParm = "default"; var copyType = CopyType.Default; var ee_mode = ExecMode.Interp; @@ -388,6 +391,7 @@ class Driver { { "copy=", s => copyTypeParm = s }, { "aot-assemblies=", s => aot_assemblies = s }, { "link-mode=", s => linkModeParm = s }, + { "pinvoke-libs=", s => pinvoke_libs = s }, { "help", s => print_usage = true }, }; @@ -427,6 +431,7 @@ class Driver { use_release_runtime = !opts.DebugRuntime; il_strip = opts.ILStrip; linker_verbose = opts.LinkerVerbose; + gen_pinvoke = pinvoke_libs != ""; if (ee_mode == ExecMode.Aot || ee_mode == ExecMode.AotInterp) enable_aot = true; @@ -437,7 +442,7 @@ class Driver { link_icalls = true; if (!enable_linker || !enable_aot) enable_dedup = false; - if (enable_aot || link_icalls) + if (enable_aot || link_icalls || gen_pinvoke) build_wasm = true; if (!enable_aot && link_icalls) enable_lto = true; @@ -651,6 +656,8 @@ class Driver { string driver_deps = ""; if (link_icalls) driver_deps += "$builddir/icall-table.h"; + if (gen_pinvoke) + driver_deps += "$builddir/pinvoke-table.h"; string emcc_flags = ""; if (enable_lto) emcc_flags += "--llvm-lto 1 "; @@ -711,6 +718,8 @@ class Driver { ninja.WriteLine (" command = $cross --print-icall-table > $out"); ninja.WriteLine ("rule gen-icall-table"); ninja.WriteLine (" command = mono $tools_dir/wasm-tuner.exe --gen-icall-table $runtime_table $in > $out"); + ninja.WriteLine ("rule gen-pinvoke-table"); + ninja.WriteLine (" command = mono $tools_dir/wasm-tuner.exe --gen-pinvoke-table $pinvoke_libs $in > $out"); ninja.WriteLine ("rule ilstrip"); ninja.WriteLine (" command = cp $in $out; mono $tools_dir/mono-cil-strip.exe $out"); ninja.WriteLine (" description = [IL-STRIP]"); @@ -739,6 +748,8 @@ class Driver { ninja.WriteLine ($" flags = -I$mono_sdkdir/wasm-runtime-release/include/mono-2.0"); driver_cflags += " -DCORE_BINDINGS "; } + if (gen_pinvoke) + driver_cflags += " -DGEN_PINVOKE "; ninja.WriteLine ($"build $builddir/driver.o: emcc $builddir/driver.c | $builddir/driver-gen.c {driver_deps}"); ninja.WriteLine ($" flags = {driver_cflags} -DDRIVER_GEN=1 -I$mono_sdkdir/wasm-runtime-release/include/mono-2.0"); @@ -838,6 +849,13 @@ class Driver { ninja.WriteLine ($"build $builddir/icall-table.h: gen-icall-table {icall_assemblies}"); ninja.WriteLine ($" runtime_table=$builddir/icall-table.json"); } + if (gen_pinvoke) { + string pinvoke_assemblies = ""; + foreach (var a in assemblies) + pinvoke_assemblies += $"{a.linkout_path} "; + ninja.WriteLine ($"build $builddir/pinvoke-table.h: gen-pinvoke-table {pinvoke_assemblies}"); + ninja.WriteLine ($" pinvoke_libs=System.Native,{pinvoke_libs}"); + } if (build_wasm) { ninja.WriteLine ($"build $appdir/mono.js: emcc-link $builddir/driver.o {wasm_core_bindings} {ofiles} {profiler_libs} {runtime_libs} $mono_sdkdir/wasm-runtime-release/lib/libmono-native.a | $tool_prefix/library_mono.js $tool_prefix/dotnet_support.js {wasm_core_support}"); } -- 2.11.4.GIT