internal LabelInfo(ILGen il, LabelTarget node, bool canReturn) { _ilg = il; Node = node; Label = il.DefineLabel(); _canReturn = canReturn; if (node != null && node.Type != typeof(void)) { Value = il.DeclareLocal(node.Type); } // Until we have more information, default to a leave instruction, which always works _opCode = OpCodes.Leave; }
// Returns true if the label was successfully defined // or false if the label is now ambiguous internal void Define(ILGen il, LabelBlockInfo block) { // Prevent the label from being shadowed, which enforces cleaner // trees. Also we depend on this for simplicity (keeping only one // active IL Label per LabelInfo) for (LabelBlockInfo j = block; j != null; j = j.Parent) { if (j.ContainsTarget(Node)) { throw Error.LabelTargetAlreadyDefined(Node.Name); } } Definitions.Add(block); block.AddLabelInfo(Node, this); // Once defined, validate all jumps if (Definitions.Count == 1) { foreach (var r in References) { ValidateJump(r); } } else { // Was just redefined, if we had any across block jumps, they're // now invalid if (_acrossBlockJump) { throw Error.AmbiguousJump(Node.Name); } // For local jumps, we need a new IL label // This is okay because: // 1. no across block jumps have been made or will be made // 2. we don't allow the label to be shadowed Label = il.DefineLabel(); } }