/// <summary> /// <para>Leave an exception or catch block, branching to the given label.</para> /// <para>This instruction empties the stack.</para> /// </summary> public Emit <DelegateType> Leave(Label label) { if (label == null) { throw new ArgumentNullException("label"); } if (((IOwned)label).Owner != this) { if (((IOwned)label).Owner is DisassembledOperations <DelegateType> ) { return(Leave(label.Name)); } FailOwnership(label); } if (!TryBlocks.Any(t => t.Value.Item2 == -1) && !CatchBlocks.Any(c => c.Value.Item2 == -1)) { throw new InvalidOperationException("Leave can only be used within an exception or catch block"); } // Note that Leave *always* nuked the stack; nothing survies exiting an exception block UpdateOpCodeDelegate update; UpdateState(OpCodes.Leave, label, Wrap(new[] { new StackTransition(new [] { typeof(PopAllType) }, TypeHelpers.EmptyTypes) }, "Leave"), out update); Branches.Add(SigilTuple.Create(OpCodes.Leave, label, IL.Index)); BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Leave); MustMark = true; var valid = CurrentVerifiers.UnconditionalBranch(label); if (!valid.Success) { throw new SigilVerificationException("Leave", valid, IL.Instructions(AllLocals)); } return(this); }
/// <summary> /// Unconditionally branches to the given label. /// </summary> public Emit <DelegateType> Branch(Label label) { if (label == null) { throw new ArgumentNullException("label"); } if (((IOwned)label).Owner != this) { if (((IOwned)label).Owner is DisassembledOperations <DelegateType> ) { return(Branch(label.Name)); } FailOwnership(label); } UnusedLabels.Remove(label); UpdateOpCodeDelegate update; UpdateState(OpCodes.Br, label, Wrap(StackTransition.None(), "Branch"), out update); var valid = CurrentVerifiers.UnconditionalBranch(label); if (!valid.Success) { throw new SigilVerificationException("Branch", valid, IL.Instructions(AllLocals)); } Branches.Add(SigilTuple.Create(OpCodes.Br, label, IL.Index)); BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Br); MustMark = true; return(this); }
/// <summary> /// Pops two arguments from the stack, branches to the given label if the second value is greater than the first value (when treated as unsigned values). /// </summary> public Emit <DelegateType> UnsignedBranchIfGreater(Label label) { if (label == null) { throw new ArgumentNullException("label"); } if (((IOwned)label).Owner != this) { if (((IOwned)label).Owner is DisassembledOperations <DelegateType> ) { return(UnsignedBranchIfGreater(label.Name)); } FailOwnership(label); } UnusedLabels.Remove(label); UpdateOpCodeDelegate update; UpdateState(OpCodes.Bgt_Un, label, BranchComparableTransitions("UnsignedBranchIfGreater"), out update); var valid = CurrentVerifiers.UnconditionalBranch(label); if (!valid.Success) { throw new SigilVerificationException("UnsignedBranchIfGreater", valid, IL.Instructions(AllLocals)); } Branches.Add(SigilTuple.Create(OpCodes.Bgt_Un, label, IL.Index)); BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Bgt_Un); return(this); }