/// <summary> /// Marks a label in the instruction stream. /// /// When branching, leaving, or switching with a label control will be transfered to where it was *marked* not defined. /// /// Labels can only be marked once, and *must* be marked before creating a delegate. /// </summary> public Emit <DelegateType> MarkLabel(Label label) { if (label == null) { throw new ArgumentNullException("label"); } if (((IOwned)label).Owner != this) { if (((IOwned)label).Owner is DisassembledOperations <DelegateType> ) { return(MarkLabel(label.Name)); } FailOwnership(label); } if (!UnmarkedLabels.Contains(label)) { throw new InvalidOperationException("label [" + label.Name + "] has already been marked, and cannot be marked a second time"); } if (MustMark) { MustMark = false; } var valid = CurrentVerifiers.Mark(label); if (!valid.Success) { throw new SigilVerificationException("MarkLabel", valid, IL.Instructions(AllLocals)); } UnmarkedLabels.Remove(label); IL.MarkLabel(label); Marks[label] = IL.Index; return(this); }
/// <summary> /// Defines a new label. /// /// This label can be used for branching, leave, and switch instructions. /// /// A label must be marked exactly once after being defined, using the MarkLabel() method. /// </summary> public Label DefineLabel(string name = null) { name = name ?? AutoNamer.Next(this, "_label", Locals.Names, Labels.Names); if (CurrentLabels.ContainsKey(name)) { throw new InvalidOperationException("Label with name '" + name + "' already exists"); } var label = IL.DefineLabel(); var ret = new Label(this, label, name); UnusedLabels.Add(ret); UnmarkedLabels.Add(ret); CurrentLabels[name] = ret; return(ret); }