/// <summary> /// Compiles the method. /// </summary> /// <param name="method">The method.</param> /// <param name="basicBlocks">The basic blocks.</param> /// <param name="threadID">The thread identifier.</param> public void CompileMethod(MosaMethod method, BasicBlocks basicBlocks, int threadID = 0) { PostCompilerTraceEvent(CompilerEvent.MethodCompileStart, method.FullName, threadID); var pipeline = GetOrCreateMethodStagePipeline(threadID); var methodCompiler = new MethodCompiler(this, method, basicBlocks, threadID) { Pipeline = pipeline }; methodCompiler.Compile(); PostCompilerTraceEvent(CompilerEvent.MethodCompileEnd, method.FullName, threadID); CompilerTrace.PostMethodCompiled(method); }
private static BasicBlock CreateMethodStructure(MethodCompiler methodCompiler) { var basicBlocks = methodCompiler.BasicBlocks; // Create the prologue block var prologue = basicBlocks.CreateBlock(BasicBlock.PrologueLabel); basicBlocks.AddHeadBlock(prologue); // Create the epilogue block var epiologue = basicBlocks.CreateBlock(BasicBlock.EpilogueLabel); var start = basicBlocks.CreateBlock(BasicBlock.StartLabel); // Add a jump instruction to the first block from the prologue prologue.First.Insert(new InstructionNode(IRInstruction.Jmp, start)); return(start); }
public static bool PatchDelegate(MethodCompiler methodCompiler) { Debug.Assert(methodCompiler.Method.DeclaringType.IsDelegate); //if (!methodCompiler.Method.DeclaringType.IsDelegate) // return false; switch (methodCompiler.Method.Name) { case ".ctor": PatchConstructor(methodCompiler); return(true); case "Invoke": PatchInvoke(methodCompiler); return(true); case "InvokeWithReturn": PatchInvoke(methodCompiler); return(true); case "BeginInvoke": PatchBeginInvoke(methodCompiler); return(true); case "EndInvoke": PatchEndInvoke(methodCompiler); return(true); default: return(false); } }
public void Execute() { foreach (var counter in Counters) { counter.Reset(); } //Run(); try { Run(); } catch (Exception ex) { MethodCompiler.Stop(); NewCompilerTraceEvent(CompilerEvent.Exception, "Method: " + Method + " -> " + ex); MethodCompiler.Compiler.Stop(); } SubmitTraceLogs(traceLogs); Finish(); foreach (var counter in Counters) { UpdateCounter(counter); } //if (!MethodCompiler.IsStopped) //{ // Debug.Assert(BasicBlocks.RuntimeValidation()); //} MethodCompiler = null; traceLogs = null; }
/// <summary> /// Gets the size of the type. /// </summary> /// <param name="type">The type.</param> /// <param name="align">if set to <c>true</c> [align].</param> /// <returns></returns> public int GetTypeSize(MosaType type, bool align) { return(MethodCompiler.GetReferenceOrTypeSize(type, align)); }
/// <summary> /// Allocates the virtual register or stack slot. /// </summary> /// <param name="type">The type.</param> /// <returns></returns> public Operand AllocateVirtualRegisterOrStackSlot(MosaType type) { return(MethodCompiler.AllocateVirtualRegisterOrStackSlot(type)); }
public void AllStopWithException(string exception) { MethodCompiler.Stop(); MethodCompiler.Compiler.Stop(); throw new CompilerException(exception); }
public string GetFormattedStageName() { return(MethodCompiler.FormatStageName(this as IPipelineStage)); }
private static void PatchInvoke(MethodCompiler methodCompiler) { // check if instance is null (if so, it's a static call to the methodPointer) var loadInstruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Load32 : IRInstruction.Load64; var compareInstruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Compare32x32 : IRInstruction.Compare64x64; var branchInstruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.CompareBranch32 : IRInstruction.CompareBranch64; var nativeIntegerType = methodCompiler.Architecture.Is32BitPlatform ? methodCompiler.TypeSystem.BuiltIn.U4 : methodCompiler.TypeSystem.BuiltIn.U8; var methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer"); int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField); var methodPointerOffsetOperand = methodCompiler.CreateConstant(methodPointerOffset); var instanceField = GetField(methodCompiler.Method.DeclaringType, "instance"); int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField); var instanceOffsetOperand = methodCompiler.CreateConstant(instanceOffset); 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.CanFitInRegister(type)) { b0.AppendInstruction(IRInstruction.LoadParamCompound, vrs[i], methodCompiler.Parameters[i]); b0.MosaType = type; } else { vrs[i] = methodCompiler.VirtualRegisters.Allocate(methodCompiler.Parameters[i].Type); var paramLoadInstruction = BaseMethodCompilerStage.GetLoadParameterInstruction(vrs[i].Type, methodCompiler.Architecture.Is32BitPlatform); b0.AppendInstruction(paramLoadInstruction, vrs[i], methodCompiler.Parameters[i]); b0.MosaType = type; } } var thisOperand = vrs[0]; var opMethod = methodCompiler.VirtualRegisters.Allocate(nativeIntegerType); var opInstance = methodCompiler.VirtualRegisters.Allocate(thisOperand.Type); var opCompare = methodCompiler.VirtualRegisters.Allocate(nativeIntegerType); var opReturn = withReturn ? methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType) : null; var c0 = methodCompiler.ConstantZero; b0.AppendInstruction(loadInstruction, opMethod, thisOperand, methodPointerOffsetOperand); b0.AppendInstruction(loadInstruction, opInstance, thisOperand, instanceOffsetOperand); b0.AppendInstruction(compareInstruction, ConditionCode.Equal, opCompare, opInstance, c0); b0.AppendInstruction(branchInstruction, 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) { var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Architecture.Is32BitPlatform); b3.AppendInstruction(setReturn, null, opReturn); } b3.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock); }
private static void PatchEndInvoke(MethodCompiler methodCompiler) { var start = CreateMethodStructure(methodCompiler); start.First.Insert(new InstructionNode(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock)); }
public bool IsTraceable(int traceLevel) { return(MethodCompiler.IsTraceable(traceLevel)); }
/// <summary> /// Create platform compound move. /// </summary> /// <param name="methodCompiler">The compiler.</param> /// <param name="context">The context.</param> /// <param name="destinationBase">The destination.</param> /// <param name="destination">The destination offset.</param> /// <param name="sourceBase">The source.</param> /// <param name="source">The source offset.</param> /// <param name="size">The size.</param> public abstract void InsertCompoundCopy(MethodCompiler methodCompiler, Context context, Operand destinationBase, Operand destination, Operand sourceBase, Operand source, int size);
/// <summary> /// Stores the on stack. /// </summary> /// <param name="type">The type.</param> /// <returns></returns> public bool StoreOnStack(MosaType type) { return(MethodCompiler.StoreOnStack(type)); }