diff options
Diffstat (limited to 'src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs')
-rw-r--r-- | src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs | 88 |
1 files changed, 76 insertions, 12 deletions
diff --git a/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs b/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs index de2cb4d51..df7a96159 100644 --- a/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs +++ b/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs @@ -389,6 +389,15 @@ namespace Internal.IL } /// <summary> + /// Append the typedef of the method to assist in function pointer conversion + /// </summary> + /// <param name="method">Method typedef</param> + private void AppendInterfaceCallTypeDef(MethodDesc method, string name) + { + _writer.AppendSignatureTypeDef(_builder, name, method.Signature, method.Signature.ReturnType); + } + + /// <summary> /// Increase level of indentation by one in <see cref="_builder"/>. /// </summary> public void Indent() @@ -491,14 +500,9 @@ namespace Internal.IL AddTypeReference(returnType, true); } var owningType = methodCodeNodeNeedingCode.Method.OwningType; - if (methodCodeNodeNeedingCode.Method.IsNativeCallable || methodCodeNodeNeedingCode.Method.IsRuntimeExport || methodCodeNodeNeedingCode.Method.IsRuntimeImplemented) - { - AddTypeReference(owningType, true); - } - if (methodCodeNodeNeedingCode.Method.Signature.IsStatic) - { - AddTypeReference(owningType, true); - } + + AddTypeReference(owningType, true); + ImportBasicBlocks(); if (_sequencePoints != null && _sequencePoints[0].Document != null) @@ -860,6 +864,7 @@ namespace Internal.IL { bool callViaSlot = false; bool delegateInvoke = false; + bool callViaInterfaceDispatch = false; DelegateCreationInfo delegateInfo = null; MethodDesc method = (MethodDesc)_methodIL.GetObject(token); @@ -936,17 +941,18 @@ namespace Internal.IL if (!method.IsNewSlot) throw new NotImplementedException(); - // TODO: Interface calls if (method.OwningType.IsInterface) - throw new NotImplementedException(); + callViaInterfaceDispatch = true; + + else + callViaSlot = true; _dependencies.Add(_nodeFactory.VirtualMethodUse(method)); - callViaSlot = true; } } - if (!callViaSlot && !delegateInvoke) + if (!callViaSlot && !delegateInvoke && !callViaInterfaceDispatch) AddMethodReference(method); if (opcode == ILOpcode.newobj) @@ -961,6 +967,55 @@ namespace Internal.IL StackValueKind retKind = StackValueKind.Unknown; var needNewLine = false; + if (callViaInterfaceDispatch) + { + _dependencies.Add(_nodeFactory.ReadyToRunHelper(ReadyToRunHelperId.InterfaceDispatch, method)); + ExpressionEntry v = (ExpressionEntry)_stack[_stack.Top - (methodSignature.Length + 1)]; + + string typeDefName = _writer.GetCppMethodName(method); + _writer.AppendSignatureTypeDef(_builder, typeDefName, method.Signature, method.OwningType); + + string functionPtr = NewTempName(); + AppendEmptyLine(); + + Append("void*"); + Append(functionPtr); + Append(" = (void*) (("); + Append(typeDefName); + // Call method to find implementation address + Append(") System_Private_CoreLib::System::Runtime::DispatchResolve::FindInterfaceMethodImplementationTarget("); + + // Get EEType of current object (interface implementation) + Append("::System_Private_CoreLib::System::Object::get_EEType((::System_Private_CoreLib::System::Object*)"); + Append(v.Name); + Append(")"); + + Append(", "); + + // Get EEType of interface + Append("((::System_Private_CoreLib::Internal::Runtime::EEType *)("); + Append(_writer.GetCppTypeName(method.OwningType)); + Append("::__getMethodTable()))"); + + Append(", "); + + // Get slot of implementation + Append("(uint16_t)"); + Append("("); + Append(_writer.GetCppTypeName(method.OwningType)); + Append("::"); + Append("__getslot__"); + Append(_writer.GetCppMethodName(method)); + Append("("); + Append(v.Name); + Append("))"); + + Append("));"); + + PushExpression(StackValueKind.ByRef, functionPtr); + + } + if (!retType.IsVoid) { retKind = GetStackValueKind(retType); @@ -1048,6 +1103,15 @@ namespace Internal.IL v.Name + ")->m_firstParameter"; } } + else if (callViaInterfaceDispatch) + { + Append("(("); + Append(_writer.GetCppMethodName(method)); + Append(")"); + ExpressionEntry v = (ExpressionEntry)_stack.Pop(); + Append(v); + Append(")"); + } else { Append(_writer.GetCppTypeName(method.OwningType)); |