Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Added support for ldvirtftn instruction to CppCodeGen #4556

Merged
merged 1 commit into from
Sep 18, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 84 additions & 44 deletions src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,44 +1046,15 @@ private void ImportCall(ILOpcode opcode, int token)
ExpressionEntry v = (ExpressionEntry)_stack[_stack.Top - (methodSignature.Length + 1)];

string typeDefName = _writer.GetCppMethodName(method);
_writer.AppendSignatureTypeDef(_builder, typeDefName, method.Signature, method.OwningType);
_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("));");
Append(" = (void*) ");
GetFunctionPointerForInterfaceMethod(method, v, typeDefName);

PushExpression(StackValueKind.ByRef, functionPtr);
}
Expand Down Expand Up @@ -1236,6 +1207,41 @@ private void ImportCall(ILOpcode opcode, int token)
}
}

private void GetFunctionPointerForInterfaceMethod(MethodDesc method, ExpressionEntry v, string typeDefName)
{
Append("((");
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("));");
}

private void PassCallArguments(MethodSignature methodSignature, TypeDesc thisArgument)
{
int signatureLength = methodSignature.Length;
Expand Down Expand Up @@ -1325,22 +1331,51 @@ private void ImportLdFtn(int token, ILOpcode opCode)
{
MethodDesc method = (MethodDesc)_methodIL.GetObject(token);

if (opCode == ILOpcode.ldvirtftn)
if (opCode == ILOpcode.ldvirtftn && method.IsVirtual && method.OwningType.IsInterface)
{
if (method.IsVirtual)
throw new NotImplementedException();
}
AddVirtualMethodReference(method);
var entry = new LdTokenEntry<MethodDesc>(StackValueKind.NativeInt, NewTempName(), method);
ExpressionEntry v = (ExpressionEntry)_stack.Pop();
string typeDefName = _writer.GetCppMethodName(method);
_writer.AppendSignatureTypeDef(_builder, typeDefName, method.Signature, method.OwningType);

AddMethodReference(method);
AppendEmptyLine();

var entry = new LdTokenEntry<MethodDesc>(StackValueKind.NativeInt, NewTempName(), method);
PushTemp(entry);
Append("(intptr_t)&");
Append(_writer.GetCppTypeName(method.OwningType));
Append("::");
Append(_writer.GetCppMethodName(method));
PushTemp(entry);
Append("(intptr_t) ");
GetFunctionPointerForInterfaceMethod(method, v, typeDefName);
}
else
{
AddMethodReference(method);
var entry = new LdTokenEntry<MethodDesc>(StackValueKind.NativeInt, NewTempName(), method);

if (opCode == ILOpcode.ldvirtftn && method.IsVirtual)
{
//ldvirtftn requires an object instance, we have to pop one off the stack
//then call the associated getslot method passing in the object instance to get the real function pointer
ExpressionEntry v = (ExpressionEntry)_stack.Pop();
PushTemp(entry);
Append("(intptr_t)");
Append(_writer.GetCppTypeName(method.OwningType));
Append("::__getslot__");
Append(_writer.GetCppMethodName(method));
Append("(");
Append(v.Name);
Append(")");
AppendSemicolon();
}
else
{
PushTemp(entry);
Append("(intptr_t)&");
Append(_writer.GetCppTypeName(method.OwningType));
Append("::");
Append(_writer.GetCppMethodName(method));

AppendSemicolon();
AppendSemicolon();
}
}
}

private void ImportLoadInt(long value, StackValueKind kind)
Expand Down Expand Up @@ -2675,6 +2710,11 @@ private void AddMethodReference(MethodDesc method)
_dependencies.Add(_nodeFactory.MethodEntrypoint(method));
}

private void AddVirtualMethodReference(MethodDesc method)
{
_dependencies.Add(_nodeFactory.VirtualMethodUse(method));
}

private void AddFieldReference(FieldDesc field)
{
if (field.IsStatic)
Expand Down