Skip to content

[Arc] Add coroutine ops#10522

Open
fabianschuiki wants to merge 1 commit into
mainfrom
fschuiki/arc-coroutines
Open

[Arc] Add coroutine ops#10522
fabianschuiki wants to merge 1 commit into
mainfrom
fschuiki/arc-coroutines

Conversation

@fabianschuiki
Copy link
Copy Markdown
Contributor

Extend the Arc dialect with a set of arc.coroutine.* operations and types. These model suspendable coroutines similar to async/await fns in Rust. The compiler is expected to split the function at yield points, determine what local state needs to be persisted to the next re-entry, and then allow the coroutine to be polled using the persisted state and an indication of where to resume execution.

The coroutine operations will later allow us to lower llhd.process and llhd.coroutine operations to arc.coroutine.*, and extend Arcilator to support concurrently executing these coroutines as a first step towards proper process support.

This PR only adds operations, tests, and some rationale to the Arc dialect documentation.

Assisted-by: Claude Opus 4.7

Extend the Arc dialect with a set of `arc.coroutine.*` operations and
types. These model suspendable coroutines similar to async/await fns in
Rust. The compiler is expected to split the function at yield points,
determine what local state needs to be persisted to the next re-entry,
and then allow the coroutine to be polled using the persisted state and
an indication of where to resume execution.

The coroutine operations will later allow us to lower `llhd.process` and
`llhd.coroutine` operations to `arc.coroutine.*`, and extend Arcilator
to support concurrently executing these coroutines as a first step
towards proper process support.

This PR only adds operations, tests, and some rationale to the Arc
dialect documentation.
@fabianschuiki fabianschuiki requested a review from maerhart as a code owner May 21, 2026 18:15
@fabianschuiki fabianschuiki added the Arc Involving the `arc` dialect label May 21, 2026
Comment thread docs/Dialects/Arc.md

Both constructs are rewritten into a canonical outlined form: an `arc.coroutine.define` definition plus one or more call sites that re-enter it.
For a process, the call site is an `arc.coroutine.instance` placed in the enclosing `hw.module`.
For a coroutine, each `llhd.call_coroutine` becomes an `arc.coroutine.call` inside its parent coroutine's body.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not blocking but could you use consistent naming for call_coroutine/coroutine.call in a follow-up?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good idea 👍 I should probably tweak the LLHD dialect to match this.

@circt-bot
Copy link
Copy Markdown

circt-bot Bot commented May 21, 2026

Results of circt-tests run for 1cc26ce compared to results for 5306f6f: no change to test results.

@fzi-hielscher
Copy link
Copy Markdown
Contributor

I'm struggling to wrap my head around where and how the "persistent state"/"local state" (those refer to the same thing, right?) of the coroutine is specified. The language in Arc.md makes it sound like this happens during lowering from LLHD to Arc. But I don't see any way how this would be modeled and accessed in the Arc IR beyond a simple opaque value. So, are we still implicitly capturing SSA values that are live across arc.coroutine.yield suspension points? If so, I don't know how to interpret this paragraph:

Arguments are passed to the coroutine upon each entry, which means that
subsequent re-entry may provide different arguments. If a coroutine wants to
preserve the arguments passed to its initial entry, it must persist them as
local state.

How are (region) arguments different from other SSA values? If an argument is used after a suspension point, isn't it then automatically part of the local state? How would we then access the new arguments passed in on re-entry?


// CHECK-LABEL: func.func @CoroutineCallWithResults
func.func @CoroutineCallWithResults(
%arg0: !arc.coroutine_state<@CoroutineWithResults>,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the rational to create separate SSA values for state/pc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arc Involving the `arc` dialect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants