private void NewArray(InstructionNode node) { var method = GetVMCallMethod(VmCall.AllocateArray); var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, node.GetOperands()); }
private void CallVirtual(InstructionNode node) { var call = node.Operand1; var result = node.Result; var method = call.Method; 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); var context = new Context(node); // Same as above except for methodPointer int methodPointerOffset = CalculateMethodTableOffset(method) + (NativePointerSize * 14); // Get the TypeDef pointer context.SetInstruction(loadInstruction, typeDefinition, thisPtr, ConstantZero); // Get the address of the method context.AppendInstruction(loadInstruction, callTarget, typeDefinition, CreateConstant(methodPointerOffset)); MakeCall(context, callTarget, result, operands); }
private void CallVirtual(InstructionNode node) { var call = node.Operand1; var method = call.Method; if (TypeLayout.IsMethodOverridden(method)) { return; } var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var operands = node.GetOperands(); operands.RemoveAt(0); if (trace.Active) { trace.Log("De-virtualize: " + method); } DevirtualizedCount++; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, operands); }
private void CallVirtual(InstructionNode node) { var method = node.Operand1.Method; // Next lines are not necessary but faster then getting the method data if (!method.HasImplementation && method.IsAbstract) { return; } var methodData = MethodCompiler.Compiler.GetMethodData(method); if (!methodData.IsDevirtualized) { return; } var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var operands = node.GetOperands(); operands.RemoveAt(0); trace?.Log($"De-virtualize: {method}"); DevirtualizedMethodCallsCount++; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, operands); MethodScanner.MethodInvoked(method, Method); }
private void CallVirtual(InstructionNode node) { var call = node.Operand1; var method = call.Method; if (TypeLayout.IsMethodOverridden(method)) { return; } if (!method.HasImplementation && method.IsAbstract) { return; } var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var operands = node.GetOperands(); operands.RemoveAt(0); trace?.Log($"De-virtualize: {method}"); DevirtualizedCount++; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, operands); MethodScanner.MethodInvoked(method, Method); }
private void CallStatic(InstructionNode node) { var call = node.Operand1; var result = node.Result; var method = call.Method; var operands = node.GetOperands(); Debug.Assert(method != null); if (MethodCompiler.Compiler.CompilerData.IsMethodInlined(method)) { // If above is true, then a race condition occurred between: // 1) after inline stage of this method, and // 2) theinline evaluation stage of the target method // the only best option at this point is to stop compiling this method. // Note: It should already be scheduled to be re-compiled! //MethodCompiler.Stop(); //return; } //Debug.Assert(!MethodCompiler.Compiler.CompilerData.IsMethodInlined(method)); operands.RemoveAt(0); var context = new Context(node); context.Empty(); MakeCall(context, call, result, operands); Debug.Assert(method == call.Method); MethodScanner.MethodDirectInvoked(call.Method, Method); }
private void NewObject(InstructionNode node) { var method = GetVMCallMethod(VmCall.AllocateObject); var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var classType = node.MosaType; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, node.GetOperands()); MethodScanner.TypeAllocated(classType, Method); }
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); }
private void CallDynamic(InstructionNode node) { var call = node.Operand1; var result = node.Result; var operands = node.GetOperands(); operands.RemoveAt(0); var context = new Context(node); context.Empty(); MakeCall(context, call, result, operands); }
private void CallStatic(InstructionNode node) { var call = node.Operand1; var result = node.Result; var method = call.Method; var operands = node.GetOperands(); Debug.Assert(method != null); operands.RemoveAt(0); var context = new Context(node); context.Empty(); MakeCall(context, call, result, operands); }
private void CallDynamic(InstructionNode node) { var call = node.Operand1; var result = node.Result; var operands = node.GetOperands(); operands.RemoveAt(0); var context = new Context(node); context.Empty(); MakeCall(context, call, result, operands); if (call.Method != null) { MethodScanner.MethodInvoked(call.Method, Method); } }
protected void Inline(InstructionNode callSiteNode, BasicBlocks blocks) { var mapBlocks = new Dictionary <BasicBlock, BasicBlock>(blocks.Count); var map = new Dictionary <Operand, Operand>(); var nextBlock = Split(callSiteNode); // create basic blocks foreach (var block in blocks) { var newBlock = CreateNewBlock(); mapBlocks.Add(block, newBlock); } // copy instructions foreach (var block in blocks) { var newBlock = mapBlocks[block]; for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.Instruction == IRInstruction.Prologue) { continue; } if (node.Instruction == IRInstruction.Epilogue) { newBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Jmp, nextBlock)); continue; } if (node.Instruction == IRInstruction.SetReturn32 || node.Instruction == IRInstruction.SetReturn64 || node.Instruction == IRInstruction.SetReturnR4 || node.Instruction == IRInstruction.SetReturnR8 || node.Instruction == IRInstruction.SetReturnCompound) { if (callSiteNode.Result != null) { var newOperand = Map(node.Operand1, map, callSiteNode); BaseInstruction moveInstruction = null; if (node.Instruction == IRInstruction.SetReturn32) { moveInstruction = IRInstruction.Move32; } else if (node.Instruction == IRInstruction.SetReturn64) { moveInstruction = IRInstruction.Move64; } else if (node.Instruction == IRInstruction.SetReturnR4) { moveInstruction = IRInstruction.MoveR4; } else if (node.Instruction == IRInstruction.SetReturnR8) { moveInstruction = IRInstruction.MoveR8; } else if (node.Instruction == IRInstruction.SetReturnCompound) { moveInstruction = IRInstruction.MoveCompound; } Debug.Assert(moveInstruction != null); var moveNode = new InstructionNode(moveInstruction, callSiteNode.Result, newOperand); newBlock.BeforeLast.Insert(moveNode); } continue; } var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount) { ConditionCode = node.ConditionCode, Label = callSiteNode.Label }; if (node.BranchTargets != null) { // copy targets foreach (var target in node.BranchTargets) { newNode.AddBranchTarget(mapBlocks[target]); } } // copy results for (int i = 0; i < node.ResultCount; i++) { var op = node.GetResult(i); var newOp = Map(op, map, callSiteNode); newNode.SetResult(i, newOp); } // copy operands for (int i = 0; i < node.OperandCount; i++) { var op = node.GetOperand(i); var newOp = Map(op, map, callSiteNode); newNode.SetOperand(i, newOp); } // copy other if (node.MosaType != null) { newNode.MosaType = node.MosaType; } if (node.MosaField != null) { newNode.MosaField = node.MosaField; } UpdateParameterInstructions(newNode); newBlock.BeforeLast.Insert(newNode); } } var prologue = mapBlocks[blocks.PrologueBlock]; var callSiteOperands = callSiteNode.GetOperands(); if (callSiteOperands.Count > 1) { var context = new Context(prologue); for (int i = 1; i < callSiteOperands.Count; i++) { var operand = callSiteOperands[i]; if (!operand.IsVirtualRegister || operand.Low == null) { continue; } context.AppendInstruction(IRInstruction.GetLow64, operand.Low, operand); context.AppendInstruction(IRInstruction.GetHigh64, operand.High, operand); } } callSiteNode.SetInstruction(IRInstruction.Jmp, prologue); }
private void Box64(InstructionNode node) { SetVMCall(node, VmCall.Box64, node.Result, node.GetOperands()); }
private void MemoryCopy(InstructionNode node) { SetVMCall(node, VmCall.MemoryCopy, node.Result, node.GetOperands()); }
private void Rethrow(InstructionNode node) { SetVMCall(node, VmCall.Rethrow, node.Result, node.GetOperands()); }
private void GetVirtualFunctionPtr(InstructionNode node) { SetVMCall(node, VmCall.GetVirtualFunctionPtr, node.Result, node.GetOperands()); }
private void IsInstanceOfInterfaceType(InstructionNode node) { SetVMCall(node, VmCall.IsInstanceOfInterfaceType, node.Result, node.GetOperands()); }
private void Unbox32(InstructionNode node) { SetVMCall(node, VmCall.Unbox32, node.Result, node.GetOperands()); }