/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { // Create the prologue block Context ctx = new Context(InstructionSet, -1); // Add a jump instruction to the first block from the prologue ctx.AppendInstruction(IR.Instruction.JmpInstruction); //ctx.AppendInstruction(CIL.Instruction.Get(CIL.OpCode.Br)); ctx.SetBranch(0); ctx.Label = -1; _prologue = CreateBlock(-1, ctx.Index); SplitIntoBlocks(0); // Create the epilogue block ctx = new Context(InstructionSet, -1); // Add null instruction, necessary to generate a block index ctx.AppendInstruction(null); ctx.Ignore = true; ctx.Label = Int32.MaxValue; _epilogue = CreateBlock(Int32.MaxValue, ctx.Index); // Link all the blocks together BuildBlockLinks(_prologue); // Link Exception Header Clauses LinkExceptionHeaderClauses(); }
/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { // Create the prologue block Context ctx = new Context(InstructionSet, -1); // Add a jump instruction to the first block from the prologue //ctx.InsertInstructionAfter(IR.Instruction.JmpInstruction); ctx.AppendInstruction(CIL.Instruction.Get(CIL.OpCode.Br)); ctx.SetBranch(0); ctx.Label = -1; _prologue = CreateBlock(-1, ctx.Index); SplitIntoBlocks(0); // Create the epilogue block ctx = new Context(InstructionSet, -1); // Add null instruction, necessary to generate a block index ctx.AppendInstruction(null); ctx.Ignore = true; ctx.Label = Int32.MaxValue; _epilogue = CreateBlock(Int32.MaxValue, ctx.Index); // Link all the blocks together BuildBlockLinks(_prologue); }
/// <summary> /// Visitation function for <see cref="CIL.ICILVisitor.BinaryBranch"/>. /// </summary> /// <param name="ctx">The context.</param> void CIL.ICILVisitor.BinaryBranch(Context ctx) { bool swap = ctx.Operand1 is ConstantOperand; IBranch branch = ctx.Branch; IR.ConditionCode conditionCode = ConvertCondition((ctx.Instruction as CIL.BinaryBranchInstruction).OpCode); if (swap) { ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Operand2, ctx.Operand1); ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, GetOppositeConditionCode(conditionCode)); } else { ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Operand1, ctx.Operand2); ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, conditionCode); } ctx.SetBranch(branch.Targets[0]); }
/// <summary> /// Visitation function for <see cref="CIL.ICILVisitor.UnaryBranch"/>. /// </summary> /// <param name="ctx">The context.</param> void CIL.ICILVisitor.UnaryBranch(Context ctx) { IBranch branch = ctx.Branch; CIL.OpCode opcode = (ctx.Instruction as CIL.ICILInstruction).OpCode; Operand op = ctx.Operand1; ctx.SetInstruction(CPUx86.Instruction.CmpInstruction, ctx.Operand1, new ConstantOperand(new SigType(CilElementType.I4), 0)); if (opcode == CIL.OpCode.Brtrue || opcode == CIL.OpCode.Brtrue_s) ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.NotEqual); else if (opcode == CIL.OpCode.Brfalse || opcode == CIL.OpCode.Brfalse_s) ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal); else throw new NotImplementedException(); ctx.SetBranch(branch.Targets[0]); }
/// <summary> /// Visitation function for <see cref="CIL.ICILVisitor.Switch"/>. /// </summary> /// <param name="ctx">The context.</param> void CIL.ICILVisitor.Switch(Context ctx) { IBranch branch = ctx.Branch; Operand operand = ctx.Operand1; ctx.Remove(); for (int i = 0; i < branch.Targets.Length - 1; ++i) { ctx.AppendInstruction(CPUx86.Instruction.CmpInstruction, operand, new ConstantOperand(new SigType(CilElementType.I), i)); ctx.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal); ctx.SetBranch(branch.Targets[i]); } }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.ReturnInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> void IR.IIRVisitor.ReturnInstruction(Context ctx) { Operand op = ctx.Operand1; if (op != null) { ICallingConvention cc = Architecture.GetCallingConvention (MethodCompiler.Method.Signature.CallingConvention); cc.MoveReturnValue (ctx, op); ctx.AppendInstruction (CPUx86.Instruction.JmpInstruction); ctx.SetBranch (Int32.MaxValue); } else { ctx.SetInstruction (CPUx86.Instruction.JmpInstruction); ctx.SetBranch (Int32.MaxValue); } }
/// <summary> /// Finds all targets. /// </summary> /// <param name="index">The index.</param> private void SplitIntoBlocks(int index) { Dictionary <int, int> targets = new Dictionary <int, int>(); targets.Add(index, -1); // Find out all targets labels for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext()) { switch (ctx.Instruction.FlowControl) { case FlowControl.Next: continue; case FlowControl.Call: continue; case FlowControl.Break: goto case FlowControl.Branch; case FlowControl.Return: continue; case FlowControl.Throw: goto case FlowControl.Branch; case FlowControl.Branch: // Unconditional branch Debug.Assert(ctx.Branch.Targets.Length == 1); if (!targets.ContainsKey(ctx.Branch.Targets[0])) { targets.Add(ctx.Branch.Targets[0], -1); } continue; case FlowControl.Switch: goto case FlowControl.ConditionalBranch; case FlowControl.ConditionalBranch: // Conditional branch with multiple targets foreach (int target in ctx.Branch.Targets) { if (!targets.ContainsKey(target)) { targets.Add(target, -1); } } int next = ctx.Next.Label; if (!targets.ContainsKey(next)) { targets.Add(next, -1); } continue; default: Debug.Assert(false); break; } } bool slice = false; for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext()) { FlowControl flow; if (targets.ContainsKey(ctx.Label)) { CreateBlock(ctx.Label, ctx.Index); if (!ctx.IsFirstInstruction) { Context prev = ctx.Previous; flow = prev.Instruction.FlowControl; if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch) { prev.AppendInstruction(IR.Instruction.JmpInstruction); prev.SetBranch(ctx.Label); prev.SliceAfter(); } } targets.Remove(ctx.Label); } if (slice) { ctx.SliceBefore(); } flow = ctx.Instruction.FlowControl; slice = (flow == FlowControl.Return || flow == FlowControl.Branch || flow == FlowControl.ConditionalBranch || flow == FlowControl.Break || flow == FlowControl.Throw); } Debug.Assert(targets.Count <= 1); if (FindBlock(0) == null) { CreateBlock(0, index); } }
/// <summary> /// Visitation function for ReturnInstruction. /// </summary> /// <param name="context">The context.</param> void IR.IIRVisitor.ReturnInstruction(Context context) { Operand op = context.Operand1; if (op != null) { callingConvention.MoveReturnValue(context, op); context.AppendInstruction(CPUx86.Instruction.JmpInstruction); context.SetBranch(Int32.MaxValue); } else { context.SetInstruction(CPUx86.Instruction.JmpInstruction); context.SetBranch(Int32.MaxValue); } }
/// <summary> /// Visitation function for <see cref="CIL.ICILVisitor.BinaryBranch"/>. /// </summary> /// <param name="ctx">The context.</param> void CIL.ICILVisitor.BinaryBranch(Context ctx) { bool swap = ctx.Operand1 is ConstantOperand; IBranch branch = ctx.Branch; CIL.OpCode opcode = (ctx.Instruction as CIL.BinaryBranchInstruction).OpCode; IR.ConditionCode conditionCode; if (swap) { int tmp = branch.Targets[0]; branch.Targets[0] = branch.Targets[1]; branch.Targets[1] = tmp; ctx.SetInstruction (CPUx86.Instruction.CmpInstruction, ctx.Operand2, ctx.Operand1); switch (opcode) { // Signed case CIL.OpCode.Beq_s: conditionCode = IR.ConditionCode.NotEqual; break; case CIL.OpCode.Bge_s: conditionCode = IR.ConditionCode.LessThan; break; case CIL.OpCode.Bgt_s: conditionCode = IR.ConditionCode.LessOrEqual; break; case CIL.OpCode.Ble_s: conditionCode = IR.ConditionCode.GreaterThan; break; case CIL.OpCode.Blt_s: conditionCode = IR.ConditionCode.GreaterOrEqual; break; // Unsigned case CIL.OpCode.Bne_un_s: conditionCode = IR.ConditionCode.Equal; break; case CIL.OpCode.Bge_un_s: conditionCode = IR.ConditionCode.UnsignedLessThan; break; case CIL.OpCode.Bgt_un_s: conditionCode = IR.ConditionCode.UnsignedLessOrEqual; break; case CIL.OpCode.Ble_un_s: conditionCode = IR.ConditionCode.UnsignedGreaterThan; break; case CIL.OpCode.Blt_un_s: conditionCode = IR.ConditionCode.UnsignedGreaterOrEqual; break; // Long form signed case CIL.OpCode.Beq: goto case CIL.OpCode.Beq_s; case CIL.OpCode.Bge: goto case CIL.OpCode.Bge_s; case CIL.OpCode.Bgt: goto case CIL.OpCode.Bgt_s; case CIL.OpCode.Ble: goto case CIL.OpCode.Ble_s; case CIL.OpCode.Blt: goto case CIL.OpCode.Blt_s; // Long form unsigned case CIL.OpCode.Bne_un: goto case CIL.OpCode.Bne_un_s; case CIL.OpCode.Bge_un: goto case CIL.OpCode.Bge_un_s; case CIL.OpCode.Bgt_un: goto case CIL.OpCode.Bgt_un_s; case CIL.OpCode.Ble_un: goto case CIL.OpCode.Ble_un_s; case CIL.OpCode.Blt_un: goto case CIL.OpCode.Blt_un_s; default: throw new NotImplementedException (); } ctx.AppendInstruction (CPUx86.Instruction.BranchInstruction, conditionCode); ctx.SetBranch (branch.Targets[0]); } else { ctx.SetInstruction (CPUx86.Instruction.CmpInstruction, ctx.Operand1, ctx.Operand2); switch (opcode) { // Signed case CIL.OpCode.Beq_s: conditionCode = IR.ConditionCode.Equal; break; case CIL.OpCode.Bge_s: conditionCode = IR.ConditionCode.GreaterOrEqual; break; case CIL.OpCode.Bgt_s: conditionCode = IR.ConditionCode.GreaterThan; break; case CIL.OpCode.Ble_s: conditionCode = IR.ConditionCode.LessOrEqual; break; case CIL.OpCode.Blt_s: conditionCode = IR.ConditionCode.LessThan; break; // Unsigned case CIL.OpCode.Bne_un_s: conditionCode = IR.ConditionCode.NotEqual; break; case CIL.OpCode.Bge_un_s: conditionCode = IR.ConditionCode.UnsignedGreaterOrEqual; break; case CIL.OpCode.Bgt_un_s: conditionCode = IR.ConditionCode.UnsignedGreaterThan; break; case CIL.OpCode.Ble_un_s: conditionCode = IR.ConditionCode.UnsignedLessOrEqual; break; case CIL.OpCode.Blt_un_s: conditionCode = IR.ConditionCode.UnsignedLessThan; break; // Long form signed case CIL.OpCode.Beq: goto case CIL.OpCode.Beq_s; case CIL.OpCode.Bge: goto case CIL.OpCode.Bge_s; case CIL.OpCode.Bgt: goto case CIL.OpCode.Bgt_s; case CIL.OpCode.Ble: goto case CIL.OpCode.Ble_s; case CIL.OpCode.Blt: goto case CIL.OpCode.Blt_s; // Long form unsigned case CIL.OpCode.Bne_un: goto case CIL.OpCode.Bne_un_s; case CIL.OpCode.Bge_un: goto case CIL.OpCode.Bge_un_s; case CIL.OpCode.Bgt_un: goto case CIL.OpCode.Bgt_un_s; case CIL.OpCode.Ble_un: goto case CIL.OpCode.Ble_un_s; case CIL.OpCode.Blt_un: goto case CIL.OpCode.Blt_un_s; default: throw new NotImplementedException (); } ctx.AppendInstruction (CPUx86.Instruction.BranchInstruction, conditionCode); ctx.SetBranch (branch.Targets[0]); } ctx.AppendInstruction (CPUx86.Instruction.JmpInstruction); ctx.SetBranch (branch.Targets[1]); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.BinaryBranch"/>. /// </summary> /// <param name="ctx">The context.</param> public void BinaryBranch(Context ctx) { IBranch branch = ctx.Branch; ConditionCode cc = ConvertCondition(((ICILInstruction)ctx.Instruction).OpCode); Operand first = ctx.Operand1; Operand second = ctx.Operand2; IInstruction comparisonInstruction = Instruction.IntegerCompareInstruction; if (first.StackType == StackTypeCode.F) { comparisonInstruction = Instruction.FloatingPointCompareInstruction; } Operand comparisonResult = this.MethodCompiler.CreateTemporary(BuiltInSigType.Int32); ctx.SetInstruction(comparisonInstruction, comparisonResult, first, second); ctx.ConditionCode = cc; ctx.AppendInstruction(Instruction.BranchInstruction, comparisonResult); ctx.ConditionCode = cc; ctx.SetBranch(branch.Targets[0]); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.UnaryBranch"/>. /// </summary> /// <param name="ctx">The context.</param> public void UnaryBranch(Context ctx) { IBranch branch = ctx.Branch; ConditionCode cc; Operand first = ctx.Operand1; Operand second = new ConstantOperand(BuiltInSigType.Int32, 0UL); OpCode opcode = ((ICILInstruction)ctx.Instruction).OpCode; if (opcode == OpCode.Brtrue || opcode == OpCode.Brtrue_s) { cc = ConditionCode.NotEqual; } else if (opcode == OpCode.Brfalse || opcode == OpCode.Brfalse_s) { cc = ConditionCode.Equal; } else { throw new NotSupportedException(@"CILTransformationStage.UnaryBranch doesn't support CIL opcode " + opcode); } Operand comparisonResult = this.MethodCompiler.CreateTemporary(BuiltInSigType.Int32); ctx.SetInstruction(Instruction.IntegerCompareInstruction, comparisonResult, first, second); ctx.ConditionCode = cc; ctx.AppendInstruction(Instruction.BranchInstruction, comparisonResult); ctx.ConditionCode = cc; ctx.SetBranch(branch.Targets[0]); }
/// <summary> /// Visitation function for BinaryBranch instruction. /// </summary> /// <param name="context">The context.</param> public void BinaryBranch(Context context) { IBranch branch = context.Branch; ConditionCode cc = ConvertCondition(((CIL.ICILInstruction)context.Instruction).OpCode); Operand first = context.Operand1; Operand second = context.Operand2; IInstruction comparisonInstruction = Instruction.IntegerCompareInstruction; if (first.StackType == StackTypeCode.F) { comparisonInstruction = Instruction.FloatingPointCompareInstruction; Operand comparisonResult = this.methodCompiler.CreateTemporary(BuiltInSigType.Int32); context.SetInstruction(comparisonInstruction, comparisonResult, first, second); context.ConditionCode = cc; context.AppendInstruction(Instruction.IntegerCompareInstruction, comparisonResult, comparisonResult, new ConstantOperand(new SigType(CilElementType.I), 1)); context.ConditionCode = ConditionCode.Equal; context.AppendInstruction(Instruction.BranchInstruction, comparisonResult); context.ConditionCode = ConditionCode.Equal; context.SetBranch(branch.Targets[0]); context.AppendInstruction(Instruction.JmpInstruction); context.SetBranch(context.Next.Label); } else { Operand comparisonResult = this.methodCompiler.CreateTemporary(BuiltInSigType.Int32); context.SetInstruction(comparisonInstruction, comparisonResult, first, second); context.ConditionCode = cc; context.AppendInstruction(Instruction.BranchInstruction, comparisonResult); context.ConditionCode = cc; context.SetBranch(branch.Targets[0]); } }
public void SwitchInstruction(Context context) { IBranch branch = context.Branch; Operand operand = context.Operand1; context.Remove(); for (int i = 0; i < branch.Targets.Length - 1; ++i) { context.AppendInstruction(CPUx86.Instruction.CmpInstruction, operand, new ConstantOperand(new SigType(CilElementType.I), i)); context.AppendInstruction(CPUx86.Instruction.BranchInstruction, IR.ConditionCode.Equal); context.SetBranch(branch.Targets[i]); } }
/// <summary> /// Visitation function for <see cref="IR.IIRVisitor.ReturnInstruction"/> instruction. /// </summary> /// <param name="ctx">The context.</param> public void ReturnInstruction(Context ctx) { Operand op = ctx.Operand1; if (op != null) { ICallingConvention cc = Architecture.GetCallingConvention(); cc.MoveReturnValue(ctx, op); ctx.AppendInstruction(CPUx86.Instruction.JmpInstruction); ctx.SetBranch(Int32.MaxValue); } else { ctx.SetInstruction(CPUx86.Instruction.JmpInstruction); ctx.SetBranch(Int32.MaxValue); } }