Ejemplo n.º 1
0
 public override BoundNode VisitBlock(BoundBlock node)
 {
     var rewrittenLocals = node.Locals.WhereAsArray(local => local.IsCompilerGenerated || local.Name == null || this.GetVariable(local.Name) == null);
     var rewrittenLocalFunctions = node.LocalFunctions;
     var rewrittenStatements = VisitList(node.Statements);
     return node.Update(rewrittenLocals, rewrittenLocalFunctions, rewrittenStatements);
 }
Ejemplo n.º 2
0
        internal static BoundNode Rewrite(CSharpCompilation compilation, EENamedTypeSymbol container, HashSet<LocalSymbol> declaredLocals, BoundNode node)
        {
            var builder = ArrayBuilder<BoundStatement>.GetInstance();
            bool hasChanged;

            // Rewrite top-level declarations only.
            switch (node.Kind)
            {
                case BoundKind.LocalDeclaration:
                    RewriteLocalDeclaration(compilation, container, declaredLocals, builder, (BoundLocalDeclaration)node);
                    hasChanged = true;
                    break;
                case BoundKind.MultipleLocalDeclarations:
                    foreach (var declaration in ((BoundMultipleLocalDeclarations)node).LocalDeclarations)
                    {
                        RewriteLocalDeclaration(compilation, container, declaredLocals, builder, declaration);
                    }
                    hasChanged = true;
                    break;
                default:
                    hasChanged = false;
                    break;
            }

            if (hasChanged)
            {
                node = new BoundBlock(node.Syntax, ImmutableArray<LocalSymbol>.Empty, builder.ToImmutable()) { WasCompilerGenerated = true };
            }

            builder.Free();
            return node;
        }
        internal static BoundStatement AnalyzeMethodBody(MethodBodyCompiler methodCompiler, MethodSymbol method, BoundBlock body, DiagnosticBag diagnostics)
        {
            Debug.Assert(diagnostics != null);

            body = FlowAnalysisPass.Rewrite(method, body, diagnostics);
            var analyzedBody = (BoundBlock)RewritePass.Rewrite(methodCompiler, method.ContainingType, body);
            return RewritePass.InsertPrologueSequencePoint(analyzedBody, method);
        }
Ejemplo n.º 4
0
        internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
        {
            var body = _generateMethodBody(this, diagnostics);
            var compilation = compilationState.Compilation;

            _lazyReturnType = CalculateReturnType(compilation, body);

            // Can't do this until the return type has been computed.
            TypeParameterChecker.Check(this, _allTypeParameters);

            if (diagnostics.HasAnyErrors())
            {
                return;
            }

            DiagnosticsPass.IssueDiagnostics(compilation, body, diagnostics, this);
            if (diagnostics.HasAnyErrors())
            {
                return;
            }

            // Check for use-site diagnostics (e.g. missing types in the signature).
            DiagnosticInfo useSiteDiagnosticInfo = null;
            this.CalculateUseSiteDiagnostic(ref useSiteDiagnosticInfo);
            if (useSiteDiagnosticInfo != null && useSiteDiagnosticInfo.Severity == DiagnosticSeverity.Error)
            {
                diagnostics.Add(useSiteDiagnosticInfo, this.Locations[0]);
                return;
            }

            var declaredLocals = PooledHashSet<LocalSymbol>.GetInstance();
            try
            {
                // Rewrite local declaration statement.
                body = (BoundStatement)LocalDeclarationRewriter.Rewrite(compilation, _container, declaredLocals, body);

                // Verify local declaration names.
                foreach (var local in declaredLocals)
                {
                    Debug.Assert(local.Locations.Length > 0);
                    var name = local.Name;
                    if (name.StartsWith("$", StringComparison.Ordinal))
                    {
                        diagnostics.Add(ErrorCode.ERR_UnexpectedCharacter, local.Locations[0], name[0]);
                        return;
                    }
                }

                // Rewrite references to placeholder "locals".
                body = (BoundStatement)PlaceholderLocalRewriter.Rewrite(compilation, _container, declaredLocals, body);
            }
            finally
            {
                declaredLocals.Free();
            }

            var syntax = body.Syntax;
            var statementsBuilder = ArrayBuilder<BoundStatement>.GetInstance();
            statementsBuilder.Add(body);
            // Insert an implicit return statement if necessary.
            if (body.Kind != BoundKind.ReturnStatement)
            {
                statementsBuilder.Add(new BoundReturnStatement(syntax, expressionOpt: null));
            }

            var localsBuilder = ArrayBuilder<LocalSymbol>.GetInstance();
            var localsSet = PooledHashSet<LocalSymbol>.GetInstance();
            foreach (var local in this.LocalsForBinding)
            {
                Debug.Assert(!localsSet.Contains(local));
                localsBuilder.Add(local);
                localsSet.Add(local);
            }
            foreach (var local in this.Locals)
            {
                if (!localsSet.Contains(local))
                {
                    localsBuilder.Add(local);
                }
            }
            localsSet.Free();

            body = new BoundBlock(syntax, localsBuilder.ToImmutableAndFree(), statementsBuilder.ToImmutableAndFree()) { WasCompilerGenerated = true };

            Debug.Assert(!diagnostics.HasAnyErrors());
            Debug.Assert(!body.HasErrors);

            bool sawLambdas;
            bool sawAwaitInExceptionHandler;
            body = LocalRewriter.Rewrite(
                compilation: this.DeclaringCompilation,
                method: this,
                methodOrdinal: _methodOrdinal,
                containingType: _container,
                statement: body,
                compilationState: compilationState,
                previousSubmissionFields: null,
                allowOmissionOfConditionalCalls: false,
                diagnostics: diagnostics,
                sawLambdas: out sawLambdas,
                sawAwaitInExceptionHandler: out sawAwaitInExceptionHandler);

            Debug.Assert(!sawAwaitInExceptionHandler);

            if (body.HasErrors)
            {
                return;
            }

            // Variables may have been captured by lambdas in the original method
            // or in the expression, and we need to preserve the existing values of
            // those variables in the expression. This requires rewriting the variables
            // in the expression based on the closure classes from both the original
            // method and the expression, and generating a preamble that copies
            // values into the expression closure classes.
            //
            // Consider the original method:
            // static void M()
            // {
            //     int x, y, z;
            //     ...
            //     F(() => x + y);
            // }
            // and the expression in the EE: "F(() => x + z)".
            //
            // The expression is first rewritten using the closure class and local <1>
            // from the original method: F(() => <1>.x + z)
            // Then lambda rewriting introduces a new closure class that includes
            // the locals <1> and z, and a corresponding local <2>: F(() => <2>.<1>.x + <2>.z)
            // And a preamble is added to initialize the fields of <2>:
            //     <2> = new <>c__DisplayClass0();
            //     <2>.<1> = <1>;
            //     <2>.z = z;

            // Rewrite "this" and "base" references to parameter in this method.
            // Rewrite variables within body to reference existing display classes.
            body = (BoundStatement)CapturedVariableRewriter.Rewrite(
                this.SubstitutedSourceMethod.IsStatic ? null : _parameters[0],
                compilation.Conversions,
                _displayClassVariables,
                body,
                diagnostics);

            if (body.HasErrors)
            {
                Debug.Assert(false, "Please add a test case capturing whatever caused this assert.");
                return;
            }

            if (diagnostics.HasAnyErrors())
            {
                return;
            }

            if (sawLambdas)
            {
                var closureDebugInfoBuilder = ArrayBuilder<ClosureDebugInfo>.GetInstance();
                var lambdaDebugInfoBuilder = ArrayBuilder<LambdaDebugInfo>.GetInstance();

                body = LambdaRewriter.Rewrite(
                    loweredBody: body,
                    thisType: this.SubstitutedSourceMethod.ContainingType,
                    thisParameter: _thisParameter,
                    method: this,
                    methodOrdinal: _methodOrdinal,
                    closureDebugInfoBuilder: closureDebugInfoBuilder,
                    lambdaDebugInfoBuilder: lambdaDebugInfoBuilder,
                    slotAllocatorOpt: null,
                    compilationState: compilationState,
                    diagnostics: diagnostics,
                    assignLocals: true);

                // we don't need this information:
                closureDebugInfoBuilder.Free();
                lambdaDebugInfoBuilder.Free();
            }

            // Insert locals from the original method,
            // followed by any new locals.
            var block = (BoundBlock)body;
            var localBuilder = ArrayBuilder<LocalSymbol>.GetInstance();
            foreach (var local in this.Locals)
            {
                Debug.Assert(!(local is EELocalSymbol) || (((EELocalSymbol)local).Ordinal == localBuilder.Count));
                localBuilder.Add(local);
            }
            foreach (var local in block.Locals)
            {
                var oldLocal = local as EELocalSymbol;
                if (oldLocal != null)
                {
                    Debug.Assert(localBuilder[oldLocal.Ordinal] == oldLocal);
                    continue;
                }
                localBuilder.Add(local);
            }

            body = block.Update(localBuilder.ToImmutableAndFree(), block.Statements);
            TypeParameterChecker.Check(body, _allTypeParameters);
            compilationState.AddSynthesizedMethod(this, body);
        }
        /// <summary>
        /// Lower a foreach loop that will enumerate a collection using an enumerator.
        /// 
        /// E e = ((C)(x)).GetEnumerator()
        /// try {
        ///     while (e.MoveNext()) {
        ///         V v = (V)(T)e.Current;
        ///         // body
        ///     }
        /// }
        /// finally {
        ///     // clean up e
        /// }
        /// </summary>
        private BoundStatement RewriteEnumeratorForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            ForEachEnumeratorInfo enumeratorInfo = node.EnumeratorInfoOpt;
            Debug.Assert(enumeratorInfo != null);

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);
            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body);

            TypeSymbol enumeratorType = enumeratorInfo.GetEnumeratorMethod.ReturnType;
            TypeSymbol elementType = enumeratorInfo.ElementType;

            // E e
            LocalSymbol enumeratorVar = new TempLocalSymbol(enumeratorType, RefKind.None, this.containingMethod);

            // Reference to e.
            BoundLocal boundEnumeratorVar = MakeBoundLocal(forEachSyntax, enumeratorVar, enumeratorType);

            // ((C)(x)).GetEnumerator() or (x).GetEnumerator();
            BoundExpression enumeratorVarInitValue = SynthesizeCall(forEachSyntax, rewrittenExpression, enumeratorInfo.GetEnumeratorMethod, enumeratorInfo.CollectionConversion, enumeratorInfo.CollectionType);

            // E e = ((C)(x)).GetEnumerator();
            BoundStatement enumeratorVarDecl = MakeLocalDeclaration(forEachSyntax, enumeratorVar, enumeratorVarInitValue);

            AddForEachExpressionSequencePoint(forEachSyntax, ref enumeratorVarDecl);

            // V v
            LocalSymbol iterationVar = node.IterationVariable;

            //(V)(T)e.Current
            BoundExpression iterationVarAssignValue = SynthesizeConversion(
                syntax: forEachSyntax,
                operand: SynthesizeConversion(
                    syntax: forEachSyntax,
                    operand: BoundCall.Synthesized(
                        syntax: forEachSyntax,
                        receiverOpt: boundEnumeratorVar,
                        method: enumeratorInfo.CurrentPropertyGetter),
                    conversion: enumeratorInfo.CurrentConversion,
                    type: elementType),
                conversion: node.ElementConversion,
                type: iterationVar.Type);

            // V v = (V)(T)e.Current;
            BoundStatement iterationVarDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarAssignValue);

            AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVarDecl);

            // while (e.MoveNext()) {
            //     V v = (V)(T)e.Current;
            //     /* node.Body */
            // }
            BoundStatement whileLoop = RewriteWhileStatement(
                syntax: forEachSyntax,
                rewrittenCondition: BoundCall.Synthesized(
                    syntax: forEachSyntax,
                    receiverOpt: boundEnumeratorVar,
                    method: enumeratorInfo.MoveNextMethod),
                conditionSequencePointSpan: forEachSyntax.InKeyword.Span,
                rewrittenBody: new BoundBlock(rewrittenBody.Syntax,
                    statements: ReadOnlyArray<BoundStatement>.CreateFrom(iterationVarDecl, rewrittenBody),
                    localsOpt: ReadOnlyArray<LocalSymbol>.CreateFrom(iterationVar)),
                breakLabel: node.BreakLabel,
                continueLabel: node.ContinueLabel,
                hasErrors: false);

            BoundStatement result;

            if (enumeratorInfo.DisposeMethodOpt != null)
            {
                BoundBlock finallyBlockOpt;
                var idisposableTypeSymbol = enumeratorInfo.DisposeMethodOpt.ContainingType;
                var conversions = new TypeConversions(this.containingMethod.ContainingAssembly.CorLibrary);

                if (conversions.ClassifyImplicitConversion(enumeratorType, idisposableTypeSymbol).IsImplicit)
                {
                    Debug.Assert(enumeratorInfo.DisposeMethodOpt != null);

                    Conversion receiverConversion = enumeratorType.IsStructType() ?
                        Conversion.Boxing :
                        Conversion.ImplicitReference;

                    // ((IDisposable)e).Dispose(); or e.Dispose();
                    BoundStatement disposeCall = new BoundExpressionStatement(forEachSyntax,
                        expression: SynthesizeCall(forEachSyntax, boundEnumeratorVar, enumeratorInfo.DisposeMethodOpt, receiverConversion, idisposableTypeSymbol));

                    BoundStatement disposeStmt;
                    if (enumeratorType.IsValueType)
                    {
                        // No way for the struct to be nullable and disposable.
                        Debug.Assert(((TypeSymbol)enumeratorType.OriginalDefinition).SpecialType != SpecialType.System_Nullable_T);

                        // For non-nullable structs, no null check is required.
                        disposeStmt = disposeCall;
                    }
                    else
                    {
                        // NB: cast to object missing from spec.  Needed to ignore user-defined operators and box type parameters.
                        // if ((object)e != null) ((IDisposable)e).Dispose(); 
                        disposeStmt = RewriteIfStatement(
                            syntax: forEachSyntax,
                            rewrittenCondition: new BoundBinaryOperator(forEachSyntax,
                                operatorKind: BinaryOperatorKind.NotEqual,
                                left: SynthesizeConversion(
                                    syntax: forEachSyntax,
                                    operand: boundEnumeratorVar,
                                    conversion: enumeratorInfo.EnumeratorConversion,
                                    type: this.compilation.GetSpecialType(SpecialType.System_Object)),
                                right: new BoundLiteral(forEachSyntax,
                                    constantValueOpt: ConstantValue.Null,
                                    type: null),
                                constantValueOpt: null,
                                methodOpt: null,
                                resultKind: LookupResultKind.Viable,
                                type: this.compilation.GetSpecialType(SpecialType.System_Boolean)),
                            rewrittenConsequence: disposeCall,
                            rewrittenAlternativeOpt: null,
                            hasErrors: false);
                    }

                    finallyBlockOpt = new BoundBlock(forEachSyntax,
                        localsOpt: ReadOnlyArray<LocalSymbol>.Null,
                        statements: ReadOnlyArray<BoundStatement>.CreateFrom(disposeStmt));
                }
                else
                {
                    Debug.Assert(!enumeratorType.IsSealed);

                    // IDisposable d
                    LocalSymbol disposableVar = new TempLocalSymbol(idisposableTypeSymbol, RefKind.None, this.containingMethod);

                    // Reference to d.
                    BoundLocal boundDisposableVar = MakeBoundLocal(forEachSyntax, disposableVar, idisposableTypeSymbol);

                    BoundTypeExpression boundIDisposableTypeExpr = new BoundTypeExpression(forEachSyntax,
                        type: idisposableTypeSymbol);

                    // e as IDisposable
                    BoundExpression disposableVarInitValue = new BoundAsOperator(forEachSyntax,
                        operand: boundEnumeratorVar,
                        targetType: boundIDisposableTypeExpr,
                        conversion: Conversion.ExplicitReference, // Explicit so the emitter won't optimize it away.
                        type: idisposableTypeSymbol);

                    // IDisposable d = e as IDisposable;
                    BoundStatement disposableVarDecl = MakeLocalDeclaration(forEachSyntax, disposableVar, disposableVarInitValue);

                    // if (d != null) d.Dispose();
                    BoundStatement ifStmt = RewriteIfStatement(
                        syntax: forEachSyntax,
                        rewrittenCondition: new BoundBinaryOperator(forEachSyntax,
                            operatorKind: BinaryOperatorKind.NotEqual, // reference equality
                            left: boundDisposableVar,
                            right: new BoundLiteral(forEachSyntax,
                                constantValueOpt: ConstantValue.Null,
                                type: null),
                            constantValueOpt: null,
                            methodOpt: null,
                            resultKind: LookupResultKind.Viable,
                            type: this.compilation.GetSpecialType(SpecialType.System_Boolean)),
                        rewrittenConsequence: new BoundExpressionStatement(forEachSyntax,
                            expression: BoundCall.Synthesized(
                                syntax: forEachSyntax,
                                receiverOpt: boundDisposableVar,
                                method: enumeratorInfo.DisposeMethodOpt)),
                        rewrittenAlternativeOpt: null,
                        hasErrors: false);

                    // IDisposable d = e as IDisposable;
                    // if (d != null) d.Dispose();
                    finallyBlockOpt = new BoundBlock(forEachSyntax,
                        localsOpt: ReadOnlyArray<LocalSymbol>.CreateFrom(disposableVar),
                        statements: ReadOnlyArray<BoundStatement>.CreateFrom(disposableVarDecl, ifStmt));
                }

                // try {
                //     while (e.MoveNext()) {
                //         V v = (V)(T)e.Current;
                //         /* loop body */
                //     }
                // }
                // finally {
                //     /* dispose of e */
                // }
                BoundStatement tryFinally = new BoundTryStatement(forEachSyntax,
                    tryBlock: new BoundBlock(forEachSyntax,
                        localsOpt: ReadOnlyArray<LocalSymbol>.Empty,
                        statements: ReadOnlyArray<BoundStatement>.CreateFrom(whileLoop)),
                    catchBlocks: ReadOnlyArray<BoundCatchBlock>.Empty,
                    finallyBlockOpt: finallyBlockOpt);

                // E e = ((C)(x)).GetEnumerator();
                // try {
                //     /* as above */
                result = new BoundBlock(
                    syntax: forEachSyntax,
                    localsOpt: ReadOnlyArray<LocalSymbol>.CreateFrom(enumeratorVar),
                    statements: ReadOnlyArray<BoundStatement>.CreateFrom(enumeratorVarDecl, tryFinally));
            }
            else
            {
                // E e = ((C)(x)).GetEnumerator();
                // while (e.MoveNext()) {
                //     V v = (V)(T)e.Current;
                //     /* loop body */
                // }
                result = new BoundBlock(
                    syntax: forEachSyntax,
                    localsOpt: ReadOnlyArray<LocalSymbol>.CreateFrom(enumeratorVar),
                    statements: ReadOnlyArray<BoundStatement>.CreateFrom(enumeratorVarDecl, whileLoop));
            }

            AddForEachKeywordSequencePoint(forEachSyntax, ref result);

            return result;
        }
        private BoundStatement RewriteMultiDimensionalArrayForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);
            Debug.Assert(collectionExpression.Type.IsArray());

            ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type;

            int rank = arrayType.Rank;
            Debug.Assert(rank > 1);

            TypeSymbol intType = compilation.GetSpecialType(SpecialType.System_Int32);
            TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body);

            // A[...] a
            LocalSymbol arrayVar = new TempLocalSymbol(arrayType, RefKind.None, containingMethod);

            // A[...] a = /*node.Expression*/;
            BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression);

            AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl);

            // Reference to a.
            BoundLocal boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType);

            // int p_0, p_1, ...
            LocalSymbol[] positionVar = new LocalSymbol[rank];
            BoundLocal[] boundPositionVar = new BoundLocal[rank];
            for (int dimension = 0; dimension < rank; dimension++)
            {
                positionVar[dimension] = new TempLocalSymbol(intType, RefKind.None, containingMethod);
                boundPositionVar[dimension] = MakeBoundLocal(forEachSyntax, positionVar[dimension], intType);
            }

            // V v
            LocalSymbol iterationVar = node.IterationVariable;
            TypeSymbol iterationVarType = iterationVar.Type;

            // (V)a[p_0, p_1, ...]
            BoundExpression iterationVarInitValue = SynthesizeConversion(
                syntax: forEachSyntax,
                operand: new BoundArrayAccess(forEachSyntax, 
                    expression: boundArrayVar,
                    indices: ReadOnlyArray<BoundExpression>.CreateFrom((BoundExpression[])boundPositionVar),
                    type: arrayType.ElementType),
                conversion: node.ElementConversion,
                type: iterationVarType);

            // V v = (V)a[p_0, p_1, ...];
            BoundStatement iterationVarDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue);

            AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVarDecl);

            // { V v = (V)a[p_0, p_1, ...]; /* node.Body */ }
            BoundStatement innermostLoopBody = new BoundBlock(forEachSyntax, 
                localsOpt: ReadOnlyArray<LocalSymbol>.CreateFrom(iterationVar),
                statements: ReadOnlyArray<BoundStatement>.CreateFrom(iterationVarDecl, rewrittenBody));

            // Values we'll use every iteration
            MethodSymbol getLowerBoundMethod = (MethodSymbol)this.compilation.GetSpecialTypeMember(SpecialMember.System_Array__GetLowerBound);
            MethodSymbol getUpperBoundMethod = (MethodSymbol)this.compilation.GetSpecialTypeMember(SpecialMember.System_Array__GetUpperBound);

            // work from most-nested to least-nested
            // for (A[...] a = /*node.Expression*/; int p_0 = a.GetLowerBound(0); p_0 <= a.GetUpperBound(0); p_0 = p_0 + 1)
            //     for (int p_1 = a.GetLowerBound(0); p_1 <= a.GetUpperBound(0); p_1 = p_1 + 1)
            //         ...
            //             { V v = (V)a[p_0, p_1, ...]; /* node.Body */ }
            BoundStatement forLoop = null;
            for (int dimension = rank - 1; dimension >= 0; dimension--)
            {
                ReadOnlyArray<BoundExpression> dimensionArgument = ReadOnlyArray<BoundExpression>.CreateFrom(
                    new BoundLiteral(forEachSyntax, 
                        constantValueOpt: ConstantValue.Create(dimension, ConstantValueTypeDiscriminator.Int32),
                        type: intType));

                // a.GetLowerBound(/*dimension*/)
                BoundExpression currentDimensionLowerBound = BoundCall.Synthesized(forEachSyntax, boundArrayVar, getLowerBoundMethod, dimensionArgument);
                // a.GetUpperBound(/*dimension*/) //CONSIDER: dev10 creates a temp for each dimension's upper bound
                BoundExpression currentDimensionUpperBound = BoundCall.Synthesized(forEachSyntax, boundArrayVar, getUpperBoundMethod, dimensionArgument);

                // int p_/*dimension*/ = a.GetLowerBound(/*dimension*/);
                BoundStatement positionVarDecl = MakeLocalDeclaration(forEachSyntax, positionVar[dimension], currentDimensionLowerBound);

                ReadOnlyArray<LocalSymbol> locals;
                BoundStatement initializer;
                GeneratedLabelSymbol breakLabel;

                if (dimension == 0)
                {
                    // outermost for-loop
                    locals = ReadOnlyArray<LocalSymbol>.CreateFrom(arrayVar, positionVar[dimension]);
                    initializer = new BoundStatementList(forEachSyntax, 
                        statements: ReadOnlyArray<BoundStatement>.CreateFrom(arrayVarDecl, positionVarDecl));
                    breakLabel = node.BreakLabel; // i.e. the one that break statements will jump to
                }
                else
                {
                    locals = ReadOnlyArray<LocalSymbol>.CreateFrom(positionVar[dimension]);
                    initializer = positionVarDecl;
                    breakLabel = new GeneratedLabelSymbol("break"); // Should not affect emitted code since unused
                }

                // p_/*dimension*/ <= a.GetUpperBound(/*dimension*/)  //NB: OrEqual
                BoundExpression exitCondition = new BoundBinaryOperator(
                    syntax: forEachSyntax, 
                    operatorKind: BinaryOperatorKind.IntLessThanOrEqual,
                    left: boundPositionVar[dimension],
                    right: currentDimensionUpperBound,
                    constantValueOpt: null, 
                    methodOpt: null, 
                    resultKind: LookupResultKind.Viable, 
                    type: boolType);

                // p_/*dimension*/ = p_/*dimension*/ + 1;
                BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar[dimension], intType);

                BoundStatement body;
                GeneratedLabelSymbol continueLabel;

                if(forLoop == null)
                {
                    // innermost for-loop
                    body = innermostLoopBody;
                    continueLabel = node.ContinueLabel; //i.e. the one continue statements will actually jump to
                }
                else
                {
                    body = forLoop;
                    continueLabel = new GeneratedLabelSymbol("continue"); // Should not affect emitted code since unused
                }

                forLoop = RewriteForStatement(
                    node.Syntax,
                    locals,
                    initializer,
                    exitCondition,
                    forEachSyntax.InKeyword,
                    positionIncrement,
                    body,
                    breakLabel,
                    continueLabel,
                    node.HasErrors);
            }

            Debug.Assert(forLoop != null);

            AddForEachExpressionSequencePoint(forEachSyntax, ref forLoop);

            return forLoop;
        }
Ejemplo n.º 7
0
        private void EmitStatements(BoundBlock node)
        {
            IL.MarkSequencePoint(node.Location);

            foreach (var statement in node.Nodes)
            {
                EmitStatement(statement);
            }
        }
Ejemplo n.º 8
0
        public override BoundNode VisitBlock(BoundBlock node)
        {
            Debug.Assert(EvalStackIsEmpty(), "entering blocks when evaluation stack is not empty?");

            // normally we would not allow stack locals
            // when evaluation stack is not empty.
            DeclareLocals(node.Locals, 0);

            return base.VisitBlock(node);
        }
Ejemplo n.º 9
0
        // used by HandleReturn method which tries to inject 
        // indirect ret sequence as a last statement in the block
        // that is the last statement of the current method
        // NOTE: it is important that there is no code after this "ret"
        //       it is desirable, for debug purposes, that this ret is emitted inside top level { } 
        private bool IsLastBlockInMethod(BoundBlock block)
        {
            if (_boundBody == block)
            {
                return true;
            }

            //sometimes top level node is a statement list containing 
            //epilogue and then a block. If we are having that block, it will do.
            var list = _boundBody as BoundStatementList;
            if (list != null && list.Statements.LastOrDefault() == block)
            {
                return true;
            }

            return false;
        }
Ejemplo n.º 10
0
 public virtual void VisitBlock(BoundBlock node)
 {
     DefaultVisit(node);
 }
Ejemplo n.º 11
0
            public override BoundNode VisitBlock(BoundBlock node)
            {
                // First check whether we have work.

                bool haveWork = false;

                foreach (var temporary in node.Temporaries)
                {
                    if (_statistics[temporary].ShouldReplace)
                    {
                        haveWork = true;
                        break;
                    }
                }

                // If we don't have work, just cascade.
                if (!haveWork)
                    return base.VisitBlock(node);

                // Create a new list of temporaries with the variables to be
                // squelched removed.
                var newTemporaries = new ReadOnlyArray<BoundTemporary>.Builder();
                foreach (var temporary in node.Temporaries)
                {
                    if (_statistics[temporary].ShouldReplace)
                        temporary.Type.MarkUnused();
                    else
                        newTemporaries.Add(temporary);
                }
                var temporaries = newTemporaries.ToReadOnly();

                // Rebuild the nodes with the new rules applied.
                var nodes = new ReadOnlyArray<BoundStatement>.Builder();

                foreach (var statement in node.Nodes)
                {
                    var setVariable = statement as BoundSetVariable;
                    if (setVariable != null)
                    {
                        setVariable = (BoundSetVariable)Visit(setVariable);

                        // If the set variable reduced to an assignment to itself,
                        // remove the set variable. This happens when the variable
                        // of the set variable is replaced.

                        var getVariable = setVariable.Value as BoundGetVariable;
                        if (getVariable != null && setVariable.Variable == getVariable.Variable)
                            continue;

                        // If we're going to squelch this local, remove the
                        // set variable for it.

                        var temporary = setVariable.Variable as BoundTemporary;
                        if (temporary != null && _statistics[temporary].ShouldRemove)
                            continue;
                    }

                    nodes.Add((BoundStatement)Visit(statement));
                }

                // Return the new block.

                return new BoundBlock(temporaries, nodes.ToReadOnly(), node.Location);
            }
Ejemplo n.º 12
0
        // block introduces a new scope
        public override BoundNode VisitBlock(BoundBlock node)
        {
            var rewrittenStatements = VisitList(node.Statements);

            return new BoundBlock(node.Syntax, node.LocalsOpt, rewrittenStatements, node.HasErrors);
        }
Ejemplo n.º 13
0
        internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
        {
            ImmutableArray <LocalSymbol> declaredLocalsArray;
            var body        = _generateMethodBody(this, diagnostics, out declaredLocalsArray, out _lazyResultProperties);
            var compilation = compilationState.Compilation;

            _lazyReturnType = CalculateReturnType(compilation, body);

            // Can't do this until the return type has been computed.
            TypeParameterChecker.Check(this, _allTypeParameters);

            if (diagnostics.HasAnyErrors())
            {
                return;
            }

            DiagnosticsPass.IssueDiagnostics(compilation, body, diagnostics, this);
            if (diagnostics.HasAnyErrors())
            {
                return;
            }

            // Check for use-site diagnostics (e.g. missing types in the signature).
            DiagnosticInfo useSiteDiagnosticInfo = null;

            this.CalculateUseSiteDiagnostic(ref useSiteDiagnosticInfo);
            if (useSiteDiagnosticInfo != null && useSiteDiagnosticInfo.Severity == DiagnosticSeverity.Error)
            {
                diagnostics.Add(useSiteDiagnosticInfo, this.Locations[0]);
                return;
            }

            try
            {
                var declaredLocals = PooledHashSet <LocalSymbol> .GetInstance();

                try
                {
                    // Rewrite local declaration statement.
                    body = (BoundStatement)LocalDeclarationRewriter.Rewrite(
                        compilation,
                        _container,
                        declaredLocals,
                        body,
                        declaredLocalsArray,
                        diagnostics);

                    // Verify local declaration names.
                    foreach (var local in declaredLocals)
                    {
                        Debug.Assert(local.Locations.Length > 0);
                        var name = local.Name;
                        if (name.StartsWith("$", StringComparison.Ordinal))
                        {
                            diagnostics.Add(ErrorCode.ERR_UnexpectedCharacter, local.Locations[0], name[0]);
                            return;
                        }
                    }

                    // Rewrite references to placeholder "locals".
                    body = (BoundStatement)PlaceholderLocalRewriter.Rewrite(compilation, _container, declaredLocals, body, diagnostics);

                    if (diagnostics.HasAnyErrors())
                    {
                        return;
                    }
                }
                finally
                {
                    declaredLocals.Free();
                }

                var syntax            = body.Syntax;
                var statementsBuilder = ArrayBuilder <BoundStatement> .GetInstance();

                statementsBuilder.Add(body);
                // Insert an implicit return statement if necessary.
                if (body.Kind != BoundKind.ReturnStatement)
                {
                    statementsBuilder.Add(new BoundReturnStatement(syntax, RefKind.None, expressionOpt: null));
                }

                var localsBuilder = ArrayBuilder <LocalSymbol> .GetInstance();

                var localsSet = PooledHashSet <LocalSymbol> .GetInstance();

                foreach (var local in this.LocalsForBinding)
                {
                    Debug.Assert(!localsSet.Contains(local));
                    localsBuilder.Add(local);
                    localsSet.Add(local);
                }
                foreach (var local in this.Locals)
                {
                    if (!localsSet.Contains(local))
                    {
                        Debug.Assert(!localsSet.Contains(local));
                        localsBuilder.Add(local);
                        localsSet.Add(local);
                    }
                }
                localsSet.Free();

                body = new BoundBlock(syntax, localsBuilder.ToImmutableAndFree(), statementsBuilder.ToImmutableAndFree())
                {
                    WasCompilerGenerated = true
                };

                Debug.Assert(!diagnostics.HasAnyErrors());
                Debug.Assert(!body.HasErrors);

                bool sawLambdas;
                bool sawLocalFunctions;
                bool sawAwaitInExceptionHandler;
                ImmutableArray <SourceSpan> dynamicAnalysisSpans = ImmutableArray <SourceSpan> .Empty;
                body = LocalRewriter.Rewrite(
                    compilation: this.DeclaringCompilation,
                    method: this,
                    methodOrdinal: _methodOrdinal,
                    containingType: _container,
                    statement: body,
                    compilationState: compilationState,
                    previousSubmissionFields: null,
                    allowOmissionOfConditionalCalls: false,
                    instrumentForDynamicAnalysis: false,
                    debugDocumentProvider: null,
                    dynamicAnalysisSpans: ref dynamicAnalysisSpans,
                    diagnostics: diagnostics,
                    sawLambdas: out sawLambdas,
                    sawLocalFunctions: out sawLocalFunctions,
                    sawAwaitInExceptionHandler: out sawAwaitInExceptionHandler);

                Debug.Assert(!sawAwaitInExceptionHandler);
                Debug.Assert(dynamicAnalysisSpans.Length == 0);

                if (body.HasErrors)
                {
                    return;
                }

                // Variables may have been captured by lambdas in the original method
                // or in the expression, and we need to preserve the existing values of
                // those variables in the expression. This requires rewriting the variables
                // in the expression based on the closure classes from both the original
                // method and the expression, and generating a preamble that copies
                // values into the expression closure classes.
                //
                // Consider the original method:
                // static void M()
                // {
                //     int x, y, z;
                //     ...
                //     F(() => x + y);
                // }
                // and the expression in the EE: "F(() => x + z)".
                //
                // The expression is first rewritten using the closure class and local <1>
                // from the original method: F(() => <1>.x + z)
                // Then lambda rewriting introduces a new closure class that includes
                // the locals <1> and z, and a corresponding local <2>: F(() => <2>.<1>.x + <2>.z)
                // And a preamble is added to initialize the fields of <2>:
                //     <2> = new <>c__DisplayClass0();
                //     <2>.<1> = <1>;
                //     <2>.z = z;

                // Rewrite "this" and "base" references to parameter in this method.
                // Rewrite variables within body to reference existing display classes.
                body = (BoundStatement)CapturedVariableRewriter.Rewrite(
                    this.SubstitutedSourceMethod.IsStatic ? null : _parameters[0],
                    compilation.Conversions,
                    _displayClassVariables,
                    body,
                    diagnostics);

                if (body.HasErrors)
                {
                    Debug.Assert(false, "Please add a test case capturing whatever caused this assert.");
                    return;
                }

                if (diagnostics.HasAnyErrors())
                {
                    return;
                }

                if (sawLambdas || sawLocalFunctions)
                {
                    var closureDebugInfoBuilder = ArrayBuilder <ClosureDebugInfo> .GetInstance();

                    var lambdaDebugInfoBuilder = ArrayBuilder <LambdaDebugInfo> .GetInstance();

                    body = LambdaRewriter.Rewrite(
                        loweredBody: body,
                        thisType: this.SubstitutedSourceMethod.ContainingType,
                        thisParameter: _thisParameter,
                        method: this,
                        methodOrdinal: _methodOrdinal,
                        substitutedSourceMethod: this.SubstitutedSourceMethod.OriginalDefinition,
                        closureDebugInfoBuilder: closureDebugInfoBuilder,
                        lambdaDebugInfoBuilder: lambdaDebugInfoBuilder,
                        slotAllocatorOpt: null,
                        compilationState: compilationState,
                        diagnostics: diagnostics,
                        assignLocals: true);

                    // we don't need this information:
                    closureDebugInfoBuilder.Free();
                    lambdaDebugInfoBuilder.Free();
                }

                // Insert locals from the original method,
                // followed by any new locals.
                var block        = (BoundBlock)body;
                var localBuilder = ArrayBuilder <LocalSymbol> .GetInstance();

                foreach (var local in this.Locals)
                {
                    Debug.Assert(!(local is EELocalSymbol) || (((EELocalSymbol)local).Ordinal == localBuilder.Count));
                    localBuilder.Add(local);
                }
                foreach (var local in block.Locals)
                {
                    var oldLocal = local as EELocalSymbol;
                    if (oldLocal != null)
                    {
                        Debug.Assert(localBuilder[oldLocal.Ordinal] == oldLocal);
                        continue;
                    }
                    localBuilder.Add(local);
                }

                body = block.Update(localBuilder.ToImmutableAndFree(), block.LocalFunctions, block.Statements);
                TypeParameterChecker.Check(body, _allTypeParameters);
                compilationState.AddSynthesizedMethod(this, body);
            }
            catch (BoundTreeVisitor.CancelledByStackGuardException ex)
            {
                ex.AddAnError(diagnostics);
            }
        }
Ejemplo n.º 14
0
 public override BoundNode VisitBlock(BoundBlock node)
 {
     AddVariables(node.Locals);
     return(base.VisitBlock(node));
 }
Ejemplo n.º 15
0
 public override void VisitCFGBlock(BoundBlock x)
 {
     VisitCFGBlockInit(x);
     VisitCFGBlockInternal(x);   // modifies _state, traverses to the edge
 }
Ejemplo n.º 16
0
        protected override void EndBlock(BoundBlock block)
        {
            var blockSyntax = block.Syntax as BlockSyntax;
            if (blockSyntax == null)
            {
                return;
            }

            NoteLocation(blockSyntax.CloseBraceToken.Span);
        }
Ejemplo n.º 17
0
 public override BoundNode VisitBlock(BoundBlock node)
 {
     var newLocals = RewriteLocals(node.Locals);
     var newLocalFunctions = node.LocalFunctions;
     var newStatements = VisitList(node.Statements);
     return node.Update(newLocals, newLocalFunctions, newStatements);
 }
        /// <summary>
        /// Lower a foreach loop that will enumerate the characters of a string.
        /// 
        /// string s = x;
        /// for (int p = 0; p &lt; s.Length; p = p + 1) {
        ///     V v = (V)s.Chars[p];
        ///     // body
        /// }
        /// </summary>
        /// <remarks>
        /// We will follow Dev10 in diverging from the C# 4 spec by ignoring string's 
        /// implementation of IEnumerable and just indexing into its characters.
        /// 
        /// NOTE: We're assuming that sequence points have already been generated.
        /// Otherwise, lowering to for-loops would generated spurious ones.
        /// </remarks>
        private BoundStatement RewriteStringForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);
            TypeSymbol stringType = collectionExpression.Type;
            Debug.Assert(stringType.SpecialType == SpecialType.System_String);

            TypeSymbol intType = compilation.GetSpecialType(SpecialType.System_Int32);
            TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body);

            // string s;
            LocalSymbol stringVar = new TempLocalSymbol(stringType, RefKind.None, containingMethod);
            // int p;
            LocalSymbol positionVar = new TempLocalSymbol(intType, RefKind.None, containingMethod);

            // Reference to s.
            BoundLocal boundStringVar = MakeBoundLocal(forEachSyntax, stringVar, stringType);

            // Reference to p.
            BoundLocal boundPositionVar = MakeBoundLocal(forEachSyntax, positionVar, intType);

            // string s = /*expr*/;
            BoundStatement stringVarDecl = MakeLocalDeclaration(forEachSyntax, stringVar, rewrittenExpression);

            AddForEachExpressionSequencePoint(forEachSyntax, ref stringVarDecl);

            // int p = 0;
            BoundStatement positionVariableDecl = MakeLocalDeclaration(forEachSyntax, positionVar, 
                new BoundLiteral(forEachSyntax, ConstantValue.ConstantValueZero.Int32, intType));

            // string s = /*node.Expression*/; int p = 0;
            BoundStatement initializer = new BoundStatementList(forEachSyntax, 
                statements: ReadOnlyArray<BoundStatement>.CreateFrom(stringVarDecl, positionVariableDecl));

            BoundExpression stringLength = BoundCall.Synthesized(
                    syntax: forEachSyntax,
                    receiverOpt: boundStringVar,
                    method: (MethodSymbol)compilation.GetSpecialTypeMember(SpecialMember.System_String__Length),
                    arguments: ReadOnlyArray<BoundExpression>.Empty);

            // p < s.Length
            BoundExpression exitCondition = new BoundBinaryOperator(
                syntax: forEachSyntax, 
                operatorKind: BinaryOperatorKind.IntLessThan,
                left: boundPositionVar,
                right: stringLength,
                constantValueOpt: null, 
                methodOpt: null, 
                resultKind: LookupResultKind.Viable, 
                type: boolType);

            // p = p + 1;
            BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar, intType);

            LocalSymbol iterationVar = node.IterationVariable;
            TypeSymbol iterationVarType = iterationVar.Type;
            Debug.Assert(node.ElementConversion.Exists);

            // (V)s.Chars[p]
            BoundExpression iterationVarInitValue = SynthesizeConversion(
                syntax: forEachSyntax,
                operand: BoundCall.Synthesized(
                    syntax: forEachSyntax,
                    receiverOpt: boundStringVar,
                    method: (MethodSymbol)this.compilation.GetSpecialTypeMember(SpecialMember.System_String__Chars),
                    arguments: ReadOnlyArray<BoundExpression>.CreateFrom(boundPositionVar)),
                conversion: node.ElementConversion,
                type: iterationVarType);

            // V v = (V)s.Chars[p];
            BoundStatement iterationVarDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue);

            AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVarDecl);

            // { V v = (V)s.Chars[p]; /*node.Body*/ }
            BoundStatement loopBody = new BoundBlock(forEachSyntax,
                localsOpt: ReadOnlyArray<LocalSymbol>.CreateFrom(iterationVar),
                statements: ReadOnlyArray<BoundStatement>.CreateFrom(iterationVarDecl, rewrittenBody));

            // for (string s = /*node.Expression*/, int p = 0; p < s.Length; p = p + 1) {
            //     V v = (V)s.Chars[p];
            //     /*node.Body*/
            // }
            BoundStatement result = RewriteForStatement(
                syntax: forEachSyntax,
                locals: ReadOnlyArray<LocalSymbol>.CreateFrom(stringVar, positionVar),
                rewrittenInitializer: initializer,
                rewrittenCondition: exitCondition,
                conditionSyntax: forEachSyntax.InKeyword,
                rewrittenIncrement: positionIncrement,
                rewrittenBody: loopBody,
                breakLabel: node.BreakLabel,
                continueLabel: node.ContinueLabel, hasErrors: node.HasErrors);

            AddForEachKeywordSequencePoint(forEachSyntax, ref result);

            return result;
        }
Ejemplo n.º 19
0
        private void EmitBlock(BoundBlock block)
        {
            var hasLocals = !block.Locals.IsEmpty;

            if (hasLocals)
            {
                _builder.OpenLocalScope();

                foreach (var local in block.Locals)
                {
                    var declaringReferences = local.DeclaringSyntaxReferences;
                    DefineLocal(local, !declaringReferences.IsEmpty ? (CSharpSyntaxNode)declaringReferences[0].GetSyntax() : block.Syntax);
                }
            }

            foreach (var statement in block.Statements)
            {
                EmitStatement(statement);
            }

            if (_indirectReturnState == IndirectReturnState.Needed &&
                IsLastBlockInMethod(block))
            {
                HandleReturn();
            }

            if (hasLocals)
            {
                foreach (var local in block.Locals)
                {
                    FreeLocal(local);
                }

                _builder.CloseLocalScope();
            }
        }
        /// <summary>
        /// Lower a foreach loop that will enumerate a single-dimensional array.
        /// 
        /// A[] a = x;
        /// for (int p = 0; p &lt; a.Length; p = p + 1) {
        ///     V v = (V)a[p];
        ///     // body
        /// }
        /// </summary>
        /// <remarks>
        /// We will follow Dev10 in diverging from the C# 4 spec by ignoring Array's 
        /// implementation of IEnumerable and just indexing into its elements.
        /// 
        /// NOTE: We're assuming that sequence points have already been generated.
        /// Otherwise, lowering to for-loops would generated spurious ones.
        /// </remarks>
        private BoundStatement RewriteSingleDimensionalArrayForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);
            Debug.Assert(collectionExpression.Type.IsArray());

            ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type;

            Debug.Assert(arrayType.Rank == 1);

            TypeSymbol intType = compilation.GetSpecialType(SpecialType.System_Int32);
            TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body);

            // A[] a
            LocalSymbol arrayVar = new TempLocalSymbol(arrayType, RefKind.None, containingMethod);

            // A[] a = /*node.Expression*/;
            BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression);

            AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl);

            // Reference to a.
            BoundLocal boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType);

            // int p
            LocalSymbol positionVar = new TempLocalSymbol(intType, RefKind.None, containingMethod);

            // Reference to p.
            BoundLocal boundPositionVar = MakeBoundLocal(forEachSyntax, positionVar, intType);

            // int p = 0;
            BoundStatement positionVarDecl = MakeLocalDeclaration(forEachSyntax, positionVar, 
                new BoundLiteral(forEachSyntax, ConstantValue.ConstantValueZero.Int32, intType));

            // V v
            LocalSymbol iterationVar = node.IterationVariable;
            TypeSymbol iterationVarType = iterationVar.Type;

            // (V)a[p]
            BoundExpression iterationVarInitValue = SynthesizeConversion(
                syntax: forEachSyntax,
                operand: new BoundArrayAccess(
                    syntax: forEachSyntax,
                    expression: boundArrayVar,
                    indices: ReadOnlyArray<BoundExpression>.CreateFrom(boundPositionVar),
                    type: arrayType.ElementType),
                conversion: node.ElementConversion,
                type: iterationVarType);

            // V v = (V)a[p];
            BoundStatement iterationVariableDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue);

            AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVariableDecl);

            BoundStatement initializer = new BoundStatementList(forEachSyntax, 
                        statements: ReadOnlyArray<BoundStatement>.CreateFrom(arrayVarDecl, positionVarDecl));

            // a.Length
            BoundExpression arrayLength = new BoundArrayLength(
                syntax: forEachSyntax,
                expression: boundArrayVar,
                type: intType);

            // p < a.Length
            BoundExpression exitCondition = new BoundBinaryOperator(
                syntax: forEachSyntax, 
                operatorKind: BinaryOperatorKind.IntLessThan,
                left: boundPositionVar,
                right: arrayLength,
                constantValueOpt: null, 
                methodOpt: null, 
                resultKind: LookupResultKind.Viable, 
                type: boolType);

            // p = p + 1;
            BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar, intType);

            // { V v = (V)a[p]; /* node.Body */ }
            BoundStatement loopBody = new BoundBlock(forEachSyntax, 
                localsOpt: ReadOnlyArray<LocalSymbol>.CreateFrom(iterationVar),
                statements: ReadOnlyArray<BoundStatement>.CreateFrom(iterationVariableDecl, rewrittenBody));

            // for (A[] a = /*node.Expression*/, int p = 0; p < a.Length; p = p + 1) {
            //     V v = (V)a[p];
            //     /*node.Body*/
            // }
            BoundStatement result = RewriteForStatement(
                syntax: node.Syntax,
                locals: ReadOnlyArray<LocalSymbol>.CreateFrom(arrayVar, positionVar),
                rewrittenInitializer: initializer,
                rewrittenCondition: exitCondition,
                conditionSyntax: forEachSyntax.InKeyword,
                rewrittenIncrement: positionIncrement,
                rewrittenBody: loopBody,
                breakLabel: node.BreakLabel,
                continueLabel: node.ContinueLabel, hasErrors: node.HasErrors);

            AddForEachKeywordSequencePoint(forEachSyntax, ref result);

            return result;
        }
Ejemplo n.º 21
0
 public static void Process(BoundBlock block, Binder binder, ArrayBuilder<string> builder)
 {
     var visitor = new NonMoveableVariableVisitor(binder, builder);
     visitor.Visit(block);
 }
Ejemplo n.º 22
0
        internal ControlFlowGraphVertex(AnalysisEngine engine, SourceRoutineSymbol routine, BoundBlock block)
        {
            this.Engine      = engine;
            this.routine     = routine;
            this.block       = block;
            this.File        = routine.ContainingFile.SyntaxTree.FilePath;
            this.Vid         = this.block.Ordinal + this.File.GetHashCode();
            this.BlockName   = this.block.DebugDisplay;
            this.Kind        = this.block.Kind.ToString();
            this.RoutineName = this.routine.Name;
            this.Statements  = this.block.Statements != null ? block.Statements.Count : 0;
            LangElement l = PhylDiagnosingVisitor.PickFirstSyntaxNode(this.block);

            if (l != null)
            {
                Tuple <int, int> pos = engine.GetLineFromTokenPosition(l.Span.Start, this.File);
                this.Line   = pos.Item1;
                this.Column = pos.Item2;
            }
        }