asyncic: coReturn
This commit is contained in:
31
cl/async.go
31
cl/async.go
@@ -85,33 +85,30 @@ func (p *context) coResume(b llssa.Builder, args []ssa.Value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) coReturn(b llssa.Builder, args []ssa.Value) {
|
func (p *context) getSetValueFunc(fn *ssa.Function) llssa.Function {
|
||||||
cargs := make([]llssa.Expr, len(args))
|
|
||||||
for i, arg := range args {
|
|
||||||
cargs[i] = p.compileValue(b, arg)
|
|
||||||
}
|
|
||||||
b.CoReturn(cargs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *context) coYield(b llssa.Builder, fn *ssa.Function, args []ssa.Value) {
|
|
||||||
typ := fn.Signature.Recv().Type()
|
typ := fn.Signature.Recv().Type()
|
||||||
mthds := p.goProg.MethodSets.MethodSet(typ)
|
mthds := p.goProg.MethodSets.MethodSet(typ)
|
||||||
// TODO(lijie): make llgo instruction callable (e.g. llgo.yield) to avoid extra setValue method
|
|
||||||
var setValue *ssa.Function
|
|
||||||
for i := 0; i < mthds.Len(); i++ {
|
for i := 0; i < mthds.Len(); i++ {
|
||||||
m := mthds.At(i)
|
m := mthds.At(i)
|
||||||
if ssaMthd := p.goProg.MethodValue(m); ssaMthd != nil {
|
if ssaMthd := p.goProg.MethodValue(m); ssaMthd != nil {
|
||||||
if ssaMthd.Name() == "setValue" || strings.HasPrefix(ssaMthd.Name(), "setValue[") {
|
if ssaMthd.Name() == "setValue" || strings.HasPrefix(ssaMthd.Name(), "setValue[") {
|
||||||
setValue = ssaMthd
|
setValueFn, _, _ := p.compileFunction(ssaMthd)
|
||||||
break
|
return setValueFn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if setValue == nil {
|
panic("method setValue not found on type " + typ.String())
|
||||||
panic("coYield(): not found method setValue")
|
}
|
||||||
}
|
|
||||||
|
func (p *context) coReturn(b llssa.Builder, fn *ssa.Function, args []ssa.Value) {
|
||||||
|
setValueFn := p.getSetValueFunc(fn)
|
||||||
|
value := p.compileValue(b, args[1])
|
||||||
|
b.CoReturn(setValueFn, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *context) coYield(b llssa.Builder, fn *ssa.Function, args []ssa.Value) {
|
||||||
|
setValueFn := p.getSetValueFunc(fn)
|
||||||
value := p.compileValue(b, args[1])
|
value := p.compileValue(b, args[1])
|
||||||
setValueFn, _, _ := p.compileFunction(setValue)
|
|
||||||
// TODO(lijie): find whether the co.Yield/co.Return is the last instruction
|
// TODO(lijie): find whether the co.Yield/co.Return is the last instruction
|
||||||
final := b.Const(constant.MakeBool(false), b.Prog.Bool())
|
final := b.Const(constant.MakeBool(false), b.Prog.Bool())
|
||||||
b.CoYield(setValueFn, value, final)
|
b.CoYield(setValueFn, value, final)
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ func (p *context) call(b llssa.Builder, act llssa.DoAction, call *ssa.CallCommon
|
|||||||
case llgoCoResume:
|
case llgoCoResume:
|
||||||
p.coResume(b, args)
|
p.coResume(b, args)
|
||||||
case llgoCoReturn:
|
case llgoCoReturn:
|
||||||
p.coReturn(b, args)
|
p.coReturn(b, cv, args)
|
||||||
case llgoCoYield:
|
case llgoCoYield:
|
||||||
p.coYield(b, cv, args)
|
p.coYield(b, cv, args)
|
||||||
case llgoCoRun:
|
case llgoCoRun:
|
||||||
|
|||||||
32
ssa/coro.go
32
ssa/coro.go
@@ -378,10 +378,6 @@ func (b Builder) AsyncToken() Expr {
|
|||||||
return b.asyncToken
|
return b.asyncToken
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Builder) SetAsyncToken(token Expr) {
|
|
||||||
b.asyncToken = token
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b Builder) EndAsync() {
|
func (b Builder) EndAsync() {
|
||||||
b.onReturn()
|
b.onReturn()
|
||||||
}
|
}
|
||||||
@@ -452,6 +448,9 @@ func (b Builder) BeginAsync(fn Function, entryBlk, allocBlk, cleanBlk, suspdBlk,
|
|||||||
b.Unreachable()
|
b.Unreachable()
|
||||||
|
|
||||||
b.onSuspBlk = func(nextBlk BasicBlock) (BasicBlock, BasicBlock, BasicBlock) {
|
b.onSuspBlk = func(nextBlk BasicBlock) (BasicBlock, BasicBlock, BasicBlock) {
|
||||||
|
if nextBlk == nil {
|
||||||
|
nextBlk = trapBlk
|
||||||
|
}
|
||||||
return suspdBlk, nextBlk, cleanBlk
|
return suspdBlk, nextBlk, cleanBlk
|
||||||
}
|
}
|
||||||
b.onReturn = func() {
|
b.onReturn = func() {
|
||||||
@@ -627,16 +626,21 @@ func (b Builder) CoSuspend(save, final Expr, nextBlk BasicBlock) {
|
|||||||
b.SetBlock(nextBlk)
|
b.SetBlock(nextBlk)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Builder) CoReturn(args ...Expr) {
|
func (b Builder) CoReturn(setValueFn Function, value Expr) {
|
||||||
if !b.async {
|
if !b.async {
|
||||||
panic(fmt.Errorf("return %v not in async block", b.Func.Name()))
|
panic(fmt.Errorf("return %v not in async block", b.Func.Name()))
|
||||||
}
|
}
|
||||||
|
b.Call(setValueFn.Expr, b.promise, value)
|
||||||
b.Func.MakeBlock("")
|
_, _, cleanBlk := b.onSuspBlk(nil)
|
||||||
nextBlk := b.Func.Block(b.blk.idx + 1)
|
|
||||||
_, _, cleanBlk := b.onSuspBlk(nextBlk)
|
|
||||||
b.Jump(cleanBlk)
|
b.Jump(cleanBlk)
|
||||||
b.SetBlock(nextBlk)
|
}
|
||||||
|
|
||||||
|
func (b Builder) CoYield(setValueFn Function, value Expr, final Expr) {
|
||||||
|
if !b.async {
|
||||||
|
panic(fmt.Errorf("yield %v not in async block", b.Func.Name()))
|
||||||
|
}
|
||||||
|
b.Call(setValueFn.Expr, b.promise, value)
|
||||||
|
b.CoSuspend(b.AsyncToken(), final, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -676,11 +680,3 @@ func (b Builder) CoAwaitSuspendHandle(awaiter, handle, f Expr) {
|
|||||||
b.Call(fn, awaiter, handle, f)
|
b.Call(fn, awaiter, handle, f)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func (b Builder) CoYield(setValueFn Function, value Expr, final Expr) {
|
|
||||||
if !b.async {
|
|
||||||
panic(fmt.Errorf("yield %v not in async block", b.Func.Name()))
|
|
||||||
}
|
|
||||||
b.Call(setValueFn.Expr, b.promise, value)
|
|
||||||
b.CoSuspend(b.AsyncToken(), final, nil)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user