/// <summary>
            /// Adds yield target to the current try statement and returns the label
            /// to which the outer code must jump to to route properly to this label.
            /// </summary>
            internal TargetLabel AddYieldTarget(TargetLabel label, int index) {
                switch (State) {
                    case TryStatementState.Try:
                        return _statement.AddTryYieldTarget(label, index);
                    case TryStatementState.Handler:
                        return _statement.AddCatchYieldTarget(label, index, _handler);
                    case TryStatementState.Finally:
                        return _statement.AddFinallyYieldTarget(label, index);

                    default:
                        Debug.Assert(false, "Invalid try statement state " + State.ToString());
                        throw new System.InvalidOperationException();
                }
            }
Example #2
0
        protected internal override void PostWalk(YieldStatement node)
        {
            // Assign the yield statement index for codegen
            int index = _topTargets.Count;
            TargetLabel label = new TargetLabel();
            node.Target = new YieldTarget(index, label);

            foreach (ExceptionBlock eb in _tryBlocks) {
                // The exception statement must determine
                // the label for the enclosing code to jump to
                // to return to the given yield target

                label = eb.AddYieldTarget(label, index);
            }

            // Insert the top target to the top yields
            Debug.Assert(_topTargets.Count == index);
            _topTargets.Add(new YieldTarget(index, label));
        }
Example #3
0
 public YieldTarget(int index, TargetLabel label)
 {
     _index = index;
     _target = label;
 }
Example #4
0
 private TargetLabel EnsureTopTarget()
 {
     if (_target == null) {
         _target = new TargetLabel();
     }
     return _target;
 }
Example #5
0
        internal TargetLabel AddTryYieldTarget(TargetLabel label, int index)
        {
            // Yield inside try stays inside try block, so we need to
            // remember the target label.

            AddYieldTarget(ref _tryYields, label, index);
            return EnsureTopTarget();
        }
Example #6
0
 internal TargetLabel AddFinallyYieldTarget(TargetLabel label, int index)
 {
     // Yields inside finally stay inside finally so we need to keep track
     // of them.
     AddYieldTarget(ref _finallyYields, label, index);
     return EnsureTopTarget();
 }
Example #7
0
        internal TargetLabel AddCatchYieldTarget(TargetLabel label, int index, int handler)
        {
            // Yields inside catch blocks are hoisted out of the catch.
            // If the catch block has a finally, though, it will get wrapped in
            // another try block, in which case the direct jump is not possible
            // and code must route through the top target.

            Debug.Assert(_handlers != null && handler < _handlers.Count);
            CatchBlock cb = _handlers[handler];

            cb.Yield = true;
            _yieldInCatch = true;

            if (_finally != null) {
                AddYieldTarget(ref _catchYields, label, index);
                return EnsureTopTarget();
            } else {
                return label;
            }
        }
Example #8
0
 internal static void AddYieldTarget(ref List<YieldTarget> list, TargetLabel target, int index)
 {
     if (list == null) {
         list = new List<YieldTarget>();
     }
     list.Add(new YieldTarget(index, target));
 }
Example #9
0
 public YieldTarget(int index, TargetLabel label)
 {
     _index  = index;
     _target = label;
 }