/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> void IMethodCompilerStage.Run() { if (AreExceptions) return; foreach (var block in this.basicBlocks) { if (block.Label == Int32.MaxValue) continue; for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext()) { if (context.Instruction is PhiInstruction) this.ProcessPhiInstruction(block, context); for (var i = 0; i < context.OperandCount; ++i) { var op = context.GetOperand(i); if (op is SsaOperand) context.SetOperand(i, (op as SsaOperand).Operand); } for (var i = 0; i < context.ResultCount; ++i) { var op = context.GetResult(i); if (op is SsaOperand) context.SetResult(i, (op as SsaOperand).Operand); } } } }
/// <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) { Operand v0 = context.Operand1; Operand v1 = context.Operand2; Operand v2 = context.Operand3; Operand v3 = context.GetOperand(3); Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP); Operand ebp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP); Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX); Operand ebx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX); Operand ecx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX); Operand exceptionRegister = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Object, methodCompiler.Architecture.ExceptionRegister); // Move all virtual registers into physical registers - necessary since stack frame pointer will change context.SetInstruction(X86.Mov, eax, v0); context.AppendInstruction(X86.Mov, ebx, v1); context.AppendInstruction(X86.Mov, ecx, v2); context.AppendInstruction(X86.Mov, exceptionRegister, v3); // Update the frame and stack registers context.AppendInstruction(X86.Mov, ebp, ecx); context.AppendInstruction(X86.Mov, esp, ebx); context.AppendInstruction(X86.Jmp, null, eax); // future - common code (refactor opportunity) context.GotoNext(); // Remove all remaining instructions in block and clear next block list while (!context.IsBlockEndInstruction) { if (!context.IsEmpty) { context.SetInstruction(X86.Nop); } context.GotoNext(); } var nextBlocks = context.Block.NextBlocks; foreach (var next in nextBlocks) { next.PreviousBlocks.Remove(context.Block); } nextBlocks.Clear(); }
/// <summary> /// Returns a <see cref="System.String"/> that represents this instance. /// </summary> /// <param name="context">The context.</param> /// <returns> /// A <see cref="System.String"/> that represents this instance. /// </returns> public virtual string ToString(Context context) { StringBuilder s = new StringBuilder(ToString()); if (context.Other is IR.ConditionCode) { s.Append(" ["); s.Append(GetConditionString(context.ConditionCode)); s.Append("]"); } string mod = GetModifier(context); if (mod != null) { s.Append(" ["); s.Append(mod); s.Append("]"); } if (context.ResultCount != 0) { s.Append(" "); s.Append(context.Result); } if (context.ResultCount > 0 && context.OperandCount > 0) { s.Append(" <-"); } for (int i = 0; (i < 3) && (i < context.OperandCount); i++) { s.Append(" "); s.Append(context.GetOperand(i)); s.Append(","); } if (context.OperandCount > 3) { s.Append(" [more]"); } else if (context.OperandCount > 0) { s.Length = s.Length - 1; } if (context.BranchTargets != null) { for (int i = 0; (i < 2) && (i < context.BranchTargets.Length); i++) { s.Append(String.Format(@" L_{0:X4},", context.BranchTargets[i])); } if (context.BranchTargets.Length > 2) { s.Append(" [more]"); } else if (context.BranchTargets.Length > 0) { s.Length = s.Length - 1; } } if (context.InvokeTarget != null) { s.Append(" {"); s.Append(context.InvokeTarget.ToString()); s.Append("}"); } if (context.RuntimeField != null) { s.Append(" {"); s.Append(context.RuntimeField.ToString()); s.Append("}"); } return s.ToString(); }
/// <summary> /// /// </summary> /// <param name="block"></param> private void RenameVariables(BasicBlock block) { for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext()) { if (!(context.Instruction is PhiInstruction)) { for (var i = 0; i < context.OperandCount; ++i) { var op = context.GetOperand(i); if (!(op is StackOperand)) continue; var name = NameForOperand(context.GetOperand(i)); if (!this.variableInformation.ContainsKey(name)) throw new Exception(name + " is not in dictionary [block = " + block + "]"); var index = this.variableInformation[name].Stack.Peek(); context.SetOperand(i, new SsaOperand(context.GetOperand(i), index)); } } if (PhiPlacementStage.IsAssignmentToStackVariable(context)) { var name = NameForOperand(context.Result); var index = this.variableInformation[name].Count; context.SetResult(new SsaOperand(context.Result, index)); this.variableInformation[name].Stack.Push(index); ++this.variableInformation[name].Count; } } foreach (var s in block.NextBlocks) { var j = this.WhichPredecessor(s, block); for (var context = new Context(this.instructionSet, s); !context.EndOfInstruction; context.GotoNext()) { if (!(context.Instruction is PhiInstruction)) continue; var name = NameForOperand(context.GetOperand(j)); if (this.variableInformation[name].Stack.Count > 0) { var index = this.variableInformation[name].Stack.Peek(); context.SetOperand(j, new SsaOperand(context.GetOperand(j), index)); } } } foreach (var s in this.dominanceCalculationStage.GetChildren(block)) { this.RenameVariables(s); } for (var context = new Context(this.instructionSet, block); !context.EndOfInstruction; context.GotoNext()) { if (PhiPlacementStage.IsAssignmentToStackVariable(context)) { var instName = context.Label + "." + context.Index; var op = this.oldLefHandSide[instName]; var name = NameForOperand(op); this.variableInformation[name].Stack.Pop(); } } }
/// <summary> /// Returns a <see cref="System.String"/> that represents this instance. /// </summary> /// <param name="context">The context.</param> /// <returns> /// A <see cref="System.String"/> that represents this instance. /// </returns> public virtual string ToString(Context context) { StringBuilder s = new StringBuilder(ToString()); if (context.ConditionCode != ConditionCode.Undefined) { s.Append(" ["); s.Append(GetConditionString(context.ConditionCode)); s.Append("]"); } if (context.MosaType != null) { s.Append(" ["); s.Append(context.MosaType.FullName); s.Append("]"); } if (context.MosaField != null) { s.Append(" ["); s.Append(context.MosaField.FullName); s.Append("]"); } string mod = GetModifier(context); if (mod != null) { s.Append(" ["); s.Append(mod); s.Append("]"); } if (context.ResultCount != 0) { s.Append(" "); s.Append(context.Result); if (context.ResultCount == 2) { s.Append(" : "); s.Append(context.Result2); } } if (context.ResultCount > 0 && context.OperandCount > 0) { s.Append(" <="); } for (int i = 0; i < context.OperandCount; i++) { s.Append(" "); s.Append(context.GetOperand(i)); s.Append(","); } if (context.OperandCount > 0) { s.Length = s.Length - 1; } if (context.BranchTargets != null) { for (int i = 0; (i < 2) && (i < context.BranchTargets.Length); i++) { s.Append(String.Format(@" L_{0:X4},", context.BranchTargets[i])); } if (context.BranchTargets.Length > 2) { s.Append(" [more]"); } else if (context.BranchTargets.Length > 0) { s.Length = s.Length - 1; } } if (context.MosaMethod != null) { s.Append(" {"); s.Append(context.MosaMethod.FullName); s.Append("}"); } if (context.MosaField != null) { s.Append(" {"); s.Append(context.MosaField.FullName); s.Append("}"); } return s.ToString(); }
/// <summary> /// Assigns the operands from CIL stack. /// </summary> /// <param name="ctx">The context.</param> /// <param name="currentStack">The current stack.</param> private void AssignOperandsFromCILStack(Context ctx, Stack<Operand> currentStack) { for (int index = ctx.OperandCount - 1; index >= 0; --index) { if (ctx.GetOperand(index) != null) continue; ctx.SetOperand(index, currentStack.Pop()); } }
/// <summary> /// Pops the operands of an instruction from the evaluation stack. /// </summary> /// <param name="ctx">The context.</param> /// <returns>The number of operands popped.</returns> private int PopOperands(Context ctx) { for (int i = ctx.OperandCount - 1; i > -1; i--) { Operand op = ctx.GetOperand(i); Operand evalOp = evaluationStack.Pop(); Debug.Assert(ReferenceEquals(evalOp, op), @"Operand's are not equal?"); } return ctx.OperandCount; }
/// <summary> /// Processes the phi instruction. /// </summary> /// <param name="block">The block.</param> /// <param name="context">The context.</param> private void ProcessPhiInstruction(BasicBlock block, Context context) { for (var predecessorIndex = 0; predecessorIndex < block.PreviousBlocks.Count; ++predecessorIndex) { var predecessor = block.PreviousBlocks[predecessorIndex]; var operand = context.GetOperand(predecessorIndex); this.InsertCopyStatement(predecessor, context.Result, operand); } context.Remove(); }