asyncic: coReturn

This commit is contained in:
Li Jie
2024-08-05 17:24:36 +08:00
parent b04ac8df30
commit d3df782fca
3 changed files with 29 additions and 36 deletions

View File

@@ -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)

View File

@@ -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:

View File

@@ -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)
}