/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { bool remove = false; foreach (BasicBlock block in BasicBlocks) { for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext()) { if (ctx.Instruction is IR.MoveInstruction || ctx.Instruction is CIL.StlocInstruction) { if (ctx.Operand1 is ConstantOperand) { // HACK: We can't track a constant through a register, so we keep those moves if (ctx.Result is StackOperand) { Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!"); ctx.Result.Replace(ctx.Operand1, InstructionSet); remove = true; } } } else if (ctx.Instruction is IR.PhiInstruction) { IR.PhiInstruction phi = (IR.PhiInstruction)ctx.Instruction; ConstantOperand co = ctx.Operand2 as ConstantOperand; List <BasicBlock> blocks = ctx.Other as List <BasicBlock>; // FIXME PG / ctx has moved if (co != null && blocks.Count == 1) { // We can remove the phi, as it is only defined once // HACK: We can't track a constant through a register, so we keep those moves if (!ctx.Result.IsRegister) { Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!"); ctx.Result.Replace(co, InstructionSet); remove = true; } } } // Shall we remove this instruction? if (remove) { ctx.Remove(); remove = false; } } } }
/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { bool remove = false; foreach (BasicBlock block in BasicBlocks) { for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext()) { if (ctx.Instruction is IR.MoveInstruction || ctx.Instruction is CIL.StlocInstruction) { if (ctx.Operand1 is ConstantOperand) { // HACK: We can't track a constant through a register, so we keep those moves if (ctx.Result is StackOperand) { Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!"); ctx.Result.Replace(ctx.Operand1, InstructionSet); remove = true; } } } else if (ctx.Instruction is IR.PhiInstruction) { IR.PhiInstruction phi = (IR.PhiInstruction)ctx.Instruction; ConstantOperand co = ctx.Operand2 as ConstantOperand; List<BasicBlock> blocks = ctx.Other as List<BasicBlock>; // FIXME PG / ctx has moved if (co != null && blocks.Count == 1) { // We can remove the phi, as it is only defined once // HACK: We can't track a constant through a register, so we keep those moves if (!ctx.Result.IsRegister) { Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!"); ctx.Result.Replace(co, InstructionSet); remove = true; } } } // Shall we remove this instruction? if (remove) { ctx.Remove(); remove = false; } } } }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Dup"/>. /// </summary> /// <param name="ctx">The context.</param> void ICILVisitor.Dup(Context ctx) { // We don't need the dup anymore. //Remove(ctx); ctx.Remove (); }
/// <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="ctx">Provides the transformation context.</param> private void ProcessLoadInstruction(Context ctx) { // We don't need to rewire the source/destination yet, its already there. :( //Remove(ctx); ctx.Remove (); }
/// <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> /// Replaces the IL load instruction by an appropriate IR move instruction or removes it entirely, if /// it is a native size. /// </summary> /// <param name="ctx">Provides the transformation context.</param> private void ProcessLoadInstruction(Context ctx) { // We don't need to rewire the source/destination yet, its already there. :( //Remove(ctx); ctx.Remove(); /* FIXME: This is only valid with reg alloc! Type type = null; load = load as LoadInstruction; // Is this a sign or zero-extending move? if (IsSignExtending(load.Source)) { type = typeof(IR.SignExtendedMoveInstruction); } else if (IsZeroExtending(load.Source)) { type = typeof(IR.ZeroExtendedMoveInstruction); } // Do we have a move replacement? if (null == type) { // No, we can safely drop the load instruction and can rewire the operands. /*if (1 == load.Destination.Definitions.Count && 1 == load.Destination.Uses.Count) { load.Destination.Replace(load.Source); Remove(ctx); } return; } else { Replace(ctx, Architecture.CreateInstruction(type, load.Destination, load.Source)); }*/ }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Call"/>. /// </summary> /// <param name="ctx">The context.</param> void ICILVisitor.Call(Context ctx) { if (this.CanSkipDueToRecursiveSystemObjectCtorCall(ctx) == true) { ctx.Remove(); return; } if (this.ProcessIntrinsicCall(ctx) == false) { // Create a symbol operand for the invocation target RuntimeMethod invokeTarget = ctx.InvokeTarget; SymbolOperand symbolOperand = SymbolOperand.FromMethod(invokeTarget); this.ProcessInvokeInstruction(ctx, symbolOperand, ctx.Result, new List<Operand>(ctx.Operands)); } }
/// <summary> /// Visitation function for Call instruction. /// </summary> /// <param name="context">The context.</param> void CIL.ICILVisitor.Call(Context context) { if (this.CanSkipDueToRecursiveSystemObjectCtorCall(context)) { context.Remove(); return; } //if (ProcessVmCall(context)) // return; if (ProcessExternalCall(context)) return; // Create a symbol operand for the invocation target RuntimeMethod invokeTarget = context.InvokeTarget; SymbolOperand symbolOperand = SymbolOperand.FromMethod(invokeTarget); ProcessInvokeInstruction(context, symbolOperand, context.Result, new List<Operand>(context.Operands)); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> public void ReplaceIntrinsicCall(Context context) { // context.SetInstruction(IR.Instruction.JmpInstruction, ); context.Remove(); }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> public void ReplaceIntrinsicCall(Context context) { // TODO context.Remove(); }
/// <summary> /// Visitation function for Ldloc instruction. /// </summary> /// <param name="context">The context.</param> public void Ldloc(Context context) { if (context.Ignore) { context.Remove(); } else { this.ProcessLoadInstruction(context); } }
/// <summary> /// Visitation function for Pop instruction. /// </summary> /// <param name="context">The context.</param> void CIL.ICILVisitor.Pop(Context context) { context.Remove(); }
/// <summary> /// Visitation function for Dup instruction. /// </summary> /// <param name="context">The context.</param> void CIL.ICILVisitor.Dup(Context context) { // We don't need the dup anymore. //Remove(context); context.Remove(); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Pop"/>. /// </summary> /// <param name="ctx">The context.</param> void ICILVisitor.Pop(Context ctx) { ctx.Remove (); }
/// <summary> /// Visitation function for <see cref="ICILVisitor.Ldloc"/>. /// </summary> /// <param name="ctx">The context.</param> public void Ldloc(Context ctx) { if (ctx.Ignore == true) { ctx.Remove(); } else { this.ProcessLoadInstruction(ctx); } }
/// <summary> /// Replaces the instrinsic call site /// </summary> /// <param name="context">The context.</param> /// <param name="typeSystem">The type system.</param> public void ReplaceIntrinsicCall(Context context, ITypeSystem typeSystem) { // TODO context.Remove(); }
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]); } }