defer refactor

This commit is contained in:
xushiwei
2024-06-03 01:06:01 +08:00
parent 410f9dd759
commit 56a5a7d72e
17 changed files with 207 additions and 171 deletions

View File

@@ -85,7 +85,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"main.init$abi"()
call void @"main.init$after"()
store i64 0, ptr @main.minhexdigits, align 4
br label %_llgo_2
@@ -1412,7 +1412,7 @@ declare i32 @printf(ptr, ...)
declare void @"github.com/goplus/llgo/internal/runtime.init"()
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_float32, align 8
%1 = icmp eq ptr %0, null

View File

@@ -19,7 +19,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"main.init$abi"()
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -118,7 +118,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_int, align 8
%1 = icmp eq ptr %0, null

View File

@@ -3,7 +3,7 @@ source_filename = "main"
%"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.Defer" = type { { ptr, ptr }, i64, ptr }
%"github.com/goplus/llgo/internal/runtime.Defer" = type { { ptr, ptr }, i64, ptr, i64 }
@"main.init$guard" = global ptr null
@0 = private unnamed_addr constant [6 x i8] c"error\00", align 1
@@ -67,75 +67,119 @@ _llgo_0:
call void @main.init()
%2 = load ptr, ptr @__llgo_defer, align 8
%3 = call ptr @pthread_getspecific(ptr %2)
%4 = alloca i8, i64 32, align 1
%4 = alloca i8, i64 40, align 1
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 0
store ptr @"main$_llgo_defer", ptr %5, align 8
store ptr null, ptr %5, align 8
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
store i64 0, ptr %6, align 4
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 2
store ptr %3, ptr %7, align 8
%8 = call i32 @pthread_setspecific(ptr %2, ptr %4)
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%10 = load i64, ptr %9, align 4
%11 = or i64 %10, 1
store i64 %11, ptr %9, align 4
%12 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %12, i32 0, i32 0
store ptr @1, ptr %13, align 8
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %12, i32 0, i32 1
store i64 5, ptr %14, align 4
%15 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %12, align 8
%16 = call i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %15)
br i1 %16, label %_llgo_2, label %_llgo_4
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 3
%11 = load i64, ptr %9, align 4
%12 = or i64 %11, 1
store i64 %12, ptr %9, align 4
%13 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%14 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 0
store ptr @1, ptr %14, align 8
%15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %13, i32 0, i32 1
store i64 5, ptr %15, align 4
%16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %13, align 8
%17 = call i1 @main.f(%"github.com/goplus/llgo/internal/runtime.String" %16)
br i1 %17, label %_llgo_2, label %_llgo_4
_llgo_1: ; No predecessors!
ret i32 0
_llgo_2: ; preds = %_llgo_0
%17 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %17, i32 0, i32 0
store ptr @2, ptr %18, align 8
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %17, i32 0, i32 1
store i64 5, ptr %19, align 4
%20 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %17, align 8
%21 = load ptr, ptr @__llgo_defer, align 8
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%23 = load i64, ptr %22, align 4
%24 = or i64 %23, 2
store i64 %24, ptr %22, align 4
%18 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 0
store ptr @2, ptr %19, align 8
%20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %18, i32 0, i32 1
store i64 5, ptr %20, align 4
%21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %18, align 8
%22 = load i64, ptr %9, align 4
%23 = or i64 %22, 2
store i64 %23, ptr %9, align 4
br label %_llgo_3
_llgo_3: ; preds = %_llgo_4, %_llgo_2
%25 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 0
store ptr @3, ptr %26, align 8
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 1
store i64 3, ptr %27, align 4
%28 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %25, align 8
%29 = load ptr, ptr @__llgo_defer, align 8
%30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%31 = load i64, ptr %30, align 4
%32 = or i64 %31, 4
store i64 %32, ptr %30, align 4
%33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%34 = load i64, ptr %33, align 4
call void @"main$_llgo_defer"(i64 %34)
ret i32 0
%24 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 0
store ptr @3, ptr %25, align 8
%26 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %24, i32 0, i32 1
store i64 3, ptr %26, align 4
%27 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %24, align 8
%28 = load i64, ptr %9, align 4
%29 = or i64 %28, 4
store i64 %29, ptr %9, align 4
store i64 0, ptr %10, align 4
br label %_llgo_5
_llgo_4: ; preds = %_llgo_0
%35 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 0
store ptr @4, ptr %36, align 8
%37 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 1
store i64 5, ptr %37, align 4
%38 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %35, align 8
%39 = load ptr, ptr @__llgo_defer, align 8
%40 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%41 = load i64, ptr %40, align 4
%42 = or i64 %41, 8
store i64 %42, ptr %40, align 4
%30 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
%31 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 0
store ptr @4, ptr %31, align 8
%32 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %30, i32 0, i32 1
store i64 5, ptr %32, align 4
%33 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %30, align 8
%34 = load i64, ptr %9, align 4
%35 = or i64 %34, 8
store i64 %35, ptr %9, align 4
call void @main.fail()
br label %_llgo_3
_llgo_5: ; preds = %_llgo_3
%36 = load i64, ptr %9, align 4
%37 = and i64 %36, 8
%38 = icmp ne i64 %37, 0
br i1 %38, label %_llgo_7, label %_llgo_8
_llgo_6: ; preds = %_llgo_14
ret i32 0
_llgo_7: ; preds = %_llgo_5
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %33)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
br label %_llgo_8
_llgo_8: ; preds = %_llgo_7, %_llgo_5
%39 = and i64 %36, 4
%40 = icmp ne i64 %39, 0
br i1 %40, label %_llgo_9, label %_llgo_10
_llgo_9: ; preds = %_llgo_8
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %27)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
br label %_llgo_10
_llgo_10: ; preds = %_llgo_9, %_llgo_8
%41 = and i64 %36, 2
%42 = icmp ne i64 %41, 0
br i1 %42, label %_llgo_11, label %_llgo_12
_llgo_11: ; preds = %_llgo_10
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %21)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
br label %_llgo_12
_llgo_12: ; preds = %_llgo_11, %_llgo_10
%43 = and i64 %36, 1
%44 = icmp ne i64 %43, 0
br i1 %44, label %_llgo_13, label %_llgo_14
_llgo_13: ; preds = %_llgo_12
call void @"main.main$1"()
br label %_llgo_14
_llgo_14: ; preds = %_llgo_13, %_llgo_12
%45 = load %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, align 8
%46 = extractvalue %"github.com/goplus/llgo/internal/runtime.Defer" %45, 2
%47 = call i32 @pthread_setspecific(ptr %2, ptr %46)
%48 = load i64, ptr %10, align 4
switch i64 %48, label %_llgo_6 [
]
}
define void @"main.init$after"() {
@@ -183,50 +227,6 @@ _llgo_0:
ret void
}
define void @"main$_llgo_defer"(i64 %0) {
_llgo_0:
%1 = and i64 %0, 1
%2 = icmp ne i64 %1, 0
br i1 %2, label %_llgo_1, label %_llgo_2
_llgo_1: ; preds = %_llgo_0
call void @"main.main$1"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
%3 = and i64 %0, 2
%4 = icmp ne i64 %3, 0
br i1 %4, label %_llgo_3, label %_llgo_4
_llgo_3: ; preds = %_llgo_2
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %20)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
br label %_llgo_4
_llgo_4: ; preds = %_llgo_3, %_llgo_2
%5 = and i64 %0, 4
%6 = icmp ne i64 %5, 0
br i1 %6, label %_llgo_5, label %_llgo_6
_llgo_5: ; preds = %_llgo_4
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %28)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
br label %_llgo_6
_llgo_6: ; preds = %_llgo_5, %_llgo_4
%7 = and i64 %0, 8
%8 = icmp ne i64 %7, 0
br i1 %8, label %_llgo_7, label %_llgo_8
_llgo_7: ; preds = %_llgo_6
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %38)
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
br label %_llgo_8
_llgo_8: ; preds = %_llgo_7, %_llgo_6
ret void
}
declare ptr @pthread_getspecific(i32)
declare i32 @pthread_setspecific(i32, ptr)

View File

@@ -60,7 +60,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"main.init$abi"()
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -102,7 +102,7 @@ _llgo_0:
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = call ptr @"github.com/goplus/llgo/internal/runtime.NewNamed"(i64 25, i64 0, i64 1)
store ptr %0, ptr @_llgo_main.errorString, align 8

View File

@@ -49,7 +49,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/cl/internal/foo.init"()
call void @"main.init$abi"()
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -241,7 +241,7 @@ _llgo_18: ; preds = %_llgo_17, %_llgo_16
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_int, align 8
%1 = icmp eq ptr %0, null

View File

@@ -117,7 +117,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/cl/internal/foo.init"()
call void @"main.init$abi"()
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -185,7 +185,7 @@ _llgo_0:
ret i32 0
}
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @"_llgo_github.com/goplus/llgo/cl/internal/foo.Foo", align 8
%1 = icmp eq ptr %0, null

View File

@@ -68,7 +68,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"main.init$abi"()
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -101,7 +101,7 @@ _llgo_0:
ret i32 0
}
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_int8, align 8
%1 = icmp eq ptr %0, null

View File

@@ -86,7 +86,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"main.init$abi"()
call void @"main.init$after"()
store i64 9223372036854775807, ptr @main.a, align 4
store i64 -9223372036854775808, ptr @main.b, align 4
store i64 -1, ptr @main.n, align 4
@@ -643,7 +643,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com
declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice", ptr, i64, i64)
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_int, align 8
%1 = icmp eq ptr %0, null

View File

@@ -401,7 +401,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"main.init$abi"()
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -472,7 +472,7 @@ _llgo_0:
ret i32 0
}
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_string, align 8
%1 = icmp eq ptr %0, null

View File

@@ -199,7 +199,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"github.com/goplus/llgo/internal/abi.init"()
call void @"main.init$abi"()
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -436,7 +436,7 @@ declare void @"github.com/goplus/llgo/internal/abi.init"()
declare void @"github.com/goplus/llgo/internal/runtime.init"()
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_bool, align 8
%1 = icmp eq ptr %0, null

View File

@@ -17,7 +17,7 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
call void @"main.init$abi"()
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
@@ -51,7 +51,7 @@ _llgo_0:
declare void @"github.com/goplus/llgo/internal/runtime.init"()
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_string, align 8
%1 = icmp eq ptr %0, null

Binary file not shown.

Binary file not shown.

View File

@@ -21,6 +21,7 @@ type Defer struct {
proc func(uintptr)
bits uintptr
link *Defer
rund int // index of RunDefers
}
// DeferProc calls deferred statements.
@@ -28,5 +29,6 @@ func DeferProc(d *Defer) {
for d != nil {
d.proc(d.bits)
d = d.link
_ = d.rund
}
}

View File

@@ -22,7 +22,6 @@ import (
"sort"
"strconv"
"strings"
"unsafe"
"github.com/goplus/llvm"
)
@@ -181,16 +180,12 @@ type aFunction struct {
blks []BasicBlock
defer_ *aDefer
params []Type
freeVars Expr
base int // base = 1 if hasFreeVars; base = 0 otherwise
deferNextBit int // next defer bit
deferData Expr
deferParam Expr
deferb unsafe.Pointer
hasVArg bool
hasVArg bool
}
// Function represents a function or method.

View File

@@ -179,7 +179,7 @@ type aProgram struct {
setSpecTy *types.Signature
routineTy *types.Signature
destructTy *types.Signature
deferFnTy *types.Signature
//deferFnTy *types.Signature
paramObjPtr_ *types.Var

View File

@@ -23,7 +23,6 @@ import (
"go/types"
"log"
"strings"
"unsafe"
"github.com/goplus/llvm"
)
@@ -65,7 +64,7 @@ type Builder = *aBuilder
// EndBuild ends the build process of a function.
func (b Builder) EndBuild() {
b.endDeferFunc()
b.Func.endDefer(b)
}
// Dispose disposes of the builder.
@@ -141,6 +140,18 @@ const (
deferKey = "__llgo_defer"
)
type aDefer struct {
nextBit int // next defer bit
key Expr // pthread TLS key
data Expr // pointer to runtime.Defer
bitsPtr Expr // pointer to defer bits
rundPtr Expr // pointer to RunDefers index
procBlk BasicBlock // deferProc block
stmts []func(bits Expr)
runsNext []BasicBlock // next blocks of RunDefers
}
/*
// func(uintptr)
func (p Program) tyDeferFunc() *types.Signature {
if p.deferFnTy == nil {
@@ -150,6 +161,7 @@ func (p Program) tyDeferFunc() *types.Signature {
}
return p.deferFnTy
}
*/
func (p Package) deferInit(b Builder) {
keyVar := p.VarOf(deferKey)
@@ -175,23 +187,31 @@ func (b Builder) deferKey() Expr {
return b.Load(b.Pkg.newDeferKey().Expr)
}
// DeferFuncName returns the name of the defer procedure.
func (p Function) DeferFuncName() string {
return p.Name() + "$_llgo_defer"
}
// DeferFunc returns the defer procedure of this function.
func (p Function) DeferFunc() Function {
name := p.DeferFuncName()
return p.Pkg.NewFunc(name, p.Prog.tyDeferFunc(), InC)
}
func (b Builder) endDeferFunc() {
func (b Builder) getDefer() *aDefer {
self := b.Func
if self.deferb != nil {
b = Builder(self.deferb)
b.Return()
if self.defer_ == nil {
// TODO(xsw): move to funtion start
// 0: proc func(uintptr)
// 1: bits uintptr
// 2: link *Defer
// 3: rund int
prog := b.Prog
key := b.deferKey()
deferfn := prog.Null(prog.VoidPtr())
zero := prog.Val(uintptr(0))
link := b.pthreadGetspecific(key)
ptr := b.aggregateAlloca(prog.Defer(), deferfn.impl, zero.impl, link.impl)
deferData := Expr{ptr, prog.DeferPtr()}
b.pthreadSetspecific(key, deferData)
self.defer_ = &aDefer{
key: key,
data: deferData,
bitsPtr: b.FieldAddr(deferData, 1),
rundPtr: b.FieldAddr(deferData, 3),
procBlk: self.MakeBlock(),
}
}
return self.defer_
}
// Defer emits a defer instruction.
@@ -200,43 +220,62 @@ func (b Builder) Defer(fn Expr, args ...Expr) {
logCall("Defer", fn, args)
}
prog := b.Prog
self := b.Func
next := self.deferNextBit
self.deferNextBit++
zero := prog.Val(uintptr(0))
key := b.deferKey()
if next == 0 {
deferfn := self.DeferFunc()
deferb := deferfn.MakeBody(1)
self.deferb = unsafe.Pointer(deferb)
self.deferParam = deferfn.Param(0)
// TODO(xsw): move to funtion start
// proc func(uintptr)
// bits uintptr
// link *Defer
link := b.pthreadGetspecific(key)
ptr := b.aggregateAlloca(prog.Defer(), deferfn.impl, zero.impl, link.impl)
self.deferData = Expr{ptr, prog.DeferPtr()}
b.pthreadSetspecific(key, self.deferData)
}
bitsPtr := b.FieldAddr(self.deferData, 1)
self := b.getDefer()
next := self.nextBit
self.nextBit++
bits := b.Load(self.bitsPtr)
nextbit := prog.Val(uintptr(1 << next))
b.Store(bitsPtr, b.BinOp(token.OR, b.Load(bitsPtr), nextbit))
b.Store(self.bitsPtr, b.BinOp(token.OR, bits, nextbit))
b = Builder(self.deferb)
has := b.BinOp(token.NEQ, b.BinOp(token.AND, self.deferParam, nextbit), zero)
b.IfThen(has, func() {
b.Call(fn, args...)
self.stmts = append(self.stmts, func(bits Expr) {
zero := prog.Val(uintptr(0))
has := b.BinOp(token.NEQ, b.BinOp(token.AND, bits, nextbit), zero)
b.IfThen(has, func() {
b.Call(fn, args...)
})
})
}
// RunDefers emits instructions to run deferred instructions.
func (b Builder) RunDefers() {
self := b.Func
deferfn := self.DeferFunc()
bitsPtr := b.FieldAddr(self.deferData, 1)
b.Call(deferfn.Expr, b.Load(bitsPtr))
prog := b.Prog
self := b.getDefer()
b.Store(self.rundPtr, prog.Val(len(self.runsNext)))
b.Jump(self.procBlk)
blk := b.Func.MakeBlock()
self.runsNext = append(self.runsNext, blk)
b.SetBlockEx(blk, AtEnd, false)
b.blk.last = blk.last
}
func (p Function) endDefer(b Builder) {
self := p.defer_
if self == nil {
return
}
nexts := self.runsNext
n := len(nexts)
if n == 0 {
return
}
b.SetBlockEx(self.procBlk, AtEnd, true)
bits := b.Load(self.bitsPtr)
stmts := self.stmts
for i := len(stmts) - 1; i >= 0; i-- {
stmts[i](bits)
}
link := b.getField(b.Load(self.data), 2)
b.pthreadSetspecific(self.key, link)
prog := b.Prog
rund := b.Load(self.rundPtr)
sw := b.impl.CreateSwitch(rund.impl, nexts[0].first, n-1)
for i := 1; i < n; i++ {
sw.AddCase(prog.Val(i).impl, nexts[i].first)
}
}
// -----------------------------------------------------------------------------