diff options
author | Jeff Greene <hippiehunterenator@gmail.com> | 2018-04-26 03:46:50 +0300 |
---|---|---|
committer | Morgan Brown <morganbr@users.noreply.github.com> | 2018-04-26 03:46:50 +0300 |
commit | aad951a27e4774a68cfdc3b5167241d373e5c5c3 (patch) | |
tree | 19688fb87d2813ea550a5e3d7c78679e82c0fd9b /src/ILCompiler.WebAssembly | |
parent | 08d3d2c4a10c970cce291c748dd304a8a9c58b5e (diff) |
Enable Interface dispatch for WASM (#5748)
Interface dispatch
Diffstat (limited to 'src/ILCompiler.WebAssembly')
-rw-r--r-- | src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs index c3ead694d..d96ff3123 100644 --- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs +++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs @@ -313,7 +313,7 @@ namespace Internal.IL { if (_basicBlocks[_currentOffset].StartOffset == 0) throw new InvalidProgramException(); - + MarkBasicBlock(_basicBlocks[_currentOffset]); LLVM.BuildBr(_builder, GetLLVMBasicBlockForBlock(_basicBlocks[_currentOffset])); } } @@ -1001,11 +1001,6 @@ namespace Internal.IL { targetMethod = parameterType.ResolveInterfaceMethodTarget(callee); } - else - { - //TODO: needs runtime support for DispatchByInterface - throw new NotImplementedException("Interface call"); - } } else { @@ -1021,14 +1016,15 @@ namespace Internal.IL return GetOrCreateLLVMFunction(_compilation.NameMangler.GetMangledMethodName(targetMethod).ToString()); } - return GetCallableVirtualMethod(thisPointer.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), callee); + return GetCallableVirtualMethod(thisPointer, callee); + } else { return GetOrCreateLLVMFunction(calleeName); } } - + private LLVMValueRef GetOrCreateMethodSlot(MethodDesc method) { var vtableSlotSymbol = _compilation.NodeFactory.VTableSlot(method); @@ -1037,24 +1033,30 @@ namespace Internal.IL return LLVM.BuildLoad(_builder, slot, string.Empty); } - private LLVMValueRef GetCallableVirtualMethod(LLVMValueRef objectPtr, MethodDesc method) + private LLVMValueRef GetCallableVirtualMethod(StackEntry objectPtr, MethodDesc method) { Debug.Assert(method.IsVirtual); + LLVMValueRef slot = GetOrCreateMethodSlot(method); + var pointerSize = method.Context.Target.PointerSize; + LLVMTypeRef universalSignature = LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.PointerType(LLVM.Int8Type(), 0) }, false); + LLVMValueRef functionPtr; if (method.OwningType.IsInterface) { - throw new NotImplementedException(); + var eeTypeDesc = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr"); + var interfaceEEType = new LoadExpressionEntry(StackValueKind.ValueType, "interfaceEEType", GetEETypePointerForTypeDesc(method.OwningType, true), eeTypeDesc); + var eeTypeExpression = new LoadExpressionEntry(StackValueKind.ValueType, "eeType", objectPtr.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), eeTypeDesc); + var targetEntry = CallRuntime(_compilation.TypeSystemContext, DispatchResolve, "FindInterfaceMethodImplementationTarget", new StackEntry[] { eeTypeExpression, interfaceEEType, new ExpressionEntry(StackValueKind.Int32, "slot", slot, GetWellKnownType(WellKnownType.UInt16)) }); + functionPtr = targetEntry.ValueAsType(LLVM.PointerType(universalSignature, 0), _builder); } else { - LLVMValueRef slot = GetOrCreateMethodSlot(method); - var pointerSize = method.Context.Target.PointerSize; - LLVMTypeRef universalSignature = LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.PointerType(LLVM.Int8Type(), 0) }, false); - var rawObjectPtr = CastIfNecessary(objectPtr, LLVM.PointerType(LLVM.PointerType(LLVM.PointerType(universalSignature, 0), 0), 0)); + var rawObjectPtr = CastIfNecessary(objectPtr.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), LLVM.PointerType(LLVM.PointerType(LLVM.PointerType(universalSignature, 0), 0), 0)); var eeType = LLVM.BuildLoad(_builder, rawObjectPtr, "ldEEType"); var slotPtr = LLVM.BuildGEP(_builder, eeType, new LLVMValueRef[] { slot }, "__getslot__"); - var functionPtr = LLVM.BuildLoad(_builder, slotPtr, "ld__getslot__"); - return functionPtr; + functionPtr = LLVM.BuildLoad(_builder, slotPtr, "ld__getslot__"); } + + return functionPtr; } private ExpressionEntry AllocateObject(TypeDesc type) @@ -2582,6 +2584,7 @@ namespace Internal.IL private const string RuntimeImport = "RuntimeImports"; private const string InternalCalls = "InternalCalls"; private const string TypeCast = "TypeCast"; + private const string DispatchResolve = "DispatchResolve"; private ExpressionEntry CallRuntime(TypeSystemContext context, string className, string methodName, StackEntry[] arguments, TypeDesc forcedReturnType = null) { MetadataType helperType = context.SystemModule.GetKnownType("System.Runtime", className); |