/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.AddressOfInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.AddressOfInstruction(Context ctx) { Operand opRes = ctx.Result; RegisterOperand eax = new RegisterOperand (opRes.Type, GeneralPurposeRegister.EAX); ctx.Result = eax; ctx.ReplaceInstructionOnly (CPUx86.Instruction.LeaInstruction); // ctx.Ignore = true; ctx.AppendInstruction (CPUx86.Instruction.MovInstruction, opRes, eax); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Switch"/>. /// </summary> /// <param name="ctx">The context.</param> public void Switch(Context ctx) { ctx.ReplaceInstructionOnly(Instruction.SwitchInstruction); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Ret"/>. /// </summary> /// <param name="ctx">The context.</param> void ICILVisitor.Ret(Context ctx) { ctx.ReplaceInstructionOnly (IR.Instruction.ReturnInstruction); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Ldarga"/>. /// </summary> /// <param name="ctx">The context.</param> void ICILVisitor.Ldarga(Context ctx) { ctx.ReplaceInstructionOnly (IR.Instruction.AddressOfInstruction); //ctx.SetInstruction(IR.Instruction.AddressOfInstruction, ctx.Result, ctx.Operand1); }
/// <summary> /// Expands the given invoke instruction to perform the method call. /// </summary> /// <param name="ctx">The context.</param> /// <returns> /// A single instruction or an array of instructions, which appropriately represent the method call. /// </returns> public void MakeCall(Context ctx, ISignatureContext context, IMetadataProvider metadata) { /* * Calling convention is right-to-left, pushed on the stack. Return value in EAX for integral * types 4 bytes or less, XMM0 for floating point and EAX:EDX for 64-bit. If this is a method * of a type, the this argument is moved to ECX right before the call. * */ Operand invokeTarget = ctx.Operand1; Operand result = ctx.Result; Stack<Operand> operands = this.BuildOperandStack(ctx); ctx.ReplaceInstructionOnly(CPUx86.Instruction.NopInstruction); ctx.OperandCount = 0; ctx.Result = null; int stackSize = this.ReserveStackSizeForCall(ctx, metadata, context, operands); if (stackSize != 0) { this.PushOperands(context, ctx, operands, stackSize, metadata); } ctx.AppendInstruction(CPUx86.Instruction.CallInstruction, null, invokeTarget); if (stackSize != 0) { this.FreeStackAfterCall(ctx, stackSize); } this.CleanupReturnValue(ctx, result); }
/// <summary> /// Visitation function for <see cref="CIL.ICILVisitor.Branch"/>. /// </summary> /// <param name="ctx">The context.</param> void CIL.ICILVisitor.Branch(Context ctx) { ctx.ReplaceInstructionOnly(CPUx86.Instruction.JmpInstruction); }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.BranchInstruction"/> instructions. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.BranchInstruction(Context context) { context.ReplaceInstructionOnly (CPUx86.Instruction.BranchInstruction); }
/// <summary> /// Special handling for shift operations, which require the shift amount in the ECX or as a constant register. /// </summary> /// <param name="ctx">The transformation context.</param> /// <param name="instruction">The instruction to transform.</param> private void HandleShiftOperation(Context ctx, IInstruction instruction) { EmitOperandConstants (ctx); ctx.ReplaceInstructionOnly (instruction); }
/// <summary> /// Visitation function for DivUInstruction. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.DivUInstruction(Context context) { context.ReplaceInstructionOnly(CPUx86.Instruction.UDivInstruction); }
/// <summary> /// Special handling for commutative operations. /// </summary> /// <param name="context">The transformation context.</param> /// <param name="instruction">The instruction.</param> /// <remarks> /// Commutative operations are reordered by moving the constant to the second operand, /// which allows the instruction selection in the code generator to use a instruction /// format with an immediate operand. /// </remarks> private void HandleCommutativeOperation(Context context, IInstruction instruction) { EmitOperandConstants(context); context.ReplaceInstructionOnly(instruction); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Ldloca"/>. /// </summary> /// <param name="ctx">The context.</param> public void Ldloca(Context ctx) { ctx.ReplaceInstructionOnly(Instruction.AddressOfInstruction); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Branch"/>. /// </summary> /// <param name="ctx">The context.</param> public void Branch(Context ctx) { ctx.ReplaceInstructionOnly(Instruction.JmpInstruction); }
/// <summary> /// Replaces the instruction with an internal call. /// </summary> /// <param name="ctx">The transformation context.</param> /// <param name="internalCallTarget">The internal call target.</param> private void ReplaceWithInternalCall(Context ctx, VmCall internalCallTarget) { RuntimeType rt = RuntimeBase.Instance.TypeLoader.GetType(@"Mosa.Runtime.RuntimeBase"); RuntimeMethod callTarget = FindMethod(rt, internalCallTarget.ToString()); ctx.ReplaceInstructionOnly(IR.Instruction.CallInstruction); ctx.SetOperand(0, SymbolOperand.FromMethod(callTarget)); }
/// <summary> /// Replaces the IL load instruction by an appropriate IR move instruction or removes it entirely, if /// it is a native size. /// </summary> /// <param name="context">Provides the transformation context.</param> private void ProcessLoadInstruction(Context context) { IInstruction extension = null; SigType extendedType = null; Operand source = context.Operand1; Operand destination = context.Result; // Is this a sign or zero-extending move? if (source != null) { if (IsSignExtending(source)) { extension = Instruction.SignExtendedMoveInstruction; extendedType = BuiltInSigType.Int32; } else if (IsZeroExtending(source)) { extension = Instruction.ZeroExtendedMoveInstruction; extendedType = BuiltInSigType.UInt32; } } if (extension != null) { Operand temp = this.MethodCompiler.CreateTemporary(extendedType); destination.Replace(temp, context.InstructionSet); context.SetInstruction(extension, temp, source); } else { context.ReplaceInstructionOnly(Instruction.MoveInstruction); } }
private static void Replace(Context context, IIRInstruction floatingPointInstruction, IIRInstruction signedInstruction, IIRInstruction unsignedInstruction) { if (IsFloatingPoint(context)) { context.ReplaceInstructionOnly(floatingPointInstruction); } else if (IsUnsigned(context)) { context.ReplaceInstructionOnly(unsignedInstruction); } else { context.ReplaceInstructionOnly(signedInstruction); } }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.UDivInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.UDivInstruction(Context ctx) { ctx.ReplaceInstructionOnly (CPUx86.Instruction.UDivInstruction); }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.ZeroExtendedMoveInstruction"/> instructions. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.ZeroExtendedMoveInstruction(Context ctx) { switch (ctx.Operand1.Type.Type) { case CilElementType.I1: ctx.ReplaceInstructionOnly (CPUx86.Instruction.MovzxInstruction); break; case CilElementType.I2: goto case CilElementType.I1; case CilElementType.I4: goto case CilElementType.I1; case CilElementType.I8: throw new NotSupportedException (); case CilElementType.U1: goto case CilElementType.I1; case CilElementType.U2: goto case CilElementType.I1; case CilElementType.U4: goto case CilElementType.I1; case CilElementType.U8: goto case CilElementType.I8; case CilElementType.Char: goto case CilElementType.I2; default: throw new NotSupportedException (); } if ((ctx.Result is RegisterOperand)) return; Operand result = ctx.Result; Operand source = ctx.Operand1; RegisterOperand ebx = new RegisterOperand (result.Type, GeneralPurposeRegister.EBX); ctx.Result = ebx; ctx.AppendInstruction (CPUx86.Instruction.MovInstruction, result, ebx); }
/// <summary> /// Visitation function for LogicalOrInstruction. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.LogicalOrInstruction(Context context) { context.ReplaceInstructionOnly(CPUx86.Instruction.OrInstruction); }
/// <summary> /// Visitation function for MoveInstruction. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.MoveInstruction(Context context) { Operand result = context.Result; Operand operand = context.Operand1; context.Operand1 = EmitConstant(context.Operand1); if (context.Result.StackType == StackTypeCode.F) { Debug.Assert(context.Operand1.StackType == StackTypeCode.F, @"Move can't convert to floating point type."); if (context.Result.Type.Type == context.Operand1.Type.Type) { if (context.Result.Type.Type == CilElementType.R4) MoveFloatingPoint(context, CPUx86.Instruction.MovssInstruction); else if (context.Result.Type.Type == CilElementType.R8) MoveFloatingPoint(context, CPUx86.Instruction.MovsdInstruction); } else if (context.Result.Type.Type == CilElementType.R8) { context.SetInstruction(CPUx86.Instruction.Cvtss2sdInstruction, context.Result, context.Operand1, context.Operand2); } else if (context.Result.Type.Type == CilElementType.R4) { context.SetInstruction(CPUx86.Instruction.Cvtsd2ssInstruction, context.Result, context.Operand1, context.Operand2); } } else { if (context.Result is MemoryOperand && context.Operand1 is MemoryOperand) { RegisterOperand load = new RegisterOperand(new SigType(CilElementType.I), GeneralPurposeRegister.EDX); RegisterOperand store = new RegisterOperand(operand.Type, GeneralPurposeRegister.EDX); if (!Is32Bit(operand) && IsSigned(operand)) context.SetInstruction(CPUx86.Instruction.MovsxInstruction, load, operand); else if (!Is32Bit(operand) && IsUnsigned(operand)) context.SetInstruction(CPUx86.Instruction.MovzxInstruction, load, operand); else context.SetInstruction(CPUx86.Instruction.MovInstruction, load, operand); context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, store); } else context.ReplaceInstructionOnly(CPUx86.Instruction.MovInstruction); } }
/// <summary> /// Visitation function for SignExtendedMoveInstruction"/> instructions. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.SignExtendedMoveInstruction(Context context) { Operand offset = context.Operand2; if (offset != null) { RegisterOperand eax = new RegisterOperand(BuiltInSigType.Int32, GeneralPurposeRegister.EAX); Operand destination = context.Result; MemoryOperand source = (MemoryOperand)context.Operand1; SigType elementType = GetElementType(source.Type); ConstantOperand constantOffset = offset as ConstantOperand; IntPtr offsetPtr = IntPtr.Zero; context.SetInstruction(CPUx86.Instruction.MovInstruction, eax, source); if (constantOffset != null) { offsetPtr = new IntPtr(Convert.ToInt64(constantOffset.Value)); } else { context.AppendInstruction(CPUx86.Instruction.AddInstruction, eax, offset); } context.AppendInstruction(CPUx86.Instruction.MovsxInstruction, destination, new MemoryOperand(elementType, GeneralPurposeRegister.EAX, offsetPtr)); } else { context.ReplaceInstructionOnly(CPUx86.Instruction.MovsxInstruction); } }
/// <summary> /// Visitation function for <see cref="CPUx86.IX86Visitor.Movzx"/> instructions. /// </summary> /// <param name="context">The context.</param> void CPUx86.IX86Visitor.Movzx(Context context) { if (Is32Bit(context.Operand1)) context.ReplaceInstructionOnly(CPUx86.Instruction.MovInstruction); else { Operand result = context.Result; if (!(result is RegisterOperand)) { RegisterOperand ecx = new RegisterOperand(context.Result.Type, GeneralPurposeRegister.ECX); context.SetInstruction(CPUx86.Instruction.MovsxInstruction, ecx, context.Operand1); context.AppendInstruction(CPUx86.Instruction.MovInstruction, result, ecx); } } }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.FloatingPointToIntegerConversionInstruction"/> instructions. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.FloatingPointToIntegerConversionInstruction(Context context) { Operand source = context.Operand1; Operand destination = context.Result; switch (destination.Type.Type) { case CilElementType.I1: goto case CilElementType.I4; case CilElementType.I2: goto case CilElementType.I4; case CilElementType.I4: if (source.Type.Type == CilElementType.R8) context.ReplaceInstructionOnly (CPUx86.Instruction.Cvttsd2siInstruction); else context.ReplaceInstructionOnly (CPUx86.Instruction.Cvttss2siInstruction); break; case CilElementType.I8: throw new NotSupportedException (); case CilElementType.U1: goto case CilElementType.U4; case CilElementType.U2: goto case CilElementType.U4; case CilElementType.U4: throw new NotSupportedException (); case CilElementType.U8: throw new NotSupportedException (); case CilElementType.I: goto case CilElementType.I4; case CilElementType.U: goto case CilElementType.U4; } }
/// <summary> /// Handles the non commutative operation. /// </summary> /// <param name="ctx">The context.</param> /// <param name="instruction">The instruction.</param> private void HandleNonCommutativeOperation(Context ctx, IInstruction instruction) { EmitResultConstants(ctx); EmitOperandConstants(ctx); ctx.ReplaceInstructionOnly(instruction); }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.LogicalXorInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.LogicalXorInstruction(Context ctx) { ctx.ReplaceInstructionOnly (CPUx86.Instruction.XorInstruction); }
/// <summary> /// Replaces the instruction with an internal call. /// </summary> /// <param name="ctx">The transformation context.</param> /// <param name="internalCallTarget">The internal call target.</param> private void ReplaceWithInternalCall(Context ctx, object internalCallTarget) { RuntimeType rt = RuntimeBase.Instance.TypeLoader.GetType ("Mosa.Runtime.RuntimeBase"); RuntimeMethod callTarget = FindMethod (rt, internalCallTarget.ToString ()); ctx.ReplaceInstructionOnly (IR.Instruction.CallInstruction); ctx.InvokeTarget = callTarget; }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.MoveInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.MoveInstruction(Context ctx) { Operand result = ctx.Result; Operand operand = ctx.Operand1; ctx.Operand1 = EmitConstant (ctx.Operand1); if (ctx.Result.Type.Type == CilElementType.R4) MoveFloatingPoint (ctx, CPUx86.Instruction.MovssInstruction); else if (ctx.Result.Type.Type == CilElementType.R8) MoveFloatingPoint (ctx, CPUx86.Instruction.MovsdInstruction); else { if (ctx.Result is MemoryOperand && ctx.Operand1 is MemoryOperand) { RegisterOperand load = new RegisterOperand (new SigType (CilElementType.I), GeneralPurposeRegister.ECX); RegisterOperand store = new RegisterOperand (operand.Type, GeneralPurposeRegister.ECX); if (!Is32Bit (operand) && IsSigned (operand)) ctx.SetInstruction (CPUx86.Instruction.MovsxInstruction, load, operand); else if (!Is32Bit (operand) && IsUnsigned (operand)) ctx.SetInstruction (CPUx86.Instruction.MovzxInstruction, load, operand); else ctx.SetInstruction (CPUx86.Instruction.MovInstruction, load, operand); ctx.AppendInstruction (CPUx86.Instruction.MovInstruction, result, store); } else ctx.ReplaceInstructionOnly (CPUx86.Instruction.MovInstruction); } }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Nop"/>. /// </summary> /// <param name="ctx">The context.</param> void ICILVisitor.Nop(Context ctx) { ctx.ReplaceInstructionOnly (IR.Instruction.NopInstruction); }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.SignExtendedMoveInstruction"/> instructions. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.SignExtendedMoveInstruction(Context ctx) { ctx.ReplaceInstructionOnly (CPUx86.Instruction.MovsxInstruction); }
private void PerformStaticAllocationOf(Context allocation, Context assignment) { RuntimeType allocatedType = allocation.InvokeTarget.DeclaringType; // Allocate a linker symbol to refer to for this allocation. Use the destination field name as the linker symbol name. string symbolName = assignment.RuntimeField.ToString() + @"<<$cctor"; using (var stream = this.linker.Allocate(symbolName, SectionKind.BSS, allocatedType.Size, 4)) { // FIXME: Do we have to initialize this? string methodTableSymbol = this.GetMethodTableForType(allocatedType); if (methodTableSymbol != null) { this.linker.Link(LinkType.AbsoluteAddress | LinkType.I4, symbolName, 0, 0, methodTableSymbol, IntPtr.Zero); } } // Issue a load request before the newobj and before the assignment. Operand symbol1 = this.InsertLoadBeforeInstruction(allocation, symbolName, assignment.RuntimeField.SignatureType); allocation.Operand1 = symbol1; Operand symbol2 = this.InsertLoadBeforeInstruction(assignment, symbolName, assignment.RuntimeField.SignatureType); assignment.Operand1 = symbol2; // Change the newobj to a call and increase the operand count to include the this ptr. allocation.OperandCount++; allocation.ResultCount = 0; allocation.ReplaceInstructionOnly(Instruction.Get(OpCode.Call)); }
/// <summary> /// Visitation function for Ldarga instruction. /// </summary> /// <param name="context">The context.</param> public void Ldarga(Context context) { context.ReplaceInstructionOnly(IR.Instruction.AddressOfInstruction); }