internal void Define(LabelScopeInfo block) { for (LabelScopeInfo info = block; info != null; info = info.Parent) { if (info.ContainsTarget(this._node)) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Label target already defined: {0}", new object[] { this._node.Name })); } } this.AddDefinition(block); block.AddLabelInfo(this._node, this); if (this.HasDefinitions && !this.HasMultipleDefinitions) { foreach (LabelScopeInfo info2 in this._references) { this.ValidateJump(info2); } } else { if (this._acrossBlockJump) { throw new InvalidOperationException("Ambiguous jump"); } this._label = null; } }
internal void Reference(LabelScopeInfo block) { _references.Add(block); if (HasDefinitions) { ValidateJump(block); } }
private LabelScopeInfo FirstDefinition() { LabelScopeInfo scope = _definitions as LabelScopeInfo; if (scope != null) { return(scope); } return(((HashSet <LabelScopeInfo>)_definitions).First()); }
public LightCompiler(int compilationThreshold) { this._locals = new LocalVariables(); this._debugInfos = new List<DebugInfo>(); this._treeLabels = new HybridReferenceDictionary<LabelTarget, LabelInfo>(); this._labelBlock = new LabelScopeInfo(null, LabelScopeKind.Lambda); this._exceptionForRethrowStack = new Stack<ParameterExpression>(); this._instructions = new InstructionList(); this._compilationThreshold = (compilationThreshold < 0) ? 0x20 : compilationThreshold; }
private LabelScopeInfo FirstDefinition() { LabelScopeInfo info = this._definitions as LabelScopeInfo; if (info != null) { return(info); } return(((HashSet <LabelScopeInfo>) this._definitions).First <LabelScopeInfo>()); }
private bool DefinedIn(LabelScopeInfo scope) { if (this._definitions == scope) { return(true); } HashSet <LabelScopeInfo> set = this._definitions as HashSet <LabelScopeInfo>; return((set != null) && set.Contains(scope)); }
private void ValidateJump(LabelScopeInfo reference) { // look for a simple jump out for (LabelScopeInfo j = reference; j != null; j = j.Parent) { if (DefinedIn(j)) { // found it, jump is valid! return; } if (j.Kind == LabelScopeKind.Filter) { break; } } _acrossBlockJump = true; if (HasMultipleDefinitions) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Ambiguous jump {0}", _node.Name)); } // We didn't find an outward jump. Look for a jump across blocks LabelScopeInfo def = FirstDefinition(); LabelScopeInfo common = CommonNode(def, reference, b => b.Parent); // Validate that we aren't jumping across a finally for (LabelScopeInfo j = reference; j != common; j = j.Parent) { if (j.Kind == LabelScopeKind.Filter) { throw new InvalidOperationException("Control cannot leave filter test"); } } // Validate that we aren't jumping into a catch or an expression for (LabelScopeInfo j = def; j != common; j = j.Parent) { if (!j.CanJumpInto) { if (j.Kind == LabelScopeKind.Expression) { throw new InvalidOperationException("Control cannot enter an expression"); } else { throw new InvalidOperationException("Control cannot enter try"); } } } }
private bool DefinedIn(LabelScopeInfo scope) { if (_definitions == scope) { return(true); } HashSet <LabelScopeInfo> definitions = _definitions as HashSet <LabelScopeInfo>; if (definitions != null) { return(definitions.Contains(scope)); } return(false); }
private void AddDefinition(LabelScopeInfo scope) { if (this._definitions == null) { this._definitions = scope; } else { HashSet <LabelScopeInfo> set = this._definitions as HashSet <LabelScopeInfo>; if (set == null) { this._definitions = set = new HashSet <LabelScopeInfo> { (LabelScopeInfo)this._definitions }; } set.Add(scope); } }
private void AddDefinition(LabelScopeInfo scope) { if (_definitions is null) { _definitions = scope; } else { HashSet <LabelScopeInfo> set = _definitions as HashSet <LabelScopeInfo>; if (set is null) { _definitions = set = new HashSet <LabelScopeInfo>() { (LabelScopeInfo)_definitions }; } set.Add(scope); } }
private void ValidateJump(LabelScopeInfo reference) { for (LabelScopeInfo info = reference; info != null; info = info.Parent) { if (this.DefinedIn(info)) { return; } if (info.Kind == LabelScopeKind.Filter) { break; } } this._acrossBlockJump = true; if (this.HasMultipleDefinitions) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Ambiguous jump {0}", new object[] { this._node.Name })); } LabelScopeInfo first = this.FirstDefinition(); LabelScopeInfo info3 = CommonNode <LabelScopeInfo>(first, reference, b => b.Parent); for (LabelScopeInfo info4 = reference; info4 != info3; info4 = info4.Parent) { if (info4.Kind == LabelScopeKind.Filter) { throw new InvalidOperationException("Control cannot leave filter test"); } } for (LabelScopeInfo info5 = first; info5 != info3; info5 = info5.Parent) { if (!info5.CanJumpInto) { if (info5.Kind == LabelScopeKind.Expression) { throw new InvalidOperationException("Control cannot enter an expression"); } throw new InvalidOperationException("Control cannot enter try"); } } }
internal void Define(LabelScopeInfo 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 (LabelScopeInfo j = block; j != null; j = j.Parent) { if (j.ContainsTarget(_node)) { throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Label target already defined: {0}", _node.Name)); } } AddDefinition(block); block.AddLabelInfo(_node, this); // Once defined, validate all jumps if (HasDefinitions && !HasMultipleDefinitions) { 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 new InvalidOperationException("Ambiguous jump"); } // 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 = null; } }
internal LabelScopeInfo(LabelScopeInfo parent, LabelScopeKind kind) { Parent = parent; Kind = kind; }
public void PushLabelBlock(LabelScopeKind type) { this._labelBlock = new LabelScopeInfo(this._labelBlock, type); }
internal LabelScopeInfo(LabelScopeInfo parent, LabelScopeKind kind) { this.Parent = parent; this.Kind = kind; }
public void PopLabelBlock(LabelScopeKind kind) { this._labelBlock = this._labelBlock.Parent; }