1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Diagnostics; 6 using System.Collections.Generic; 7 using System.Globalization; 8 9 namespace System.Linq.Expressions.Interpreter 10 { 11 internal readonly struct RuntimeLabel 12 { 13 public readonly int Index; 14 public readonly int StackDepth; 15 public readonly int ContinuationStackDepth; 16 RuntimeLabelSystem.Linq.Expressions.Interpreter.RuntimeLabel17 public RuntimeLabel(int index, int continuationStackDepth, int stackDepth) 18 { 19 Index = index; 20 ContinuationStackDepth = continuationStackDepth; 21 StackDepth = stackDepth; 22 } 23 ToStringSystem.Linq.Expressions.Interpreter.RuntimeLabel24 public override string ToString() 25 { 26 return string.Format(CultureInfo.InvariantCulture, "->{0} C({1}) S({2})", Index, ContinuationStackDepth, StackDepth); 27 } 28 } 29 30 internal sealed class BranchLabel 31 { 32 internal const int UnknownIndex = int.MinValue; 33 internal const int UnknownDepth = int.MinValue; 34 35 private int _targetIndex = UnknownIndex; 36 private int _stackDepth = UnknownDepth; 37 private int _continuationStackDepth = UnknownDepth; 38 39 // Offsets of forward branching instructions targeting this label 40 // that need to be updated after we emit the label. 41 private List<int> _forwardBranchFixups; 42 43 internal int LabelIndex { get; set; } = UnknownIndex; 44 internal bool HasRuntimeLabel => LabelIndex != UnknownIndex; 45 internal int TargetIndex => _targetIndex; 46 ToRuntimeLabel()47 internal RuntimeLabel ToRuntimeLabel() 48 { 49 Debug.Assert(_targetIndex != UnknownIndex && _stackDepth != UnknownDepth && _continuationStackDepth != UnknownDepth); 50 return new RuntimeLabel(_targetIndex, _continuationStackDepth, _stackDepth); 51 } 52 Mark(InstructionList instructions)53 internal void Mark(InstructionList instructions) 54 { 55 //ContractUtils.Requires(_targetIndex == UnknownIndex && _stackDepth == UnknownDepth && _continuationStackDepth == UnknownDepth); 56 57 _stackDepth = instructions.CurrentStackDepth; 58 _continuationStackDepth = instructions.CurrentContinuationsDepth; 59 _targetIndex = instructions.Count; 60 61 if (_forwardBranchFixups != null) 62 { 63 foreach (int branchIndex in _forwardBranchFixups) 64 { 65 FixupBranch(instructions, branchIndex); 66 } 67 _forwardBranchFixups = null; 68 } 69 } 70 AddBranch(InstructionList instructions, int branchIndex)71 internal void AddBranch(InstructionList instructions, int branchIndex) 72 { 73 Debug.Assert(((_targetIndex == UnknownIndex) == (_stackDepth == UnknownDepth))); 74 Debug.Assert(((_targetIndex == UnknownIndex) == (_continuationStackDepth == UnknownDepth))); 75 76 if (_targetIndex == UnknownIndex) 77 { 78 if (_forwardBranchFixups == null) 79 { 80 _forwardBranchFixups = new List<int>(); 81 } 82 _forwardBranchFixups.Add(branchIndex); 83 } 84 else 85 { 86 FixupBranch(instructions, branchIndex); 87 } 88 } 89 FixupBranch(InstructionList instructions, int branchIndex)90 internal void FixupBranch(InstructionList instructions, int branchIndex) 91 { 92 Debug.Assert(_targetIndex != UnknownIndex); 93 instructions.FixupBranch(branchIndex, _targetIndex - branchIndex); 94 } 95 } 96 } 97