Пример #1
0
        public override BoundNode VisitBlock(BoundBlock node)
        {
            if (!this.Instrument || (node != _rootStatement && (node.WasCompilerGenerated || node.Syntax.Kind() != SyntaxKind.Block)))
            {
                return(node.Update(node.Locals, node.LocalFunctions, VisitList(node.Statements)));
            }

            var builder = ArrayBuilder <BoundStatement> .GetInstance();

            for (int i = 0; i < node.Statements.Length; i++)
            {
                var stmt = (BoundStatement)Visit(node.Statements[i]);
                if (stmt != null)
                {
                    builder.Add(stmt);
                }
            }

            LocalSymbol    synthesizedLocal;
            BoundStatement prologue = _instrumenter.CreateBlockPrologue(node, out synthesizedLocal);

            if (prologue != null)
            {
                builder.Insert(0, prologue);
            }

            BoundStatement epilogue = _instrumenter.CreateBlockEpilogue(node);

            if (epilogue != null)
            {
                builder.Add(epilogue);
            }

            return(new BoundBlock(node.Syntax, synthesizedLocal == null ? node.Locals : node.Locals.Add(synthesizedLocal), node.LocalFunctions, builder.ToImmutableAndFree(), node.HasErrors));
        }
Пример #2
0
        public override BoundNode VisitBlock(BoundBlock node)
        {
            if (node.WasCompilerGenerated || !this.generateDebugInfo)
            {
                return node.Update(node.LocalsOpt, VisitList(node.Statements));
            }

            BlockSyntax syntax = node.Syntax as BlockSyntax;
            Debug.Assert(syntax != null);

            var builder = ArrayBuilder<BoundStatement>.GetInstance();

            var oBspan = syntax.OpenBraceToken.Span;
            builder.Add(new BoundSequencePointWithSpan(syntax, null, oBspan));

            for (int i = 0; i < node.Statements.Length; i++)
            {
                var stmt = (BoundStatement)Visit(node.Statements[i]);
                if (stmt != null) builder.Add(stmt);
            }

            // no need to mark "}" on the outermost block
            // as it cannot leave it normally. The block will have "return" at the end.
            if (syntax.Parent == null || !(syntax.Parent.IsAnonymousFunction() || syntax.Parent is BaseMethodDeclarationSyntax))
            {
                var cBspan = syntax.CloseBraceToken.Span;
                builder.Add(new BoundSequencePointWithSpan(syntax, null, cBspan));
            }

            return new BoundBlock(syntax, node.LocalsOpt, builder.ToImmutableAndFree(), node.HasErrors);
        }
Пример #3
0
        protected BoundBlock RewriteBlock(BoundBlock node, ArrayBuilder <BoundExpression> prologue, ArrayBuilder <LocalSymbol> newLocals)
        {
            AddLocals(node.LocalsOpt, newLocals);

            var newStatements = ArrayBuilder <BoundStatement> .GetInstance();

            if (GenerateDebugInfo && prologue.Count > 0)
            {
                newStatements.Add(new BoundSequencePoint(null, null)
                {
                    WasCompilerGenerated = true
                });
            }

            InsertAndFreePrologue(newStatements, prologue);

            foreach (var statement in node.Statements)
            {
                var replacement = (BoundStatement)this.Visit(statement);
                if (replacement != null)
                {
                    newStatements.Add(replacement);
                }
            }

            // TODO: we may not need to update if there was nothing to rewrite.
            return(node.Update(newLocals.ToImmutableAndFree(), newStatements.ToImmutableAndFree()));
        }
Пример #4
0
        public override BoundNode VisitBlock(BoundBlock node)
        {
            var builder = ArrayBuilder <BoundStatement> .GetInstance();

            VisitStatementSubList(builder, node.Statements);

            if (!this.Instrument || (node != _rootStatement && (node.WasCompilerGenerated || node.Syntax.Kind() != SyntaxKind.Block)))
            {
                return(node.Update(node.Locals, node.LocalFunctions, builder.ToImmutableAndFree()));
            }

            LocalSymbol?   synthesizedLocal;
            BoundStatement?prologue = _instrumenter.CreateBlockPrologue(node, out synthesizedLocal);

            if (prologue != null)
            {
                builder.Insert(0, prologue);
            }
            else if (node == _rootStatement && _factory.TopLevelMethod is SynthesizedSimpleProgramEntryPointSymbol entryPoint)
            {
                builder.Insert(0, _factory.HiddenSequencePoint());
            }

            BoundStatement?epilogue = _instrumenter.CreateBlockEpilogue(node);

            if (epilogue != null)
            {
                builder.Add(epilogue);
            }

            return(new BoundBlock(node.Syntax, synthesizedLocal == null ? node.Locals : node.Locals.Add(synthesizedLocal), node.LocalFunctions, builder.ToImmutableAndFree(), node.HasErrors));
        }
Пример #5
0
        // insert the implicit "return" statement at the end of the method body
        // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
        // ones are going to have sequence points.
        internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, CSharpSyntaxNode syntax = null)
        {
            Debug.Assert(body != null);
            Debug.Assert(method != null);

            if (syntax == null)
            {
                syntax = body.Syntax;
            }

            Debug.Assert(body.WasCompilerGenerated || syntax.IsKind(SyntaxKind.Block) || syntax.IsKind(SyntaxKind.ArrowExpressionClause));

            BoundStatement ret = method.IsIterator
                ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax)
                : BoundReturnStatement.Synthesized(syntax, null);

            // Implicitly added return for async method does not need sequence points since lowering would add one.
            if (syntax.IsKind(SyntaxKind.Block) && !method.IsAsync)
            {
                var blockSyntax = (BlockSyntax)syntax;

                ret = new BoundSequencePointWithSpan(
                    blockSyntax,
                    ret,
                    blockSyntax.CloseBraceToken.Span)
                {
                    WasCompilerGenerated = true
                };
            }

            return(body.Update(body.Locals, body.Statements.Add(ret)));
        }
        internal static BoundBlock Rewrite(SourceMethodSymbol sourceMethodSymbol, MethodContractSyntax contract, BoundBlock body, TypeCompilationState compilationState, DiagnosticBag diagsForCurrentMethod)
        {
            var binder = compilationState.Compilation.GetBinderFactory(sourceMethodSymbol.SyntaxTree)
                                     .GetBinder(body.Syntax);
            SyntheticBoundNodeFactory factory = new SyntheticBoundNodeFactory(sourceMethodSymbol, sourceMethodSymbol.SyntaxNode, compilationState, diagsForCurrentMethod);
            var contractType = compilationState.Compilation.GetTypeByReflectionType(typeof(System.Diagnostics.Contracts.Contract), diagsForCurrentMethod);

            var contractStatements = ArrayBuilder<BoundStatement>.GetInstance(contract.Requires.Count);
            foreach (var requires in contract.Requires)
            {
                var condition = binder.BindExpression(requires.Condition, diagsForCurrentMethod);
                
                var methodCall = factory.StaticCall(contractType, "Requires", condition);
                var statement = factory.ExpressionStatement(methodCall);

                contractStatements.Add(statement);
            }
            foreach (var requires in contract.Ensures)
            {
                var condition = binder.BindExpression(requires.Condition, diagsForCurrentMethod);
                var methodCall = factory.StaticCall(contractType, "Ensures", condition);
                var statement = factory.ExpressionStatement(methodCall);

                contractStatements.Add(statement);
            }

            return body.Update(body.Locals, body.Statements.InsertRange(0, contractStatements.ToImmutableAndFree()));
        }
Пример #7
0
        private static BoundBlock AppendImplicitReturn(
            BoundBlock body,
            MethodSymbol method,
            bool originalBodyNested
            )
        {
            if (originalBodyNested)
            {
                var statements = body.Statements;
                int n          = statements.Length;

                var builder = ArrayBuilder <BoundStatement> .GetInstance(n);

                builder.AddRange(statements, n - 1);
                builder.Add(AppendImplicitReturn((BoundBlock)statements[n - 1], method));

                return(body.Update(
                           body.Locals,
                           ImmutableArray <LocalFunctionSymbol> .Empty,
                           builder.ToImmutableAndFree()
                           ));
            }
            else
            {
                return(AppendImplicitReturn(body, method));
            }
        }
Пример #8
0
        public override BoundNode VisitBlock(BoundBlock node)
        {
            if (!this.Instrument || (node != _rootStatement && (node.WasCompilerGenerated || node.Syntax.Kind() != SyntaxKind.Block)))
            {
                return node.Update(node.Locals, node.LocalFunctions, VisitList(node.Statements));
            }

            var builder = ArrayBuilder<BoundStatement>.GetInstance();

            for (int i = 0; i < node.Statements.Length; i++)
            {
                var stmt = (BoundStatement)Visit(node.Statements[i]);
                if (stmt != null) builder.Add(stmt);
            }

            LocalSymbol synthesizedLocal;
            BoundStatement prologue = _instrumenter.CreateBlockPrologue(node, out synthesizedLocal);
            if (prologue != null)
            {
                builder.Insert(0, prologue);
            }

            BoundStatement epilogue = _instrumenter.CreateBlockEpilogue(node);
            if (epilogue != null)
            {
                builder.Add(epilogue);
            }

            return new BoundBlock(node.Syntax, synthesizedLocal == null ? node.Locals : node.Locals.Add(synthesizedLocal), node.LocalFunctions, builder.ToImmutableAndFree(), node.HasErrors);
        }
Пример #9
0
        internal static BoundBlock FixCodeBlockProblems(LambdaSymbol lambdaSymbol, Binder lambdaBodyBinder, BoundBlock block, DiagnosticBag diagnostics)
        {
            // check for a Lambda that returns a USUAL
            var usualType = lambdaBodyBinder.Compilation.UsualType();

            if (lambdaSymbol.ReturnType != usualType)
            {
                return(block);
            }
            // handle 2 problems:
            // 1) no statements, then add a return statement
            // 2) last statement is a void expression. Then the conversion to USUAL fails
            var count = block.Statements.Length;
            List <BoundStatement> newlist = new List <BoundStatement>();

            if (count == 0)
            {
                var result = new BoundDefaultExpression(block.Syntax, usualType);
                newlist.Add(new BoundReturnStatement(block.Syntax, RefKind.None, result));
                block = block.Update(block.Locals, ImmutableArray <LocalFunctionSymbol> .Empty, newlist.ToImmutableArray <BoundStatement>());
            }
            else
            {
                var stmt = block.Statements[count - 1];
                if (stmt is BoundReturnStatement && stmt.HasErrors)
                {
                    BoundExpression expr = (stmt as BoundReturnStatement).ExpressionOpt;
                    // when the last expression is a conversion to USUAL
                    // and there is an error, then this is most likely the conversion from
                    // a void to USUAL. When that happens, then create an extra stmt in the body of the lambda
                    // store the return expression in an expression statement
                    // and return a NIL
                    if (expr is BoundConversion)
                    {
                        var boundConv = expr as BoundConversion;
                        var operand   = boundConv.Operand;
                        if (boundConv.Type == usualType && operand.Type.SpecialType == SpecialType.System_Void)
                        {
                            diagnostics.Clear();
                            for (int i = 0; i < block.Statements.Length - 1; i++)
                            {
                                newlist.Add(block.Statements[i]);
                            }
                            newlist.Add(new BoundExpressionStatement(stmt.Syntax, operand));
                            var result = new BoundDefaultExpression(stmt.Syntax, usualType);
                            newlist.Add(new BoundReturnStatement(stmt.Syntax, RefKind.None, result));
                            block = new BoundBlock(block.Syntax, block.Locals, newlist.ToImmutableArray <BoundStatement>());
                        }
                    }
                }
            }
            return(block);
        }
Пример #10
0
        // insert the implicit "return" statement at the end of the method body
        // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
        // ones are going to have sequence points.
        internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method)
        {
            Debug.Assert(body != null);
            Debug.Assert(method != null);

            SyntaxNode syntax = body.Syntax;

            Debug.Assert(body.WasCompilerGenerated ||
                         syntax.IsKind(SyntaxKind.Block) ||
                         syntax.IsKind(SyntaxKind.ArrowExpressionClause) ||
                         syntax.IsKind(SyntaxKind.ConstructorDeclaration));

            BoundStatement ret = (method.IsIterator && !method.IsAsync)
                ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax)
                : BoundReturnStatement.Synthesized(syntax, RefKind.None, null);

            return(body.Update(body.Locals, body.LocalFunctions, body.Statements.Add(ret)));
        }
Пример #11
0
        private static BoundBlock PrependImplicitInitializations(BoundBlock body, MethodSymbol method, ImmutableArray <FieldSymbol> implicitlyInitializedFields, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(method.MethodKind == MethodKind.Constructor);
            Debug.Assert(method.ContainingType.IsStructType());

            var F = new SyntheticBoundNodeFactory(method, body.Syntax, compilationState, diagnostics);

            var builder = ArrayBuilder <BoundStatement> .GetInstance(implicitlyInitializedFields.Length);

            foreach (var field in implicitlyInitializedFields)
            {
                builder.Add(
                    F.ExpressionStatement(
                        F.AssignmentExpression(
                            F.Field(F.This(), field),
                            F.Default(field.Type))));
            }
            var initializations = F.HiddenSequencePoint(F.Block(builder.ToImmutableAndFree()));

            return(body.Update(body.Locals, body.LocalFunctions, body.Statements.Insert(index: 0, initializations)));
        }
Пример #12
0
        public override BoundNode VisitBlock(BoundBlock node)
        {
            if (node.WasCompilerGenerated || !this.GenerateDebugInfo || node.Syntax.Kind() == SyntaxKind.ArrowExpressionClause)
            {
                return(node.Update(node.Locals, node.LocalFunctions, VisitList(node.Statements)));
            }

            BlockSyntax syntax = node.Syntax as BlockSyntax;

            var builder = ArrayBuilder <BoundStatement> .GetInstance();

            if (syntax != null)
            {
                var oBspan = syntax.OpenBraceToken.Span;
                builder.Add(new BoundSequencePointWithSpan(syntax, null, oBspan));
            }

            for (int i = 0; i < node.Statements.Length; i++)
            {
                var stmt = (BoundStatement)Visit(node.Statements[i]);
                if (stmt != null)
                {
                    builder.Add(stmt);
                }
            }

            // no need to mark "}" on the outermost block
            // as it cannot leave it normally. The block will have "return" at the end.
            if (syntax != null && (syntax.Parent == null || !(syntax.Parent.IsAnonymousFunction() || syntax.Parent is BaseMethodDeclarationSyntax)))
            {
                var cBspan = syntax.CloseBraceToken.Span;
                builder.Add(new BoundSequencePointWithSpan(syntax, null, cBspan));
            }

            return(new BoundBlock(node.Syntax, node.Locals, node.LocalFunctions, builder.ToImmutableAndFree(), node.HasErrors));
        }
Пример #13
0
        private static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, CSharpSyntaxNode syntax, bool originalBodyNested)
        {
            if (originalBodyNested)
            {
                var statements = body.Statements;
                int n = statements.Length;

                var builder = ArrayBuilder<BoundStatement>.GetInstance(n);
                builder.AddRange(statements, n - 1);
                builder.Add(AppendImplicitReturn((BoundBlock)statements[n - 1], method, syntax));

                return body.Update(body.Locals, ImmutableArray<LocalFunctionSymbol>.Empty, builder.ToImmutableAndFree());
            }
            else
            {
                return AppendImplicitReturn(body, method, syntax);
            }
        }
Пример #14
0
        // insert the implicit "return" statement at the end of the method body
        // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
        // ones are going to have sequence points.
        internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, CSharpSyntaxNode syntax = null)
        {
            Debug.Assert(body != null);
            Debug.Assert(method != null);

            if (syntax == null)
            {
                syntax = body.Syntax;
            }

            Debug.Assert(body.WasCompilerGenerated || syntax.IsKind(SyntaxKind.Block) || syntax.IsKind(SyntaxKind.ArrowExpressionClause));

            BoundStatement ret = method.IsIterator
                ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax)
                : BoundReturnStatement.Synthesized(syntax, RefKind.None, null);

            return body.Update(body.Locals, body.LocalFunctions, body.Statements.Add(ret));
        }
        // insert the implicit "return" statement at the end of the method body
        // Normally, we wouldn't bother attaching syntax trees to compiler-generated nodes, but these
        // ones are going to have sequence points.
        internal static BoundBlock AppendImplicitReturn(BoundBlock body, MethodSymbol method, CSharpSyntaxNode syntax = null)
        {
            Debug.Assert(body != null);
            Debug.Assert(method != null);

            if (syntax == null)
            {
                syntax = body.Syntax;
            }

            Debug.Assert(body.WasCompilerGenerated || syntax.IsKind(SyntaxKind.Block) || syntax.IsKind(SyntaxKind.ArrowExpressionClause));

            BoundStatement ret = method.IsIterator
                ? (BoundStatement)BoundYieldBreakStatement.Synthesized(syntax)
                : BoundReturnStatement.Synthesized(syntax, null);

            // Implicitly added return for async method does not need sequence points since lowering would add one.
            if (syntax.IsKind(SyntaxKind.Block) && !method.IsAsync)
            {
                var blockSyntax = (BlockSyntax)syntax;

                ret = new BoundSequencePointWithSpan(
                    blockSyntax,
                    ret,
                    blockSyntax.CloseBraceToken.Span)
                { WasCompilerGenerated = true };
            }

            return body.Update(body.Locals, body.Statements.Add(ret));
        }