Ejemplo n.º 1
0
        private void CallInterface(Context context)
        {
            var call     = context.Operand1;
            var method   = call.Method;
            var result   = context.Result;
            var thisPtr  = context.Operand2;
            var operands = context.GetOperands();

            Debug.Assert(method != null);

            operands.RemoveAt(0);

            Debug.Assert(method.DeclaringType.IsInterface);

            // FUTURE: This can be optimized to skip Method Definition lookup.

            // Offset to MethodTable from thisPtr
            var typeDefOffset = CreateConstant32(-NativePointerSize);

            // Offset for InterfaceSlotTable in TypeDef/MethodTable
            var interfaceSlotTableOffset = CreateConstant32(NativePointerSize * 11);

            // Offset for InterfaceMethodTable in InterfaceSlotTable
            var interfaceMethodTableOffset = CreateConstant32(CalculateInterfaceSlotOffset(method));

            // Offset for Method Def in InterfaceMethodTable
            var methodDefinitionOffset = CreateConstant32(CalculateInterfaceMethodTableOffset(method));

            // Offset for Method pointer in MethodDef
            var methodPointerOffset = CreateConstant32(NativePointerSize * 4);

            // Operands to hold pointers
            var typeDef    = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);
            var callTarget = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);

            var interfaceSlotPtr        = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);
            var interfaceMethodTablePtr = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);
            var methodDefinition        = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);

            // Get the MethodTable pointer
            context.SetInstruction(LoadInstruction, typeDef, thisPtr, typeDefOffset);

            // Get the InterfaceSlotTable pointer
            context.AppendInstruction(LoadInstruction, interfaceSlotPtr, typeDef, interfaceSlotTableOffset);

            // Get the InterfaceMethodTable pointer
            context.AppendInstruction(LoadInstruction, interfaceMethodTablePtr, interfaceSlotPtr, interfaceMethodTableOffset);

            // Get the MethodDef pointer
            context.AppendInstruction(LoadInstruction, methodDefinition, interfaceMethodTablePtr, methodDefinitionOffset);

            // Get the address of the method
            context.AppendInstruction(LoadInstruction, callTarget, methodDefinition, methodPointerOffset);

            MakeCall(context, callTarget, result, operands, method);

            MethodScanner.InterfaceMethodInvoked(method, Method);
        }
Ejemplo n.º 2
0
        private void CallInterface(InstructionNode node)
        {
            var call     = node.Operand1;
            var method   = call.Method;
            var result   = node.Result;
            var thisPtr  = node.Operand2;
            var operands = node.GetOperands();

            Debug.Assert(method != null);

            operands.RemoveAt(0);

            var typeDefinition = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);
            var callTarget     = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);

            Debug.Assert(method.DeclaringType.IsInterface);

            // Offset for InterfaceSlotTable in TypeDef
            int interfaceSlotTableOffset = (NativePointerSize * 11);

            // Offset for InterfaceMethodTable in InterfaceSlotTable
            int interfaceMethodTableOffset = (NativePointerSize * 1) + CalculateInterfaceSlotOffset(method);

            // Offset for MethodDef in InterfaceMethodTable
            int methodDefinitionOffset = (NativePointerSize * 2) + CalculateMethodTableOffset(method);

            // Offset for Method pointer in MethodDef
            int methodPointerOffset = (NativePointerSize * 4);

            // Operands to hold pointers
            var interfaceSlotPtr        = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);
            var interfaceMethodTablePtr = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);
            var methodDefinition        = AllocateVirtualRegister(TypeSystem.BuiltIn.Pointer);

            var context = new Context(node);

            // Get the TypeDef pointer
            context.SetInstruction(loadInstruction, typeDefinition, thisPtr, ConstantZero);

            // Get the Interface Slot Table pointer
            context.AppendInstruction(loadInstruction, interfaceSlotPtr, typeDefinition, CreateConstant(interfaceSlotTableOffset));

            // Get the Interface Method Table pointer
            context.AppendInstruction(loadInstruction, interfaceMethodTablePtr, interfaceSlotPtr, CreateConstant(interfaceMethodTableOffset));

            // Get the MethodDef pointer
            context.AppendInstruction(loadInstruction, methodDefinition, interfaceMethodTablePtr, CreateConstant(methodDefinitionOffset));

            // Get the address of the method
            context.AppendInstruction(loadInstruction, callTarget, methodDefinition, CreateConstant(methodPointerOffset));

            MakeCall(context, callTarget, result, operands);

            MethodScanner.InterfaceMethodInvoked(method, Method);
        }