/// <summary> /// <para>Pops a value off the stack and branches to the label at the index of that value in the given labels.</para> /// <para>If the value is out of range, execution falls through to the next instruction.</para> /// </summary> public Emit <DelegateType> Switch(params Label[] labels) { if (labels == null) { throw new ArgumentNullException("labels"); } if (labels.Length == 0) { throw new ArgumentException("labels must have at least one element"); } if (LinqAlternative.Any(labels, l => ((IOwned)l).Owner is DisassembledOperations <DelegateType>)) { return (Switch(LinqAlternative.Select(labels, l => l.Name).ToArray())); } foreach (var label in labels) { if (((IOwned)label).Owner != this) { FailOwnership(label); } } foreach (var label in labels) { UnusedLabels.Remove(label); } var transitions = new[] { new StackTransition(new [] { typeof(int) }, TypeHelpers.EmptyTypes), new StackTransition(new [] { typeof(NativeIntType) }, TypeHelpers.EmptyTypes), }; var labelsCopy = ((LinqArray <Label>)labels).Select(l => l).ToArray(); UpdateOpCodeDelegate update; UpdateState(OpCodes.Switch, labelsCopy, Wrap(transitions, "Switch"), out update); var valid = CurrentVerifiers.ConditionalBranch(labels); if (!valid.Success) { throw new SigilVerificationException("Switch", valid, IL.Instructions(AllLocals)); } foreach (var label in labels) { Branches.Add(SigilTuple.Create(OpCodes.Switch, label, IL.Index)); BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Switch); } return(this); }
/// <summary> /// <para>Pops one argument from the stack, branches to the given label if the value is true.</para> /// <para>A value is true if it is non-zero or non-null.</para> /// </summary> public Emit <DelegateType> BranchIfTrue(Label label) { if (label == null) { throw new ArgumentNullException("label"); } if (((IOwned)label).Owner != this) { if (((IOwned)label).Owner is DisassembledOperations <DelegateType> ) { return(BranchIfTrue(label.Name)); } FailOwnership(label); } UnusedLabels.Remove(label); var transitions = new[] { new StackTransition(new [] { typeof(WildcardType) }, TypeHelpers.EmptyTypes) }; UpdateOpCodeDelegate update; UpdateState(OpCodes.Brtrue, label, Wrap(transitions, "BranchIfTrue"), out update); var valid = CurrentVerifiers.ConditionalBranch(label); if (!valid.Success) { throw new SigilVerificationException("BranchIfTrue", valid, IL.Instructions(AllLocals)); } Branches.Add(SigilTuple.Create(OpCodes.Brtrue, label, IL.Index)); BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Brtrue); 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 less than the first value (when treated as unsigned values). /// </summary> public Emit <DelegateType> UnsignedBranchIfLess(Label label) { if (label == null) { throw new ArgumentNullException("label"); } if (((IOwned)label).Owner != this) { if (((IOwned)label).Owner is DisassembledOperations <DelegateType> ) { return(UnsignedBranchIfLess(label.Name)); } FailOwnership(label); } UnusedLabels.Remove(label); UpdateOpCodeDelegate update; UpdateState(OpCodes.Blt_Un, label, BranchComparableTransitions("UnsignedBranchIfLess"), out update); var valid = CurrentVerifiers.ConditionalBranch(label); if (!valid.Success) { throw new SigilVerificationException("UnsignedBranchIfLess", valid, IL.Instructions(AllLocals)); } Branches.Add(SigilTuple.Create(OpCodes.Blt_Un, label, IL.Index)); BranchPatches[IL.Index] = SigilTuple.Create(label, update, OpCodes.Blt_Un); return(this); }