[llvm-dev] Fwd: [RFC] LLVM Coroutines

Gor Nishanov via llvm-dev
Sat, 11 Jun 2016 00:42:51 -0000

Hi Josh:

> Sorry for the novice question, but how are coroutines lowered in the
> backend? It requires making operating system calls to something like
> pthreads right?

No OS, no target specific code required. Just simple rewriting of a function
during the middle optimizer. One of the first examples in the RFC shows
that a coroutine is optimized down to a constant. Try doing that with
pthreads :-)

>>   generator<int> range(int from, int to) {
>>      for(int i = from; i < to; ++n)
>>         co_yield i;
>>   }
>>   int main() {
>>      int sum = 0;
>>      for (auto v: range(1,100))
>>         sum += v;
>>      return sum;
>>   }
>>
>> And translate it down to this:
>>
>>   define i32 @main() #5 {
>>   entry:
>>     ret i32 4950
>>   }


Very briefly:

LLVM coroutines are functions that have one or more `suspend points`_.
When a suspend point is reached, the execution of a coroutine is suspended and
control is returned back to its caller. A suspended coroutine can be resumed
to continue execution from the last suspend point or be destroyed.

Let's say you get coroutine that looks something like this

  void *f(int n) {
     for(;;) {
       bar(n++);
       <suspend> // magic: returns a coroutine handle on first suspend
     }
  }

We will split it up into start, resume and destroy functions and will create
a coroutine frame that will keep values that need to be live across suspension
points.

  struct f.frame { int n; }

  void* f(int n) {
    auto s = new f.frame{n};
    bar(s->n++);
    return s;
  }

  void f.resume(f.frame* s) {
    bar(s->n++);
  }

  void f.destroy(f.frame* s) {
    delete s;
  }

You can read more details in the doc/Coroutines.rst up for review at

http://reviews.llvm.org/D21170

or in the RFC that started this thread.

Cheers
Gor