From 755f9d4193bd3cd7c3f5a778f3166925caa498ee Mon Sep 17 00:00:00 2001 From: yowl Date: Fri, 31 Aug 2018 03:11:12 -0500 Subject: [PATCH] WASM: Add intrinsic implementation for ByReference ctor and fix the Value getter (#5987) --- .../src/CodeGen/ILToWebAssemblyImporter.cs | 17 +++++++++++++++++ tests/src/Simple/HelloWasm/Program.cs | 16 ++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs index 5dd76b0fe..2701adb4b 100644 --- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs +++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs @@ -1562,6 +1562,23 @@ namespace Internal.IL return true; } break; + case ".ctor": + if (metadataType.IsByReferenceOfT) + { + StackEntry byRefValueParamHolder = _stack.Pop(); + + // Allocate a slot on the shadow stack for the ByReference type + int spillIndex = _spilledExpressions.Count; + SpilledExpressionEntry spillEntry = new SpilledExpressionEntry(StackValueKind.ByRef, "byref" + _currentOffset, metadataType, spillIndex, this); + _spilledExpressions.Add(spillEntry); + LLVMValueRef addrOfValueType = LoadVarAddress(spillIndex, LocalVarKind.Temp, out TypeDesc unused); + var typedAddress = CastIfNecessary(_builder, addrOfValueType, LLVM.PointerType(LLVM.Int32Type(), 0)); + LLVM.BuildStore(_builder, byRefValueParamHolder.ValueForStackKind(StackValueKind.ByRef, _builder, false), typedAddress); + + _stack.Push(spillEntry); + return true; + } + break; } return false; diff --git a/tests/src/Simple/HelloWasm/Program.cs b/tests/src/Simple/HelloWasm/Program.cs index 8b722882c..95563912a 100644 --- a/tests/src/Simple/HelloWasm/Program.cs +++ b/tests/src/Simple/HelloWasm/Program.cs @@ -294,6 +294,22 @@ internal static class Program PrintLine("float comparison: Ok."); } + // Create a ByReference through the ReadOnlySpan ctor and call the ByReference.Value via the indexer. + var span = "123".AsSpan(); + if (span[0] != '1' + || span[1] != '2' + || span[2] != '3') + { + PrintLine("ByReference intrinsics exercise via ReadOnlySpan failed"); + PrintLine(span[0].ToString()); + PrintLine(span[1].ToString()); + PrintLine(span[2].ToString()); + } + else + { + PrintLine("ByReference intrinsics exercise via ReadOnlySpan OK."); + } + // This test should remain last to get other results before stopping the debugger PrintLine("Debugger.Break() test: Ok if debugger is open and breaks."); System.Diagnostics.Debugger.Break();