Ejemplo n.º 1
0
        // 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();
            }
        }
Ejemplo n.º 2
0
 internal void Reference(LabelBlockInfo block)
 {
     References.Add(block);
     if (Definitions.Count > 0)
     {
         ValidateJump(block);
     }
 }
Ejemplo n.º 3
0
 private void CheckRethrow()
 {
     // Rethrow is only valid inside a catch.
     for (LabelBlockInfo j = _labelBlock; j != null; j = j.Parent)
     {
         if (j.Kind == LabelBlockKind.Catch)
         {
             return;
         }
         else if (j.Kind == LabelBlockKind.Finally)
         {
             // Rethrow from inside finally is not verifiable
             break;
         }
     }
     throw Error.RethrowRequiresCatch();
 }
Ejemplo n.º 4
0
        // 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();
            }
        }
 private void PushLabelBlock(LabelBlockKind type) {
     _labelBlock = new LabelBlockInfo(_labelBlock, type);
 }
Ejemplo n.º 6
0
 internal void Reference(LabelBlockInfo block) {
     References.Add(block);
     if (Definitions.Count > 0) {
         ValidateJump(block);
     }
 }
Ejemplo n.º 7
0
 internal LabelBlockInfo(LabelBlockInfo parent, LabelBlockKind kind) {
     Parent = parent;
     Kind = kind;
 }
Ejemplo n.º 8
0
        private void ValidateJump(LabelBlockInfo reference) {
            // Assume we can do a ret/branch
            _opCode = _canReturn ? OpCodes.Ret : OpCodes.Br;

            // look for a simple jump out
            for (LabelBlockInfo j = reference; j != null; j = j.Parent) {
                if (Definitions.Contains(j)) {
                    // found it, jump is valid!
                    return;
                }
                if (j.Kind == LabelBlockKind.Finally ||
                    j.Kind == LabelBlockKind.Filter) {
                    break;
                }
                if (j.Kind == LabelBlockKind.Try ||
                    j.Kind == LabelBlockKind.Catch) {
                    _opCode = OpCodes.Leave;
                }
            }

            _acrossBlockJump = true;
            if (Definitions.Count > 1) {
                throw Error.AmbiguousJump(Node.Name);
            }

            // We didn't find an outward jump. Look for a jump across blocks
            LabelBlockInfo def = Definitions.First();
            LabelBlockInfo common = Helpers.CommonNode(def, reference, b => b.Parent);

            // Assume we can do a ret/branch
            _opCode = _canReturn ? OpCodes.Ret : OpCodes.Br;

            // Validate that we aren't jumping across a finally
            for (LabelBlockInfo j = reference; j != common; j = j.Parent) {
                if (j.Kind == LabelBlockKind.Finally) {
                    throw Error.ControlCannotLeaveFinally();
                }
                if (j.Kind == LabelBlockKind.Filter) {
                    throw Error.ControlCannotLeaveFilterTest();
                }
                if (j.Kind == LabelBlockKind.Try ||
                    j.Kind == LabelBlockKind.Catch) {
                    _opCode = OpCodes.Leave;
                }
            }

            // Valdiate that we aren't jumping into a catch or an expression
            for (LabelBlockInfo j = def; j != common; j = j.Parent) {
                if (j.Kind != LabelBlockKind.Block) {
                    if (j.Kind == LabelBlockKind.Expression) {
                        throw Error.ControlCannotEnterExpression();
                    } else {
                        throw Error.ControlCannotEnterTry();
                    }
                }
            }
        }
Ejemplo n.º 9
0
 private void PushLabelBlock(LabelBlockKind type)
 {
     _labelBlock = new LabelBlockInfo(_labelBlock, type);
 }
Ejemplo n.º 10
0
 internal LabelBlockInfo(LabelBlockInfo parent, LabelBlockKind kind)
 {
     Parent = parent;
     Kind   = kind;
 }
Ejemplo n.º 11
0
        private void ValidateJump(LabelBlockInfo reference)
        {
            // Assume we can do a ret/branch
            _opCode = _canReturn ? OpCodes.Ret : OpCodes.Br;

            // look for a simple jump out
            for (LabelBlockInfo j = reference; j != null; j = j.Parent)
            {
                if (Definitions.Contains(j))
                {
                    // found it, jump is valid!
                    return;
                }
                if (j.Kind == LabelBlockKind.Finally ||
                    j.Kind == LabelBlockKind.Filter)
                {
                    break;
                }
                if (j.Kind == LabelBlockKind.Try ||
                    j.Kind == LabelBlockKind.Catch)
                {
                    _opCode = OpCodes.Leave;
                }
            }

            _acrossBlockJump = true;
            if (Definitions.Count > 1)
            {
                throw Error.AmbiguousJump(Node.Name);
            }

            // We didn't find an outward jump. Look for a jump across blocks
            LabelBlockInfo def    = Definitions.First();
            LabelBlockInfo common = Helpers.CommonNode(def, reference, b => b.Parent);

            // Assume we can do a ret/branch
            _opCode = _canReturn ? OpCodes.Ret : OpCodes.Br;

            // Validate that we aren't jumping across a finally
            for (LabelBlockInfo j = reference; j != common; j = j.Parent)
            {
                if (j.Kind == LabelBlockKind.Finally)
                {
                    throw Error.ControlCannotLeaveFinally();
                }
                if (j.Kind == LabelBlockKind.Filter)
                {
                    throw Error.ControlCannotLeaveFilterTest();
                }
                if (j.Kind == LabelBlockKind.Try ||
                    j.Kind == LabelBlockKind.Catch)
                {
                    _opCode = OpCodes.Leave;
                }
            }

            // Valdiate that we aren't jumping into a catch or an expression
            for (LabelBlockInfo j = def; j != common; j = j.Parent)
            {
                if (j.Kind != LabelBlockKind.Block)
                {
                    if (j.Kind == LabelBlockKind.Expression)
                    {
                        throw Error.ControlCannotEnterExpression();
                    }
                    else
                    {
                        throw Error.ControlCannotEnterTry();
                    }
                }
            }
        }