diff options
author | Jeff Greene <hippiehunterenator@gmail.com> | 2017-11-06 11:23:49 +0300 |
---|---|---|
committer | Morgan Brown <morganbr@users.noreply.github.com> | 2017-11-06 11:23:49 +0300 |
commit | 9a819d14db26b678e8fd9338084abd1665b18148 (patch) | |
tree | 34f3291b1c44adc621ca894059d0f03265074b00 /src/ILCompiler.WebAssembly | |
parent | ff7decc2fdfc22c32c627734c2ff4eda2696911b (diff) |
added support for box/unbox/unbox_any for WASM using malloc (#4731)
Diffstat (limited to 'src/ILCompiler.WebAssembly')
-rw-r--r-- | src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs index ebe4a44bf..745dd0d20 100644 --- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs +++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs @@ -804,6 +804,11 @@ namespace Internal.IL { MetadataType metadataType = (MetadataType)type; int objectSize = metadataType.InstanceByteCount.AsInt; + if (metadataType.IsValueType) + { + objectSize += type.Context.Target.PointerSize; + } + LLVMValueRef allocatedMemory = LLVM.BuildMalloc(_builder, LLVM.ArrayType(LLVM.Int8Type(), (uint)objectSize), "newobj"); LLVMValueRef castMemory = LLVM.BuildPointerCast(_builder, allocatedMemory, LLVM.PointerType(LLVM.Int8Type(), 0), "castnewobj"); ImportCallMemset(castMemory, 0, objectSize); @@ -1428,6 +1433,37 @@ namespace Internal.IL private void ImportUnbox(int token, ILOpcode opCode) { + TypeDesc type = ResolveTypeToken(token); + if (type.IsNullable) + throw new NotImplementedException(); + + if (opCode == ILOpcode.unbox) + { + var unboxResult = _stack.Pop().ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder); + LLVMValueRef unboxData = LLVM.BuildGEP(_builder, unboxResult, new LLVMValueRef[] { BuildConstInt32(type.Context.Target.PointerSize) }, "unboxData"); + //push the pointer to the data, but it shouldnt be implicitly dereferenced + PushExpression(GetStackValueKind(type), "unboxed", unboxData, type); + } + else //unbox_any + { + Debug.Assert(opCode == ILOpcode.unbox_any); + + //TODO: when the runtime is ready switch this to calling the real RhUnboxAny + //LLVMValueRef eeType = GetEETypeForTypeDesc(type); + //var eeTypeDesc = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr"); + //LLVMValueRef untypedObjectValue = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(type), "objptr"); + //PushExpression(StackValueKind.ByRef, "objPtr", untypedObjectValue, type.MakePointerType()); + //PushExpression(StackValueKind.ByRef, "eeType", eeType, eeTypeDesc); + //CallRuntimeExport(_compilation.TypeSystemContext, "RhUnboxAny"); + //PushLoadExpression(GetStackValueKind(type), "unboxed", untypedObjectValue, type); + //this can be removed once we can call RhUnboxAny + if (!type.IsValueType) + throw new NotImplementedException(); + + var unboxResult = _stack.Pop().ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder); + LLVMValueRef unboxData = LLVM.BuildGEP(_builder, unboxResult, new LLVMValueRef[] { BuildConstInt32(type.Context.Target.PointerSize) }, "unboxData"); + PushLoadExpression(GetStackValueKind(type), "unboxed", unboxData, type); + } } private void ImportRefAnyVal(int token) @@ -1542,7 +1578,6 @@ namespace Internal.IL var objectType = objectEntry.Type ?? field.OwningType; LLVMValueRef untypedObjectValue; LLVMTypeRef llvmObjectType = GetLLVMTypeForTypeDesc(objectType); - if (objectType.IsValueType && !objectType.IsPointer && objectEntry.Kind != StackValueKind.NativeInt && objectEntry.Kind != StackValueKind.ByRef) { if (objectEntry is LoadExpressionEntry) @@ -1560,7 +1595,6 @@ namespace Internal.IL { untypedObjectValue = objectEntry.ValueAsType(LLVM.PointerType(LLVMTypeRef.Int8Type(), 0), _builder); } - if (field.Offset.AsInt == 0) { return untypedObjectValue; @@ -1649,7 +1683,19 @@ namespace Internal.IL private void ImportBox(int token) { + TypeDesc type = ResolveTypeToken(token); + if (type.IsValueType) + { + if (type.IsNullable) + throw new NotImplementedException(); + var value = _stack.Pop(); + ExpressionEntry boxTarget = AllocateObject(type); + LLVMValueRef boxData = LLVM.BuildGEP(_builder, boxTarget.RawLLVMValue, new LLVMValueRef[] { BuildConstInt32(type.Context.Target.PointerSize) }, "boxData"); + LLVMValueRef typedBoxData = LLVM.BuildPointerCast(_builder, boxData, LLVM.PointerType(GetLLVMTypeForTypeDesc(type), 0), "typedBoxData"); + LLVM.BuildStore(_builder, value.ValueAsType(type, _builder), typedBoxData); + _stack.Push(boxTarget); + } } private void ImportLeave(BasicBlock target) @@ -1762,6 +1808,13 @@ namespace Internal.IL } + private void CallRuntimeExport(TypeSystemContext context, string methodName) + { + MetadataType helperType = context.SystemModule.GetKnownType("System.Runtime", "RuntimeExports"); + MethodDesc helperMethod = helperType.GetKnownMethod(methodName, null); + HandleCall(helperMethod); + } + private StackEntry NewSpillSlot(StackEntry entry) { if (entry is SpilledExpressionEntry) |