Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlealtan <blealtan@outlook.com>2018-02-28 06:30:54 +0300
committerMorgan Brown <morganbr@users.noreply.github.com>2018-02-28 06:30:54 +0300
commitbeff0a43b2635ff5acdcb413c037d3ecc97864cb (patch)
tree2a503e5d02457386546fb127b1acee4cb5152b48
parent76899b2aaef6e30297e06ba7043995c1b2336c42 (diff)
Implement intrinsic call to RuntimeHelpers.InitializeArray for WASM (#5377)
* Implement intrinsic call to InitializeArray. RuntimeHelpers.InitializeArray is implemented as a call to LLVM intrinsic llvm.memcpy.p0i8.p0i8.i32, which copies from generated global constant to provided target array. Currently the base size of the array object is hardcoded to 8, since no EEType is provided in the intrinsic call. Fix #5345. Add testing code for InitializeArray in HelloWasm. Roslyn generates RuntimeHelpers.InitializeArray for arrays of integral types with initializer of length greater or equal than 3. Here we use this feature to generate a call to RuntimeHelpers.InitializeArray for test. Catagorize array argument types in InitializeArray Differently handle vectors, multidimensional arrays and object typed arrays in InitializeArray intrinsic.
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs57
-rw-r--r--tests/src/Simple/HelloWasm/Program.cs8
2 files changed, 65 insertions, 0 deletions
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
index 037140bb6..8b0936d1e 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
@@ -1062,6 +1062,63 @@ namespace Internal.IL
switch (method.Name)
{
+ case "InitializeArray":
+ if (metadataType.Namespace == "System.Runtime.CompilerServices" && metadataType.Name == "RuntimeHelpers")
+ {
+ StackEntry fieldSlot = _stack.Pop();
+ StackEntry arraySlot = _stack.Pop();
+
+ // TODO: Does fldHandle always come from ldtoken? If not, what to do with other cases?
+ if (!(fieldSlot is LdTokenEntry<FieldDesc> checkedFieldSlot) ||
+ !(_compilation.GetFieldRvaData(checkedFieldSlot.LdToken) is BlobNode fieldNode))
+ throw new InvalidProgramException("Provided field handle is invalid.");
+
+ LLVMValueRef src = LoadAddressOfSymbolNode(fieldNode);
+ _dependencies.Add(fieldNode);
+ int srcLength = fieldNode.GetData(_compilation.NodeFactory, false).Data.Length;
+
+ if (arraySlot.Type.IsSzArray)
+ {
+ // Handle single dimensional arrays (vectors).
+ LLVMValueRef arrayObjPtr = arraySlot.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder);
+
+ var argsType = new LLVMTypeRef[]
+ {
+ LLVM.PointerType(LLVM.Int8Type(), 0),
+ LLVM.PointerType(LLVM.Int8Type(), 0),
+ LLVM.Int32Type(),
+ LLVM.Int32Type(),
+ LLVM.Int1Type()
+ };
+ LLVMValueRef memcpyFunction = GetOrCreateLLVMFunction("llvm.memcpy.p0i8.p0i8.i32", LLVM.FunctionType(LLVM.VoidType(), argsType, false));
+
+ var args = new LLVMValueRef[]
+ {
+ LLVM.BuildGEP(_builder, arrayObjPtr, new LLVMValueRef[] { ArrayBaseSize() }, string.Empty),
+ LLVM.BuildBitCast(_builder, src, LLVM.PointerType(LLVM.Int8Type(), 0), string.Empty),
+ BuildConstInt32(srcLength), // TODO: Handle destination array length to avoid runtime overflow.
+ BuildConstInt32(0), // Assume no alignment
+ BuildConstInt1(0)
+ };
+ LLVM.BuildCall(_builder, memcpyFunction, args, string.Empty);
+ }
+ else if (arraySlot.Type.IsMdArray)
+ {
+ // Handle multidimensional arrays.
+ // TODO: Add support for multidimensional array.
+ throw new NotImplementedException();
+ }
+ else
+ {
+ // Handle object-typed first argument. This include System.Array typed array, and any ill-typed argument.
+ // TODO: Emit runtime type check code on array argument and further memcpy.
+ // TODO: Maybe a new runtime interface for this is better than hand-written code emission?
+ throw new NotImplementedException();
+ }
+
+ return true;
+ }
+ break;
case "get_Value":
if (metadataType.IsByReferenceOfT)
{
diff --git a/tests/src/Simple/HelloWasm/Program.cs b/tests/src/Simple/HelloWasm/Program.cs
index 812101795..75864c2e0 100644
--- a/tests/src/Simple/HelloWasm/Program.cs
+++ b/tests/src/Simple/HelloWasm/Program.cs
@@ -210,6 +210,14 @@ internal static class Program
System.Diagnostics.Debugger.Break();
+ var testRuntimeHelpersInitArray = new long[] {1, 2, 3};
+ if(testRuntimeHelpersInitArray[0] == 1 &&
+ testRuntimeHelpersInitArray[1] == 2 &&
+ testRuntimeHelpersInitArray[2] == 3)
+ {
+ PrintLine("Runtime.Helpers array initialization test: Ok.");
+ }
+
PrintLine("Done");
}