public static BaseIRInstruction GetSetReturnInstruction(MosaType type, bool is32bitPlatform) { if (type == null) { return(null); } if (type.IsR4) { return(IRInstruction.SetReturnR4); } else if (type.IsR8) { return(IRInstruction.SetReturnR8); } if (!is32bitPlatform) { return(IRInstruction.SetReturn64); } if (type.IsUI8 || (type.IsEnum && type.ElementType.IsUI8)) { return(IRInstruction.SetReturn64); } if (MosaTypeLayout.IsStoredOnStack(type)) { return(IRInstruction.SetReturnCompound); } return(IRInstruction.SetReturn32); }
/// <summary> /// Allocates the virtual register or stack slot. /// </summary> /// <param name="type">The type.</param> /// <returns></returns> public Operand AllocateVirtualRegisterOrStackSlot(MosaType type) { if (MosaTypeLayout.IsStoredOnStack(type)) { return(AddStackLocal(type)); } else { return(CreateVirtualRegister(type.GetStackType())); } }
/// <summary> /// Allocates the virtual register or stack slot. /// </summary> /// <param name="type">The type.</param> /// <returns></returns> public Operand AllocateVirtualRegisterOrStackSlot(MosaType type) { if (MosaTypeLayout.IsStoredOnStack(type)) { return(AddStackLocal(type)); } else { var resultType = Compiler.GetStackType(type); return(CreateVirtualRegister(resultType)); } }
/// <summary> /// Allocates the local variable virtual registers. /// </summary> /// <param name="locals">The locals.</param> public void SetLocalVariables(IList <MosaLocal> locals) { LocalVariables = new Operand[locals.Count]; int index = 0; foreach (var local in locals) { if (MosaTypeLayout.IsStoredOnStack(local.Type) || local.IsPinned) { LocalVariables[index++] = AddStackLocal(local.Type, local.IsPinned); } else { var stacktype = Compiler.GetStackType(local.Type); LocalVariables[index++] = CreateVirtualRegister(stacktype); } } }
/// <summary> /// Evaluates the parameter operands. /// </summary> private void EvaluateParameterOperands() { int offset = Architecture.OffsetOfFirstParameter; if (MosaTypeLayout.IsStoredOnStack(Method.Signature.ReturnType)) { offset += TypeLayout.GetTypeSize(Method.Signature.ReturnType); } int index = 0; if (Method.HasThis || Method.HasExplicitThis) { if (Method.DeclaringType.IsValueType) { var ptr = Method.DeclaringType.ToManagedPointer(); SetStackParameter(index++, ptr, "this", true, offset); var size = GetReferenceOrTypeSize(ptr, true); offset += size; } else { SetStackParameter(index++, Method.DeclaringType, "this", true, offset); var size = GetReferenceOrTypeSize(Method.DeclaringType, true); offset += size; } } foreach (var parameter in Method.Signature.Parameters) { SetStackParameter(index++, parameter.ParameterType, parameter.Name, false, offset); var size = GetReferenceOrTypeSize(parameter.ParameterType, true); offset += size; } }
/// <summary> /// Allocates the local variable virtual registers. /// </summary> /// <param name="locals">The locals.</param> public void SetLocalVariables(IList <MosaLocal> locals) { LocalVariables = new Operand[locals.Count]; int index = 0; foreach (var local in locals) { Operand operand = null; if (!MosaTypeLayout.IsStoredOnStack(local.Type) && !local.IsPinned) { var stacktype = local.Type.GetStackType(); operand = CreateVirtualRegister(stacktype); } else { operand = AddStackLocal(local.Type, local.IsPinned); } LocalVariables[index++] = operand; } }
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); }