예제 #1
0
            public AwaitCatchFrame(TypeSystemServices tss, BooCodeBuilder builder, Method currentMethod)
            {
                pendingCaughtException = builder.DeclareTempLocal(currentMethod, tss.ObjectType);
                pendingCatch           = builder.DeclareTempLocal(currentMethod, tss.IntType);

                handlers              = new List <Block>();
                _hoistedLocals        = new Dictionary <InternalLocal, InternalLocal>();
                _orderedHoistedLocals = new List <InternalLocal>();
                _currentMethod        = currentMethod;
            }
예제 #2
0
        public static void UnpackArray(BooCodeBuilder codeBuilder, Method method, Block block, Expression expression, DeclarationCollection declarations)
        {
            ILocalEntity local = expression.Entity as ILocalEntity;

            if (null == local)
            {
                local = codeBuilder.DeclareTempLocal(method,
                                                     expression.ExpressionType);
                block.Add(
                    codeBuilder.CreateAssignment(
                        codeBuilder.CreateReference(local),
                        expression));
            }
            for (int i = 0; i < declarations.Count; ++i)
            {
                Declaration declaration = declarations[i];
                block.Add(
                    codeBuilder.CreateAssignment(
                        codeBuilder.CreateReference(
                            declaration.Entity),
                        codeBuilder.CreateSlicing(
                            codeBuilder.CreateReference(local),
                            i)));
            }
        }
예제 #3
0
            public InternalLabel ProxyReturnIfNeeded(
                Method containingMethod,
                Node valueOpt,
                out InternalLocal retVal)
            {
                retVal = null;

                // no need to proxy returns  at the root
                if (IsRoot())
                {
                    return(null);
                }

                var returnProxy = returnProxyLabel;

                if (returnProxy == null)
                {
                    returnProxyLabel = returnProxy = _builder.CreateLabel(valueOpt ?? containingMethod, "returnProxy", _tryDepth);
                }

                if (valueOpt != null)
                {
                    retVal = returnValue;
                    if (retVal == null)
                    {
                        Debug.Assert(_tryStatementOpt != null);
                        returnValue = retVal = _builder.DeclareTempLocal(
                            containingMethod,
                            ((ITypedEntity)valueOpt.Entity).Type);
                    }
                }

                return(returnProxy);
            }
예제 #4
0
        private Expression VisitExpression(ref BoundSpillSequenceBuilder builder, Expression expression)
        {
            // wrap the node in a spill sequence to mark the fact that it must be moved up the tree.
            // The caller will handle this node type if the result is discarded.
            if (expression != null && expression.NodeType == NodeType.AwaitExpression)
            {
                // we force the await expression to be assigned to a temp variable
                var awaitExpression = (AwaitExpression)expression;
                awaitExpression.BaseExpression = VisitExpression(ref builder, awaitExpression.BaseExpression);

                var local       = _F.DeclareTempLocal(_currentMethod, awaitExpression.ExpressionType);
                var replacement = _F.CreateAssignment(
                    awaitExpression.LexicalInfo,
                    _F.CreateLocalReference(local),
                    awaitExpression);
                if (builder == null)
                {
                    builder = new BoundSpillSequenceBuilder();
                }

                builder.AddLocal(local);
                builder.AddStatement(new ExpressionStatement(replacement));
                return(_F.CreateLocalReference(local));
            }

            var e = Visit(expression);

            if (e == null || e.NodeType != SpillSequenceBuilder)
            {
                return(e);
            }

            var newBuilder = (BoundSpillSequenceBuilder)e;

            if (builder == null)
            {
                builder = newBuilder.Update(null);
            }
            else
            {
                builder.Include(newBuilder);
            }

            return(newBuilder.Value);
        }
예제 #5
0
        public static void UnpackEnumerable(BooCodeBuilder codeBuilder, Method method, Block block, Expression expression, DeclarationCollection declarations)
        {
            TypeSystemServices tss = codeBuilder.TypeSystemServices;

            InternalLocal local = codeBuilder.DeclareTempLocal(method,
                                                               tss.IEnumeratorType);

            IType expressionType = expression.ExpressionType;

            if (expressionType.IsSubclassOf(codeBuilder.TypeSystemServices.IEnumeratorType))
            {
                block.Add(
                    codeBuilder.CreateAssignment(
                        codeBuilder.CreateReference(local),
                        expression));
            }
            else
            {
                if (!expressionType.IsSubclassOf(codeBuilder.TypeSystemServices.IEnumerableType))
                {
                    expression = codeBuilder.CreateMethodInvocation(
                        RuntimeServices_GetEnumerable, expression);
                }

                block.Add(
                    codeBuilder.CreateAssignment(
                        block.LexicalInfo,
                        codeBuilder.CreateReference(local),
                        codeBuilder.CreateMethodInvocation(
                            expression, IEnumerable_GetEnumerator)));
            }

            for (int i = 0; i < declarations.Count; ++i)
            {
                Declaration declaration = declarations[i];

                block.Add(
                    codeBuilder.CreateAssignment(
                        codeBuilder.CreateReference(declaration.Entity),
                        codeBuilder.CreateMethodInvocation(RuntimeServices_MoveNext,
                                                           codeBuilder.CreateReference(local))));
            }
        }
예제 #6
0
            public void HoistLocal(InternalLocal local, BooCodeBuilder F)
            {
                if (!_hoistedLocals.Keys.Any(l => l.Name == local.Name && l.Type == local.Type))
                {
                    _hoistedLocals.Add(local, local);
                    _orderedHoistedLocals.Add(local);
                    return;
                }

                // code uses "await" in two sibling catches with exception filters
                // locals with same names and types may cause problems if they are lifted
                // and become fields with identical signatures.
                // To avoid such problems we will mangle the name of the second local.
                // This will only affect debugging of this extremely rare case.
                var newLocal = F.DeclareTempLocal(_currentMethod, local.Type);

                _hoistedLocals.Add(local, newLocal);
                _orderedHoistedLocals.Add(newLocal);
            }