diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
index a3dd64c87a3a..d03e79685e79 100644
--- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
+++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
@@ -424,6 +424,7 @@
+
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs
new file mode 100644
index 000000000000..7605bdd55e16
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs
@@ -0,0 +1,77 @@
+// 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.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Runtime.CompilerServices
+{
+ /// Represents a builder for asynchronous iterators.
+ [StructLayout(LayoutKind.Auto)]
+ public struct AsyncIteratorMethodBuilder
+ {
+ // AsyncIteratorMethodBuilder is used by the language compiler as part of generating
+ // async iterators. For now, the implementation just wraps AsyncTaskMethodBuilder, as
+ // most of the logic is shared. However, in the future this could be changed and
+ // optimized. For example, we do need to allocate an object (once) to flow state like
+ // ExecutionContext, which AsyncTaskMethodBuilder handles, but it handles it by
+ // allocating a Task-derived object. We could optimize this further by removing
+ // the Task from the hierarchy, but in doing so we'd also lose a variety of optimizations
+ // related to it, so we'd need to replicate all of those optimizations (e.g. storing
+ // that box object directly into a Task's continuation field).
+
+ private AsyncTaskMethodBuilder _methodBuilder; // mutable struct; do not make it readonly
+
+ /// Creates an instance of the struct.
+ /// The initialized instance.
+ public static AsyncIteratorMethodBuilder Create() =>
+#if CORERT
+ // corert's AsyncTaskMethodBuilder.Create() currently does additional debugger-related
+ // work, so we need to delegate to it.
+ new AsyncIteratorMethodBuilder() { _methodBuilder = AsyncTaskMethodBuilder.Create() };
+#else
+ default; // coreclr's AsyncTaskMethodBuilder.Create just returns default as well
+#endif
+
+ /// Invokes on the state machine while guarding the
+ /// The type of the state machine.
+ /// The state machine instance, passed by reference.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void MoveNext(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
+#if CORERT
+ _methodBuilder.Start(ref stateMachine);
+#else
+ AsyncMethodBuilderCore.Start(ref stateMachine);
+#endif
+
+ /// Schedules the state machine to proceed to the next action when the specified awaiter completes.
+ /// The type of the awaiter.
+ /// The type of the state machine.
+ /// The awaiter.
+ /// The state machine.
+ public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : INotifyCompletion
+ where TStateMachine : IAsyncStateMachine =>
+ _methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);
+
+ /// Schedules the state machine to proceed to the next action when the specified awaiter completes.
+ /// The type of the awaiter.
+ /// The type of the state machine.
+ /// The awaiter.
+ /// The state machine.
+ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : ICriticalNotifyCompletion
+ where TStateMachine : IAsyncStateMachine =>
+ _methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
+
+ /// Marks iteration as being completed, whether successfully or otherwise.
+ public void Complete() =>
+ _methodBuilder.SetResult();
+
+ /// Gets an object that may be used to uniquely identify this builder to the debugger.
+ internal object ObjectIdForDebugger =>
+ _methodBuilder.ObjectIdForDebugger;
+ }
+}