cl: fix CoYield

This commit is contained in:
Li Jie
2024-08-05 12:37:34 +08:00
parent 93bff83e3d
commit a1fdc05e26
4 changed files with 56 additions and 50 deletions

View File

@@ -1,7 +1,7 @@
; ModuleID = 'github.com/goplus/llgo/cl/_testdata/async' ; ModuleID = 'github.com/goplus/llgo/cl/_testdata/async'
source_filename = "github.com/goplus/llgo/cl/_testdata/async" source_filename = "github.com/goplus/llgo/cl/_testdata/async"
%"github.com/goplus/llgo/internal/runtime.Defer" = type { ptr, i64, ptr, ptr } %"github.com/goplus/llgo/internal/runtime.Defer" = type { ptr, i64, ptr, ptr, ptr }
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr } %"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr }
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } %"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 }
@@ -94,66 +94,71 @@ _llgo_4: ; preds = %alloc, %entry
%4 = load i32, ptr @__llgo_defer, align 4 %4 = load i32, ptr @__llgo_defer, align 4
%5 = call ptr @pthread_getspecific(i32 %4) %5 = call ptr @pthread_getspecific(i32 %4)
%6 = alloca i8, i64 196, align 1 %6 = alloca i8, i64 196, align 1
%7 = alloca i8, i64 32, align 1 %7 = alloca i8, i64 40, align 1
%8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 0 %8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 0
store ptr %6, ptr %8, align 8 store ptr %6, ptr %8, align 8
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 1 %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 1
store i64 0, ptr %9, align 4 store i64 0, ptr %9, align 4
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 2 %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 2
store ptr %5, ptr %10, align 8 store ptr %5, ptr %10, align 8
%11 = call i32 @pthread_setspecific(i32 %4, ptr %7) %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 3
%12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 1 store ptr blockaddress(@"github.com/goplus/llgo/cl/_testdata/async.GenIntsWithDefer", %_llgo_6), ptr %11, align 8
%13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 3 %12 = call i32 @pthread_setspecific(i32 %4, ptr %7)
%14 = call i32 @sigsetjmp(ptr %6, i32 0) %13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 1
%15 = icmp eq i32 %14, 0 %14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 3
br i1 %15, label %_llgo_8, label %_llgo_9 %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, i32 0, i32 4
%16 = call i32 @sigsetjmp(ptr %6, i32 0)
%17 = icmp eq i32 %16, 0
br i1 %17, label %_llgo_8, label %_llgo_9
_llgo_5: ; preds = %_llgo_8, %_llgo_7 _llgo_5: ; preds = %_llgo_8, %_llgo_7
%16 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %18 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 0 %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 0
store ptr @0, ptr %17, align 8 store ptr @0, ptr %19, align 8
%18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %16, i32 0, i32 1 %20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 1
store i64 16, ptr %18, align 4 store i64 16, ptr %20, align 4
%19 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %16, align 8 %21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %18, align 8
%20 = load ptr, ptr @_llgo_string, align 8 %22 = load ptr, ptr @_llgo_string, align 8
%21 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16) %23 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16)
store %"github.com/goplus/llgo/internal/runtime.String" %19, ptr %21, align 8 store %"github.com/goplus/llgo/internal/runtime.String" %21, ptr %23, align 8
%22 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8 %24 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
%23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %22, i32 0, i32 0 %25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %24, i32 0, i32 0
store ptr %20, ptr %23, align 8 store ptr %22, ptr %25, align 8
%24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %22, i32 0, i32 1 %26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %24, i32 0, i32 1
store ptr %21, ptr %24, align 8 store ptr %23, ptr %26, align 8
%25 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %22, align 8 %27 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %24, align 8
call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %25) call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %27)
unreachable unreachable
%26 = load ptr, ptr %3, align 8 %28 = load ptr, ptr %3, align 8
br label %clean br label %clean
_llgo_6: ; preds = %_llgo_9 _llgo_6: ; preds = %_llgo_9
%27 = load i64, ptr %12, align 4 store ptr blockaddress(@"github.com/goplus/llgo/cl/_testdata/async.GenIntsWithDefer", %_llgo_7), ptr %14, align 8
%29 = load i64, ptr %13, align 4
call void @"github.com/goplus/llgo/cl/_testdata/async.GenIntsWithDefer$1"() call void @"github.com/goplus/llgo/cl/_testdata/async.GenIntsWithDefer$1"()
%28 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, align 8 %30 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %7, align 8
%29 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %28, 2 %31 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %30, 2
%30 = call i32 @pthread_setspecific(i32 %4, ptr %29) %32 = call i32 @pthread_setspecific(i32 %4, ptr %31)
%31 = load ptr, ptr %13, align 8 %33 = load ptr, ptr %15, align 8
indirectbr ptr %31, [label %_llgo_7] indirectbr ptr %33, [label %_llgo_7]
_llgo_7: ; preds = %_llgo_6 _llgo_7: ; preds = %_llgo_9, %_llgo_6
call void @"github.com/goplus/llgo/internal/runtime.Rethrow"(ptr %5) call void @"github.com/goplus/llgo/internal/runtime.Rethrow"(ptr %5)
br label %_llgo_5 br label %_llgo_5
_llgo_8: ; preds = %_llgo_4 _llgo_8: ; preds = %_llgo_4
%32 = load ptr, ptr %3, align 8 %34 = load ptr, ptr %3, align 8
call void @"github.com/goplus/llgo/x/async.(*Promise).setValue[int]"(ptr %promise, i64 1) call void @"github.com/goplus/llgo/x/async.(*Promise).setValue[int]"(ptr %promise, i64 1)
%33 = call i8 @llvm.coro.suspend(token %id, i1 false) %35 = call i8 @llvm.coro.suspend(token %id, i1 false)
switch i8 %33, label %suspend [ switch i8 %35, label %suspend [
i8 0, label %_llgo_5 i8 0, label %_llgo_5
i8 1, label %clean i8 1, label %clean
] ]
_llgo_9: ; preds = %_llgo_4 _llgo_9: ; preds = %_llgo_4
store ptr blockaddress(@"github.com/goplus/llgo/cl/_testdata/async.GenIntsWithDefer", %_llgo_7), ptr %13, align 8 store ptr blockaddress(@"github.com/goplus/llgo/cl/_testdata/async.GenIntsWithDefer", %_llgo_7), ptr %15, align 8
br label %_llgo_6 %36 = load ptr, ptr %14, align 8
indirectbr ptr %36, [label %_llgo_7, label %_llgo_6]
_llgo_10: ; No predecessors! _llgo_10: ; No predecessors!
} }
@@ -283,7 +288,12 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #4
; Function Attrs: nounwind ; Function Attrs: nounwind
declare i1 @llvm.coro.end(ptr, i1, token) #2 declare i1 @llvm.coro.end(ptr, i1, token) #2
declare void @"github.com/goplus/llgo/x/async.(*Promise).setValue[int]"(ptr, i64) define void @"github.com/goplus/llgo/x/async.(*Promise).setValue[int]"(ptr %0, i64 %1) {
_llgo_0:
%2 = getelementptr inbounds %"github.com/goplus/llgo/x/async.Promise[int]", ptr %0, i32 0, i32 1
store i64 %1, ptr %2, align 4
ret void
}
; Function Attrs: nounwind ; Function Attrs: nounwind
declare i8 @llvm.coro.suspend(token, i1) #2 declare i8 @llvm.coro.suspend(token, i1) #2

View File

@@ -17,6 +17,7 @@
package cl package cl
import ( import (
"go/constant"
"go/types" "go/types"
"strings" "strings"
@@ -95,7 +96,7 @@ func (p *context) coReturn(b llssa.Builder, args []ssa.Value) {
func (p *context) coYield(b llssa.Builder, fn *ssa.Function, args []ssa.Value) { 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) // TODO(lijie): make llgo instruction callable (e.g. llgo.yield) to avoid extra setValue method
var setValue *ssa.Function 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)
@@ -110,8 +111,10 @@ func (p *context) coYield(b llssa.Builder, fn *ssa.Function, args []ssa.Value) {
panic("coYield(): not found method setValue") panic("coYield(): not found method setValue")
} }
value := p.compileValue(b, args[1]) value := p.compileValue(b, args[1])
setValueFn, _, _ := p.funcOf(setValue) setValueFn, _, _ := p.compileFunction(setValue)
b.CoYield(setValueFn, value) // TODO(lijie): find whether the co.Yield/co.Return is the last instruction
final := b.Const(constant.MakeBool(false), b.Prog.Bool())
b.CoYield(setValueFn, value, final)
} }
func (p *context) coRun(b llssa.Builder, args []ssa.Value) { func (p *context) coRun(b llssa.Builder, args []ssa.Value) {

View File

@@ -240,6 +240,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
} }
fn.MakeBlocks(nblk) // to set fn.HasBody() = true fn.MakeBlocks(nblk) // to set fn.HasBody() = true
if f.Recover != nil { // set recover block if f.Recover != nil { // set recover block
// TODO(lijie): fix this for async function because of the block offset increase
fn.SetRecover(fn.Block(f.Recover.Index + nBlkOff)) fn.SetRecover(fn.Block(f.Recover.Index + nBlkOff))
} }
p.inits = append(p.inits, func() { p.inits = append(p.inits, func() {

View File

@@ -382,14 +382,6 @@ func (b Builder) EndAsync() {
b.Jump(cleanBlk) b.Jump(cleanBlk)
} }
func promiseImplType(ty types.Type) types.Type {
ty = ty.Underlying().(*types.Struct).Field(0).Type()
if ptrTy, ok := ty.(*types.Pointer); ok {
return ptrTy.Elem()
}
panic(fmt.Sprintf("unexpected promise impl type: %v", ty))
}
/* /*
id := @llvm.coro.id(0, null, null, null) id := @llvm.coro.id(0, null, null, null)
frameSize := @llvm.coro.size.i64() frameSize := @llvm.coro.size.i64()
@@ -672,7 +664,7 @@ 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) { func (b Builder) CoYield(setValueFn Function, value Expr, final Expr) {
if !b.async { if !b.async {
panic(fmt.Errorf("yield %v not in async block", b.Func.Name())) panic(fmt.Errorf("yield %v not in async block", b.Func.Name()))
} }