diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
index 3e8151e3388c2..f177c27818018 100644
--- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
@@ -1753,6 +1753,76 @@ internal PointerTypeSymbol CreatePointerTypeSymbol(TypeSymbol elementType)
#endregion
+ #region Operations
+
+ ///
+ /// Gets the low-level operation corresponding to the method's body.
+ ///
+ /// The method symbol.
+ /// An optional cancellation token.
+ /// The low-level operation corresponding to the method's body.
+ protected override IOperation GetLowLevelOperationCore(IMethodSymbol method, CancellationToken cancellationToken = default)
+ {
+ IOperation result = null;
+ var csmethod = method.EnsureCSharpSymbolOrNull(nameof(method));
+
+ if ((object)csmethod != null && csmethod.IsFromCompilation(this))
+ {
+ var body = LowerMethodBody(csmethod);
+
+ if (body != null)
+ {
+ var operationFactory = new Semantics.CSharpOperationFactory(null);
+ result = operationFactory.Create(body);
+ }
+ }
+
+ return result;
+ }
+
+ private BoundStatement LowerMethodBody(MethodSymbol method)
+ {
+ BoundStatement result = null;
+
+ // We don't want to support synthesized bodies
+ // (like auto-property accessors, etc.)
+ if (method is SourceMemberMethodSymbol sourceMethod && sourceMethod.BodySyntax != null)
+ {
+ var compilationState = new TypeCompilationState(method.ContainingType, this, null);
+ var diagnostics = DiagnosticBag.GetInstance();
+ var body = MethodCompiler.BindMethodBody(method, compilationState, diagnostics);
+
+ if (body != null && !body.HasErrors && !diagnostics.HasAnyErrors())
+ {
+ const int methodOrdinal = -1;
+ var dynamicAnalysisSpans = ImmutableArray.Empty;
+
+ result = LocalRewriter.Rewrite(
+ this,
+ method,
+ methodOrdinal,
+ method.ContainingType,
+ body,
+ compilationState,
+ previousSubmissionFields: null,
+ allowOmissionOfConditionalCalls: true,
+ instrumentForDynamicAnalysis: false,
+ debugDocumentProvider: null,
+ dynamicAnalysisSpans: ref dynamicAnalysisSpans,
+ diagnostics: diagnostics,
+ sawLambdas: out bool sawLambdas,
+ sawLocalFunctions: out bool sawLocalFunctions,
+ sawAwaitInExceptionHandler: out bool sawAwaitInExceptionHandler);
+ }
+
+ diagnostics.Free();
+ }
+
+ return result;
+ }
+
+ #endregion
+
#region Binding
///
diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
index 12f2029312428..c9333c3426c0c 100644
--- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
+++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
@@ -254,6 +254,21 @@ private IOperation CreateInternal(BoundNode boundNode)
return CreateBoundPatternSwitchLabelOperation((BoundPatternSwitchLabel)boundNode);
case BoundKind.IsPatternExpression:
return CreateBoundIsPatternExpressionOperation((BoundIsPatternExpression)boundNode);
+
+ // To support BoundNodes after lowering phase.
+ case BoundKind.SequencePoint:
+ return CreateBoundSequencePointOperation((BoundSequencePoint)boundNode);
+ case BoundKind.SequencePointWithSpan:
+ return CreateBoundSequencePointWithSpanOperation((BoundSequencePointWithSpan)boundNode);
+ case BoundKind.SequencePointExpression:
+ return CreateBoundSequencePointExpressionOperation((BoundSequencePointExpression)boundNode);
+ case BoundKind.StatementList:
+ return CreateBoundStatementListOperation((BoundStatementList)boundNode);
+ case BoundKind.ConditionalGoto:
+ return CreateBoundConditionalGotoOperation((BoundConditionalGoto)boundNode);
+ case BoundKind.Sequence:
+ return CreateBoundSequenceOperation((BoundSequence)boundNode);
+
default:
var constantValue = ConvertToOptional((boundNode as BoundExpression)?.ConstantValue);
bool isImplicit = boundNode.WasCompilerGenerated;
@@ -426,7 +441,7 @@ private IEventAssignmentExpression CreateBoundEventAssignmentOperatorOperation(B
return new LazyEventAssignmentExpression(eventReference, handlerValue, adds, _semanticModel, syntax, type, constantValue, isImplicit);
}
- private IParameterReferenceExpression CreateBoundParameterOperation(BoundParameter boundParameter)
+ private IParameterReferenceExpression CreateBoundParameterOperation(BoundParameter boundParameter)
{
IParameterSymbol parameter = boundParameter.ParameterSymbol;
SyntaxNode syntax = boundParameter.Syntax;
@@ -1064,7 +1079,7 @@ private IParameterInitializer CreateBoundParameterEqualsValueOperation(BoundPara
private IBlockStatement CreateBoundBlockOperation(BoundBlock boundBlock)
{
Lazy> statements =
- new Lazy>(() => boundBlock.Statements.Select(s => Create(s)).Where(s => s.Kind != OperationKind.None).ToImmutableArray());
+ new Lazy>(() => boundBlock.Statements.Select(s => Create(s)).Where(s => s != null && s.Kind != OperationKind.None).ToImmutableArray());
ImmutableArray locals = boundBlock.Locals.As();
SyntaxNode syntax = boundBlock.Syntax;
@@ -1506,5 +1521,59 @@ private IIsPatternExpression CreateBoundIsPatternExpressionOperation(BoundIsPatt
bool isImplicit = boundIsPatternExpression.WasCompilerGenerated;
return new LazyIsPatternExpression(expression, pattern, _semanticModel, syntax, type, constantValue, isImplicit);
}
+
+ private IOperation CreateBoundSequencePointOperation(BoundSequencePoint boundSequencePoint)
+ {
+ return Create(boundSequencePoint.StatementOpt);
+ }
+
+ private IOperation CreateBoundSequencePointWithSpanOperation(BoundSequencePointWithSpan boundSequencePointWithSpan)
+ {
+ return Create(boundSequencePointWithSpan.StatementOpt);
+ }
+
+ private IOperation CreateBoundSequencePointExpressionOperation(BoundSequencePointExpression boundSequencePointExpression)
+ {
+ return Create(boundSequencePointExpression.Expression);
+ }
+
+ private IBlockStatement CreateBoundStatementListOperation(BoundStatementList boundStatementList)
+ {
+ Lazy> statements =
+ new Lazy>(() => boundStatementList.Statements.Select(s => Create(s)).Where(s => s != null).ToImmutableArray());
+
+ ImmutableArray locals = ImmutableArray.Empty;
+ SyntaxNode syntax = boundStatementList.Syntax;
+ ITypeSymbol type = null;
+ Optional