public static void ByReference__ctor(Context context, MethodCompiler methodCompiler) { var instance = methodCompiler.Parameters[0]; var value = methodCompiler.Parameters[1]; var opInstance = methodCompiler.AllocateVirtualRegisterOrStackSlot(instance.Type); var opValue = methodCompiler.AllocateVirtualRegisterOrStackSlot(value.Type); // Load instance parameter var loadInstance = BaseMethodCompilerStage.GetLoadParameterInstruction(instance.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(loadInstance, opInstance, instance); // Load value parameter var loadValue = BaseMethodCompilerStage.GetLoadParameterInstruction(value.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(loadValue, opValue, value); // Store value inside instance var store = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Store32 : IRInstruction.Store64; context.AppendInstruction(store, null, opInstance, methodCompiler.ConstantZero, opValue); context.MosaType = methodCompiler.TypeSystem.BuiltIn.I; context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
public static void Unsafe_AddByteOffset(Context context, MethodCompiler methodCompiler) { var source = methodCompiler.Parameters[0]; var byteOffset = methodCompiler.Parameters[1]; var opSource = methodCompiler.AllocateVirtualRegisterOrStackSlot(source.Type); var opByteOffset = methodCompiler.AllocateVirtualRegisterOrStackSlot(byteOffset.Type); var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // Load left parameter var loadSource = BaseMethodCompilerStage.GetLoadParameterInstruction(source.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(loadSource, opSource, source); // Load right parameter var loadByteOffset = BaseMethodCompilerStage.GetLoadParameterInstruction(byteOffset.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(loadByteOffset, opByteOffset, byteOffset); // Compare and store into result operand var add = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Add32 : IRInstruction.Add64; context.AppendInstruction(add, opReturn, opSource, opByteOffset); // Return comparison result var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
public static void Unsafe_AreSame(Context context, MethodCompiler methodCompiler) { var left = methodCompiler.Parameters[0]; var right = methodCompiler.Parameters[1]; var opLeft = methodCompiler.AllocateVirtualRegisterOrStackSlot(left.Type); var opRight = methodCompiler.AllocateVirtualRegisterOrStackSlot(right.Type); var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // Load left parameter var loadLeft = BaseMethodCompilerStage.GetLoadParameterInstruction(left.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(loadLeft, opLeft, left); // Load right parameter var loadRight = BaseMethodCompilerStage.GetLoadParameterInstruction(right.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(loadRight, opRight, right); // Compare and store into result operand context.AppendInstruction(IRInstruction.CompareObject, ConditionCode.Equal, opReturn, opLeft, opRight); // Set return var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
/// <summary> /// Replaces the intrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler) { var zero = Operand.CreateConstant(0, methodCompiler.TypeSystem); var size = BaseMethodCompilerStage.GetInstructionSize(context.Size, context.InvokeMethod.Signature.Parameters[1].ParameterType); context.SetInstruction(X86.MovStore, size, null, context.Operand1, zero, context.Operand2); }
private static void MovRegToMemory(InstructionNode node, MachineCodeEmitter emitter) { Debug.Assert(node.Operand3.IsRegister); Debug.Assert(node.ResultCount == 0); Debug.Assert(!node.Operand3.IsConstant); var size = BaseMethodCompilerStage.GetInstructionSize(node.Size, node.Operand1.Type); var linkreference = node.Operand1.IsLabel || node.Operand1.IsField || node.Operand1.IsSymbol; // reg to memory 1000 100w: mod reg r/m var opcode = new OpcodeEncoder() .AppendConditionalPrefix(0x66, size == InstructionSize.Size16) // 8:prefix: 16bit .AppendNibble(Bits.b1000) // 4:opcode .Append3Bits(Bits.b100) // 3:opcode .AppendWidthBit(size != InstructionSize.Size8) // 1:width .ModRegRMSIBDisplacement(node.Operand3, node.Operand1, node.Operand2) // Mod-Reg-RM-?SIB-?Displacement .AppendConditionalIntegerValue(0, linkreference); // 32:memory if (linkreference) { emitter.Emit(opcode, node.Operand1, (opcode.Size - 32) / 8); } else { emitter.Emit(opcode); } }
public static void Run(MethodCompiler methodCompiler, BaseMethodCompilerStage stage) { Run( methodCompiler.Trace, stage.FormattedStageName, methodCompiler.Method, methodCompiler.BasicBlocks ); }
public static void Run(MethodCompiler methodCompiler, BaseMethodCompilerStage stage, NotifyTraceLogHandler handler) { Run( stage.FormattedStageName, methodCompiler.Method, methodCompiler.BasicBlocks, methodCompiler.MethodData.Version, handler ); }
public static void Unsafe_As(Context context, MethodCompiler methodCompiler) { var source = methodCompiler.Parameters[0]; var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // Load source into return operand var loadSource = BaseMethodCompilerStage.GetLoadParameterInstruction(source.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(loadSource, opReturn, source); // Set return var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
public static void Unsafe_SizeOf(Context context, MethodCompiler methodCompiler) { var type = methodCompiler.Method.GenericArguments[0]; var size = methodCompiler.TypeLayout.GetTypeSize(type); var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // Move constant into return operand var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(size)); // Set return var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
/// <summary> /// Computes the opcode. /// </summary> /// <param name="size">The size.</param> /// <param name="destination">The destination operand.</param> /// <param name="source">The source operand.</param> /// <returns></returns> /// <exception cref="System.ArgumentException">@No opcode for operand type. [ + destination + , + source + )</exception> private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source) { Debug.Assert(destination.IsMemoryAddress); Debug.Assert(source.IsRegister || source.IsConstant || source.IsSymbol); size = BaseMethodCompilerStage.GetInstructionSize(size, destination); if (source.IsSymbol) { return(RM_C); } if (source.IsConstant) { if (size == InstructionSize.Size8) { return(RM_C_U8); } if (size == InstructionSize.Size16) { return(M_C_16); } return(RM_C); } if (source.IsRegister) { if (size == InstructionSize.Size8) { return(RM_R_U8); } if (size == InstructionSize.Size16) { return(M_R_16); } return(M_R); } throw new ArgumentException(@"No opcode for operand type. [" + destination + ", " + source + ")"); }
private void CheckAndClearEmptyBlock(BasicBlock block) { if (block.PreviousBlocks.Count != 0 || block.IsHeadBlock) { return; } trace?.Log($"*** Removed Block: {block}"); var nextBlocks = block.NextBlocks.ToArray(); EmptyBlockOfAllInstructions(block); BaseMethodCompilerStage.RemoveBlocksFromPHIInstructions(block, nextBlocks); foreach (var next in nextBlocks) { CheckAndClearEmptyBlock(next); } }
public static void RuntimeHelpers_IsReferenceOrContainsReferences(Context context, MethodCompiler methodCompiler) { var type = methodCompiler.Method.GenericArguments[0]; var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // FIXME: we're only checking if the current type is a reference type, we aren't checking if it contains references var isReferenceOrContainsReferences = type.IsReferenceType; // Move constant into return operand var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64; context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(isReferenceOrContainsReferences ? 1 : 0)); // Set return var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
/// <summary> /// Computes the opcode. /// </summary> /// <param name="size">The size.</param> /// <param name="destination">The destination operand.</param> /// <param name="source">The source operand.</param> /// <returns></returns> /// <exception cref="System.ArgumentException">@No opcode for operand type. [ + destination + , + source + )</exception> private OpCode ComputeOpCode(InstructionSize size, Operand destination, Operand source) { Debug.Assert(destination.IsRegister); Debug.Assert(source.IsMemoryAddress); size = BaseMethodCompilerStage.GetInstructionSize(size, destination); Debug.Assert(size != InstructionSize.Size64); if (size == InstructionSize.Size8) { return(R_M_U8); } if (size == InstructionSize.Size16) { return(R_RM_16); } return(R_RM); }
public static void ByReference_get_Value(Context context, MethodCompiler methodCompiler) { var instance = methodCompiler.Parameters[0]; var opInstance = methodCompiler.AllocateVirtualRegisterOrStackSlot(instance.Type); var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType); // Load instance parameter var loadInstance = BaseMethodCompilerStage.GetLoadParameterInstruction(instance.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(loadInstance, opInstance, instance); // Load value from instance into return operand var loadValue = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Load32 : IRInstruction.Load64; context.AppendInstruction(loadValue, opReturn, opInstance, methodCompiler.ConstantZero); context.MosaType = methodCompiler.TypeSystem.BuiltIn.I; // Set return var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform); context.AppendInstruction(setReturn, null, opReturn); context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
public static void RemoveBlockFromPHIInstructions(BasicBlock removedBlock, BasicBlock phiBlock) { BaseMethodCompilerStage.RemoveBlockFromPHIInstructions(removedBlock, phiBlock); }
public static void UpdatePHIInstructionTargets(List <BasicBlock> targets, BasicBlock source, BasicBlock newSource) { BaseMethodCompilerStage.UpdatePHIInstructionTargets(targets, source, newSource); }
public static void UpdatePHIInstructionTarget(BasicBlock target, BasicBlock source, BasicBlock newSource) { BaseMethodCompilerStage.UpdatePHIInstructionTarget(target, source, newSource); }
public static void RemoveBlocksFromPHIInstructions(BasicBlock removedBlock, BasicBlock[] nextBlocks) { BaseMethodCompilerStage.RemoveBlocksFromPHIInstructions(removedBlock, nextBlocks); }