private static void PatchBeginInvoke(BaseMethodCompiler methodCompiler) { var nullOperand = Operand.GetNull(methodCompiler.TypeSystem); var context = new Context(CreateMethodStructure(methodCompiler, true)); context.AppendInstruction(IRInstruction.Return, null, nullOperand); context.AddBranchTarget(methodCompiler.BasicBlocks.EpilogueBlock); }
private static void PatchInvoke(BaseMethodCompiler methodCompiler) { // check if instance is null (if so, it's a static call to the methodPointer) MosaField methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer"); int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField); Operand methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset); MosaField instanceField = GetField(methodCompiler.Method.DeclaringType, "instance"); int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField); Operand instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset); var size = methodCompiler.Architecture.NativeInstructionSize; bool withReturn = (methodCompiler.Method.Signature.ReturnType == null) ? false : !methodCompiler.Method.Signature.ReturnType.IsVoid; Context b0 = new Context(CreateMethodStructure(methodCompiler, false)); Context b1 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Context b2 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Context b3 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Operand[] vrs = new Operand[methodCompiler.Parameters.Length]; for (int i = 0; i < methodCompiler.Parameters.Length; i++) { vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type); //fixme: handle structs var loadInstruction = BaseMethodCompilerStage.GetLoadInstruction(vrs[i].Type); var moveSize = BaseMethodCompilerStage.GetInstructionSize(vrs[i].Type); b0.AppendInstruction(loadInstruction, moveSize, vrs[i], methodCompiler.StackFrame, methodCompiler.Parameters[i]); } Operand thisOperand = vrs[0]; Operand opMethod = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.U4); Operand opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type); Operand opCompare = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.I4); Operand opReturn = withReturn ? methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType) : null; Operand c0 = Operand.CreateConstant(methodCompiler.TypeSystem, 0); b0.AppendInstruction(IRInstruction.LoadInteger, size, opMethod, thisOperand, methodPointerOffsetOperand); b0.AppendInstruction(IRInstruction.LoadInteger, size, opInstance, thisOperand, instanceOffsetOperand); b0.AppendInstruction(IRInstruction.CompareInteger, ConditionCode.Equal, opCompare, opInstance, c0); b0.AppendInstruction(IRInstruction.CompareIntegerBranch, ConditionCode.Equal, null, opCompare, c0); b0.AddBranchTarget(b2.Block); b0.AppendInstruction(IRInstruction.Jmp, b1.Block); // no instance b1.AppendInstruction(IRInstruction.Call, opReturn, opMethod); b1.InvokeMethod = methodCompiler.Method; for (int i = 1; i < methodCompiler.Parameters.Length; i++) b1.AddOperand(vrs[i]); if (withReturn) b1.SetResult(0, opReturn); b1.AppendInstruction(IRInstruction.Jmp, b3.Block); // instance b2.AppendInstruction(IRInstruction.Call, opReturn, opMethod); b2.InvokeMethod = methodCompiler.Method; b2.AddOperand(opInstance); for (int i = 1; i < methodCompiler.Parameters.Length; i++) b2.AddOperand(vrs[i]); if (withReturn) b2.SetResult(0, opReturn); b2.AppendInstruction(IRInstruction.Jmp, b3.Block); // return b3.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock); if (withReturn) b3.SetOperand(0, opReturn); }
private void PatchInvoke(BaseMethodCompiler methodCompiler) { // check if instance is null (if so, it's a static call to the methodPointer) var methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer"); int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField); var methodPointerOffsetOperand = Operand.CreateConstant(methodPointerOffset, methodCompiler.TypeSystem); var instanceField = GetField(methodCompiler.Method.DeclaringType, "instance"); int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField); var instanceOffsetOperand = Operand.CreateConstant(instanceOffset, methodCompiler.TypeSystem); var size = methodCompiler.Architecture.NativeInstructionSize; bool withReturn = (methodCompiler.Method.Signature.ReturnType == null) ? false : !methodCompiler.Method.Signature.ReturnType.IsVoid; var b0 = new Context(CreateMethodStructure(methodCompiler)); var b1 = new Context(methodCompiler.BasicBlocks.CreateBlock()); var b2 = new Context(methodCompiler.BasicBlocks.CreateBlock()); var b3 = new Context(methodCompiler.BasicBlocks.CreateBlock()); var vrs = new Operand[methodCompiler.Parameters.Length]; for (int i = 0; i < methodCompiler.Parameters.Length; i++) { var type = methodCompiler.Parameters[i].Type; if (MosaTypeLayout.IsStoredOnStack(type)) { b0.AppendInstruction(IRInstruction.LoadParameterCompound, vrs[i], methodCompiler.Parameters[i]); b0.MosaType = type; } else { vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type); var loadInstruction = BaseMethodCompilerStage.GetLoadParameterInstruction(vrs[i].Type); var loadsize = BaseMethodCompilerStage.GetInstructionSize(vrs[i].Type); b0.AppendInstruction(loadInstruction, loadsize, vrs[i], methodCompiler.Parameters[i]); b0.MosaType = type; } } var thisOperand = vrs[0]; var opMethod = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.U4); var opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type); var opCompare = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.I4); var opReturn = withReturn ? methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType) : null; var c0 = Operand.CreateConstant(0, methodCompiler.TypeSystem); b0.AppendInstruction(IRInstruction.LoadInteger, size, opMethod, thisOperand, methodPointerOffsetOperand); b0.AppendInstruction(IRInstruction.LoadInteger, size, opInstance, thisOperand, instanceOffsetOperand); b0.AppendInstruction(IRInstruction.CompareInteger, ConditionCode.Equal, opCompare, opInstance, c0); b0.AppendInstruction(IRInstruction.CompareIntegerBranch, ConditionCode.Equal, null, opCompare, c0); b0.AddBranchTarget(b2.Block); b0.AppendInstruction(IRInstruction.Jmp, b1.Block); var operands = new List <Operand>(methodCompiler.Parameters.Length + 1); for (int i = 1; i < methodCompiler.Parameters.Length; i++) { operands.Add(vrs[i]); } var result = withReturn ? opReturn : null; // no instance b1.AppendInstruction(IRInstruction.CallDynamic, result, opMethod, operands); b1.AppendInstruction(IRInstruction.Jmp, b3.Block); // instance b2.AppendInstruction(IRInstruction.CallDynamic, result, opMethod, opInstance, operands); b2.AppendInstruction(IRInstruction.Jmp, b3.Block); // return if (opReturn != null) { b3.AppendInstruction(IRInstruction.SetReturn, null, opReturn); } b3.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
private static void PatchInvoke(BaseMethodCompiler methodCompiler, bool withReturn) { // check if instance is null (if so, it's a static call to the methodPointer) MosaField methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer"); int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField); Operand methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset); MosaField instanceField = GetField(methodCompiler.Method.DeclaringType, "instance"); int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField); Operand instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset); var size = methodCompiler.Architecture.NativeInstructionSize; Context b0 = new Context(CreateMethodStructure(methodCompiler, false)); Context b1 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Context b2 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Context b3 = new Context(methodCompiler.BasicBlocks.CreateBlock()); Operand[] vrs = new Operand[methodCompiler.Parameters.Length]; for (int i = 0; i < methodCompiler.Parameters.Length; i++) { vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type); if (methodCompiler.TypeLayout.IsCompoundType(methodCompiler.Parameters[i].Type)) { b0.AppendInstruction(IRInstruction.CompoundMove, vrs[i], methodCompiler.Parameters[i]); } else { b0.AppendInstruction(IRInstruction.Move, vrs[i], methodCompiler.Parameters[i]); } } Operand thisOperand = vrs[0]; Operand opMethod = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.U4); Operand opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type); Operand opCompare = methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.I4); Operand opReturn = withReturn ? methodCompiler.VirtualRegisters.Allocate(methodCompiler.TypeSystem.BuiltIn.Object) : null; Operand c0 = Operand.CreateConstant(methodCompiler.TypeSystem, 0); b0.AppendInstruction(IRInstruction.Load, size, opMethod, thisOperand, methodPointerOffsetOperand); b0.AppendInstruction(IRInstruction.Load, size, opInstance, thisOperand, instanceOffsetOperand); b0.AppendInstruction(IRInstruction.IntegerCompare, ConditionCode.Equal, opCompare, opInstance, c0); b0.AppendInstruction(IRInstruction.IntegerCompareBranch, ConditionCode.Equal, null, opCompare, c0); b0.AddBranchTarget(b2.Block); b0.AppendInstruction(IRInstruction.Jmp, b1.Block); // no instance b1.AppendInstruction(IRInstruction.Call, opReturn, opMethod); b1.InvokeMethod = methodCompiler.Method; for (int i = 1; i < methodCompiler.Parameters.Length; i++) { b1.AddOperand(vrs[i]); } b1.AppendInstruction(IRInstruction.Jmp, b3.Block); // instance b2.AppendInstruction(IRInstruction.Call, opReturn, opMethod); b2.InvokeMethod = methodCompiler.Method; b2.AddOperand(opInstance); for (int i = 1; i < methodCompiler.Parameters.Length; i++) { b2.AddOperand(vrs[i]); } b2.AppendInstruction(IRInstruction.Jmp, b3.Block); // return b3.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock); if (withReturn) { b3.SetOperand(0, opReturn); } }