using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ICSharpCode.Decompiler.IL { /// /// Base class for unconditional and conditional branches. /// class Branch(OpCode opCode, public int TargetILOffset) : ILInstruction(opCode) { public string TargetLabel { get { return CecilExtensions.OffsetToString(TargetILOffset); } } public override bool IsPeeking { get { return false; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode.ToString()); output.Write(' '); output.WriteReference(TargetLabel, TargetILOffset, isLocal: true); } public override bool IsEndReachable { get { // end is reachable for conditional branches, but not unconditional ones return OpCode == OpCode.ConditionalBranch; } } public override void TransformChildren(Func transformFunc) { } public override InstructionFlags Flags { get { return InstructionFlags.MayJump; } } internal override ILInstruction Inline(InstructionFlags flagsBefore, Stack instructionStack, out bool finished) { finished = true; return this; } } /// /// Special instruction for unresolved branches. /// Created by ILReader phase, replaced with TODO when building basic blocks. /// class ConditionalBranch(public ILInstruction Condition, int targetILOffset) : Branch(OpCode.ConditionalBranch, targetILOffset) { public override bool IsPeeking { get { return Condition.IsPeeking; } } public override void WriteTo(ITextOutput output) { base.WriteTo(output); output.Write('('); Condition.WriteTo(output); output.Write(')'); } public override void TransformChildren(Func transformFunc) { Condition = transformFunc(Condition); } internal override ILInstruction Inline(InstructionFlags flagsBefore, Stack instructionStack, out bool finished) { Condition = Condition.Inline(flagsBefore, instructionStack, out finished); return this; } public override InstructionFlags Flags { get { return InstructionFlags.MayJump | Condition.Flags; } } } class ReturnVoidInstruction() : SimpleInstruction(OpCode.Ret) { public override bool IsEndReachable { get { return false; } } public override InstructionFlags Flags { get { return InstructionFlags.MayJump; } } } class ReturnInstruction() : UnaryInstruction(OpCode.Ret) { public override bool IsEndReachable { get { return false; } } public override InstructionFlags Flags { get { return InstructionFlags.MayJump | Operand.Flags; } } } class ThrowInstruction() : UnaryInstruction(OpCode.Throw) { public override bool IsEndReachable { get { return false; } } public override InstructionFlags Flags { get { return InstructionFlags.MayJump | Operand.Flags; } } } }