コード例 #1
0
 internal void Reference(LabelScopeInfo block)
 {
     _references.Add(block);
     if (_definitions.Count > 0)
     {
         ValidateJump(block);
     }
 }
コード例 #2
0
 private void CheckTry()
 {
     // Try inside a filter is not verifiable
     for (LabelScopeInfo j = _labelBlock; j != null; j = j.Parent)
     {
         if (j.Kind == LabelScopeKind.Filter)
         {
             throw Error.TryNotAllowedInFilter();
         }
     }
 }
コード例 #3
0
 private void CheckRethrow()
 {
     // Rethrow is only valid inside a catch.
     for (LabelScopeInfo j = _labelBlock; j != null; j = j.Parent)
     {
         if (j.Kind == LabelScopeKind.Catch)
         {
             return;
         }
         else if (j.Kind == LabelScopeKind.Finally)
         {
             // Rethrow from inside finally is not verifiable
             break;
         }
     }
     throw Error.RethrowRequiresCatch();
 }
コード例 #4
0
        // Returns true if the label was successfully defined
        // or false if the label is now ambiguous
        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 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
                _labelDefined = false;
            }
        }
コード例 #5
0
 private void PushLabelBlock(LabelScopeKind type)
 {
     _labelBlock = new LabelScopeInfo(_labelBlock, type);
 }
コード例 #6
0
 private void PushLabelBlock(LabelScopeKind type) {
     _labelBlock = new LabelScopeInfo(_labelBlock, type);
 }
コード例 #7
0
 internal LabelScopeInfo(LabelScopeInfo parent, LabelScopeKind kind)
 {
     Parent = parent;
     Kind   = kind;
 }
コード例 #8
0
        private void ValidateJump(LabelScopeInfo reference)
        {
            // Assume we can do a ret/branch
            _opCode = _canReturn ? OpCodes.Ret : OpCodes.Br;

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

            _acrossBlockJump = true;
            if (_node != null && _node.Type != typeof(void))
            {
                throw Error.NonLocalJumpWithValue(_node.Name);
            }

            if (_definitions.Count > 1)
            {
                throw Error.AmbiguousJump(_node.Name);
            }

            // We didn't find an outward jump. Look for a jump across blocks
            LabelScopeInfo def    = _definitions.First();
            LabelScopeInfo 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 (LabelScopeInfo j = reference; j != common; j = j.Parent)
            {
                if (j.Kind == LabelScopeKind.Finally)
                {
                    throw Error.ControlCannotLeaveFinally();
                }
                if (j.Kind == LabelScopeKind.Filter)
                {
                    throw Error.ControlCannotLeaveFilterTest();
                }
                if (j.Kind == LabelScopeKind.Try ||
                    j.Kind == LabelScopeKind.Catch)
                {
                    _opCode = OpCodes.Leave;
                }
            }

            // Valdiate 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 Error.ControlCannotEnterExpression();
                    }
                    else
                    {
                        throw Error.ControlCannotEnterTry();
                    }
                }
            }
        }
コード例 #9
0
        private void EmitExpression(Expression node, CompilationFlags flags)
        {
            // When compiling deep trees, we run the risk of triggering a terminating StackOverflowException,
            // so we use the StackGuard utility here to probe for sufficient stack and continue the work on
            // another thread when we run out of stack space.
            if (!_guard.TryEnterOnCurrentStack())
            {
                _guard.RunOnEmptyStack((@this, n, f) => @this.EmitExpression(n, f), this, node, flags);
                return;
            }

            var emitStart            = (flags & CompilationFlags.EmitExpressionStartMask) == CompilationFlags.EmitExpressionStart;
            var labelScopeChangeInfo = GetLabelScopeChangeInfo(emitStart, _labelBlock, node);

            if (labelScopeChangeInfo.HasValue)
            {
                _labelBlock = new LabelScopeInfo(labelScopeChangeInfo.Value.parent, labelScopeChangeInfo.Value.kind);
                DefineBlockLabels(labelScopeChangeInfo.Value.nodes);
            }

            // only pass tail call flags to emit the expression
            flags &= CompilationFlags.EmitAsTailCallMask;

            switch (node.NodeType)
            {
            case ExpressionType.Add:
            case ExpressionType.AddChecked:
            case ExpressionType.And:
            case ExpressionType.ArrayIndex:
            case ExpressionType.Divide:
            case ExpressionType.Equal:
            case ExpressionType.ExclusiveOr:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.LeftShift:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
            case ExpressionType.Modulo:
            case ExpressionType.Multiply:
            case ExpressionType.MultiplyChecked:
            case ExpressionType.NotEqual:
            case ExpressionType.Or:
            case ExpressionType.Power:
            case ExpressionType.RightShift:
            case ExpressionType.Subtract:
            case ExpressionType.SubtractChecked:
                EmitBinaryExpression(node, flags);
                break;

            case ExpressionType.AndAlso:
                EmitAndAlsoBinaryExpression(node, flags);
                break;

            case ExpressionType.OrElse:
                EmitOrElseBinaryExpression(node, flags);
                break;

            case ExpressionType.Coalesce:
                EmitCoalesceBinaryExpression(node);
                break;

            case ExpressionType.Assign:
                EmitAssignBinaryExpression(node);
                break;

            case ExpressionType.ArrayLength:
            case ExpressionType.Decrement:
            case ExpressionType.Increment:
            case ExpressionType.IsFalse:
            case ExpressionType.IsTrue:
            case ExpressionType.Negate:
            case ExpressionType.NegateChecked:
            case ExpressionType.Not:
            case ExpressionType.OnesComplement:
            case ExpressionType.TypeAs:
            case ExpressionType.UnaryPlus:
                EmitUnaryExpression(node, flags);
                break;

            case ExpressionType.Convert:
            case ExpressionType.ConvertChecked:
                EmitConvertUnaryExpression(node, flags);
                break;

            case ExpressionType.Quote:
                EmitQuoteUnaryExpression(node);
                break;

            case ExpressionType.Throw:
                EmitThrowUnaryExpression(node);
                break;

            case ExpressionType.Unbox:
                EmitUnboxUnaryExpression(node);
                break;

            case ExpressionType.Call:
                EmitMethodCallExpression(node, flags);
                break;

            case ExpressionType.Conditional:
                EmitConditionalExpression(node, flags);
                break;

            case ExpressionType.Constant:
                EmitConstantExpression(node);
                break;

            case ExpressionType.Invoke:
                EmitInvocationExpression(node, flags);
                break;

            case ExpressionType.Lambda:
                EmitLambdaExpression(node);
                break;

            case ExpressionType.ListInit:
                EmitListInitExpression(node);
                break;

            case ExpressionType.MemberAccess:
                EmitMemberExpression(node);
                break;

            case ExpressionType.MemberInit:
                EmitMemberInitExpression(node);
                break;

            case ExpressionType.New:
                EmitNewExpression(node);
                break;

            case ExpressionType.NewArrayInit:
            case ExpressionType.NewArrayBounds:
                EmitNewArrayExpression(node);
                break;

            case ExpressionType.Parameter:
                EmitParameterExpression(node);
                break;

            case ExpressionType.TypeEqual:
            case ExpressionType.TypeIs:
                EmitTypeBinaryExpression(node);
                break;

            case ExpressionType.Block:
                EmitBlockExpression(node, flags);
                break;

            case ExpressionType.DebugInfo:
                EmitDebugInfoExpression(node);
                break;

            case ExpressionType.Dynamic:
                EmitDynamicExpression(node);
                break;

            case ExpressionType.Default:
                EmitDefaultExpression(node);
                break;

            case ExpressionType.Goto:
                EmitGotoExpression(node, flags);
                break;

            case ExpressionType.Index:
                EmitIndexExpression(node);
                break;

            case ExpressionType.Label:
                EmitLabelExpression(node, flags);
                break;

            case ExpressionType.RuntimeVariables:
                EmitRuntimeVariablesExpression(node);
                break;

            case ExpressionType.Loop:
                EmitLoopExpression(node);
                break;

            case ExpressionType.Switch:
                EmitSwitchExpression(node, flags);
                break;

            case ExpressionType.Try:
                EmitTryExpression(node);
                break;

            default:
                break;
            }

            if (labelScopeChangeInfo.HasValue)
            {
                _labelBlock = labelScopeChangeInfo.Value.parent;
            }
        }
コード例 #10
0
ファイル: LabelInfo.cs プロジェクト: KonajuGames/SharpLang
 internal void Reference(LabelScopeInfo block) {
     _references.Add(block);
     if (_definitions.Count > 0) {
         ValidateJump(block);
     }
 }
コード例 #11
0
ファイル: LabelInfo.cs プロジェクト: KonajuGames/SharpLang
 internal LabelScopeInfo(LabelScopeInfo parent, LabelScopeKind kind) {
     Parent = parent;
     Kind = kind;
 }
コード例 #12
0
ファイル: LabelInfo.cs プロジェクト: KonajuGames/SharpLang
        private void ValidateJump(LabelScopeInfo reference) {
            // Assume we can do a ret/branch
            _opCode = _canReturn ? OpCodes.Ret : OpCodes.Br;

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

            _acrossBlockJump = true;
            if (_node != null && _node.Type != typeof(void)) {
                throw Error.NonLocalJumpWithValue(_node.Name);
            }

            if (_definitions.Count > 1) {
                throw Error.AmbiguousJump(_node.Name);
            }

            // We didn't find an outward jump. Look for a jump across blocks
            LabelScopeInfo def = _definitions.First();
            LabelScopeInfo 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 (LabelScopeInfo j = reference; j != common; j = j.Parent) {
                if (j.Kind == LabelScopeKind.Finally) {
                    throw Error.ControlCannotLeaveFinally();
                }
                if (j.Kind == LabelScopeKind.Filter) {
                    throw Error.ControlCannotLeaveFilterTest();
                }
                if (j.Kind == LabelScopeKind.Try ||
                    j.Kind == LabelScopeKind.Catch) {
                    _opCode = OpCodes.Leave;
                }
            }

            // Valdiate 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 Error.ControlCannotEnterExpression();
                    } else {
                        throw Error.ControlCannotEnterTry();
                    }
                }
            }
        }
コード例 #13
0
ファイル: LabelInfo.cs プロジェクト: KonajuGames/SharpLang
        // Returns true if the label was successfully defined
        // or false if the label is now ambiguous
        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 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
                _labelDefined = false;
            }
        }