| File: Lowering\LocalRewriter\LocalRewriter_Await.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Immutable; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Symbols; namespace Microsoft.CodeAnalysis.CSharp { internal sealed partial class LocalRewriter { public override BoundNode VisitAwaitExpression(BoundAwaitExpression node) { return VisitAwaitExpression(node, true); } public BoundExpression VisitAwaitExpression(BoundAwaitExpression node, bool used) { return RewriteAwaitExpression((BoundExpression)base.VisitAwaitExpression(node)!, used); } private BoundExpression RewriteAwaitExpression(SyntaxNode syntax, BoundExpression rewrittenExpression, BoundAwaitableInfo awaitableInfo, TypeSymbol type, BoundAwaitExpressionDebugInfo debugInfo, bool used) { return RewriteAwaitExpression(new BoundAwaitExpression(syntax, rewrittenExpression, awaitableInfo, debugInfo, type) { WasCompilerGenerated = true }, used); } /// <summary> /// Lower an await expression that has already had its components rewritten. /// </summary> private BoundExpression RewriteAwaitExpression(BoundExpression rewrittenAwait, bool used) { _sawAwait = true; if (!used) { // Await expression is already at the statement level. return rewrittenAwait; } // The await expression will be lowered to code that involves the use of side-effects // such as jumps and labels, which we can only emit with an empty stack, so we require // that the await expression itself is produced only when the stack is empty. // Therefore it is represented by a BoundSpillSequence. The resulting nodes will be "spilled" to move // such statements to the top level (i.e. into the enclosing statement list). Here we ensure // that the await result itself is stored into a temp at the statement level, as that is // the form handled by async lowering. _needsSpilling = true; var tempAccess = _factory.StoreToTemp(rewrittenAwait, out BoundAssignmentOperator tempAssignment, syntaxOpt: rewrittenAwait.Syntax, kind: SynthesizedLocalKind.Spill); return new BoundSpillSequence( syntax: rewrittenAwait.Syntax, locals: ImmutableArray.Create<LocalSymbol>(tempAccess.LocalSymbol), sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignment), value: tempAccess, type: tempAccess.Type); } } }