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)); }
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); }
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())); }
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)); }
// 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())); }
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)); } }
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); }
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); }
// 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))); }
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))); }
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)); }
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); } }
// 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)); }