From 56a5a7d72e4578e0bdc8edefddf66203a839f6b9 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 3 Jun 2024 01:06:01 +0800 Subject: [PATCH] defer refactor --- cl/_testdata/print/out.ll | 4 +- cl/_testdata/vargs/out.ll | 4 +- cl/_testgo/defer/out.ll | 190 +++++++++++++++--------------- cl/_testgo/errors/out.ll | 4 +- cl/_testgo/strucintf/out.ll | 4 +- cl/_testgo/struczero/out.ll | 4 +- cl/_testrt/any/out.ll | 4 +- cl/_testrt/builtin/out.ll | 4 +- cl/_testrt/cast/out.ll | 4 +- cl/_testrt/eface/out.ll | 4 +- cl/_testrt/panic/out.ll | 4 +- internal/abi/llgo_autogen.lla | Bin 3631 -> 3631 bytes internal/runtime/llgo_autogen.lla | Bin 12615 -> 12781 bytes internal/runtime/z_defer.go | 2 + ssa/decl.go | 11 +- ssa/package.go | 2 +- ssa/stmt_builder.go | 133 +++++++++++++-------- 17 files changed, 207 insertions(+), 171 deletions(-) diff --git a/cl/_testdata/print/out.ll b/cl/_testdata/print/out.ll index 9f89186a..8fbc290b 100644 --- a/cl/_testdata/print/out.ll +++ b/cl/_testdata/print/out.ll @@ -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 diff --git a/cl/_testdata/vargs/out.ll b/cl/_testdata/vargs/out.ll index a687457b..2dcb1327 100644 --- a/cl/_testdata/vargs/out.ll +++ b/cl/_testdata/vargs/out.ll @@ -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 diff --git a/cl/_testgo/defer/out.ll b/cl/_testgo/defer/out.ll index b37f04be..6ef57dab 100644 --- a/cl/_testgo/defer/out.ll +++ b/cl/_testgo/defer/out.ll @@ -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) diff --git a/cl/_testgo/errors/out.ll b/cl/_testgo/errors/out.ll index 599cc745..56719002 100644 --- a/cl/_testgo/errors/out.ll +++ b/cl/_testgo/errors/out.ll @@ -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 diff --git a/cl/_testgo/strucintf/out.ll b/cl/_testgo/strucintf/out.ll index f23f046d..57632d34 100644 --- a/cl/_testgo/strucintf/out.ll +++ b/cl/_testgo/strucintf/out.ll @@ -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 diff --git a/cl/_testgo/struczero/out.ll b/cl/_testgo/struczero/out.ll index 2bd65e65..48894dd4 100644 --- a/cl/_testgo/struczero/out.ll +++ b/cl/_testgo/struczero/out.ll @@ -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 diff --git a/cl/_testrt/any/out.ll b/cl/_testrt/any/out.ll index d2f59f3f..83e277c1 100644 --- a/cl/_testrt/any/out.ll +++ b/cl/_testrt/any/out.ll @@ -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 diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll index 8045b41c..ffd5bc49 100644 --- a/cl/_testrt/builtin/out.ll +++ b/cl/_testrt/builtin/out.ll @@ -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 diff --git a/cl/_testrt/cast/out.ll b/cl/_testrt/cast/out.ll index 1f6b0f30..5225b11c 100644 --- a/cl/_testrt/cast/out.ll +++ b/cl/_testrt/cast/out.ll @@ -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 diff --git a/cl/_testrt/eface/out.ll b/cl/_testrt/eface/out.ll index af51095f..c809135b 100644 --- a/cl/_testrt/eface/out.ll +++ b/cl/_testrt/eface/out.ll @@ -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 diff --git a/cl/_testrt/panic/out.ll b/cl/_testrt/panic/out.ll index 4bac3016..ce254403 100644 --- a/cl/_testrt/panic/out.ll +++ b/cl/_testrt/panic/out.ll @@ -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 diff --git a/internal/abi/llgo_autogen.lla b/internal/abi/llgo_autogen.lla index 747da4e5dd5762de366e733a45fe063c15df467a..eb0833a52b935b58b9da512baaa15a58ea7d1dec 100644 GIT binary patch delta 49 zcmZ24vtEWbz?+#xgn@y9gJB!T;fcJe>>0~q(z2GtY_y!t%M28ne3{pn87MZHlTQr* DRmKk9 delta 49 zcmZ24vtEWbz?+#xgn@y9gCV)$;6z?k_MKOw(so~s+GshQml-HD`7*CDGf-?YC!ZPs DcODR) diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index 6574534d716e05f65771ac9b1371ca6cb75527ab..cfd6dabb077ab6d264d3d66e9d6839992dbd247c 100644 GIT binary patch literal 12781 zcmZ|0Q;;q^w65E>&DrK`+qP}nwr$(CZ5v;8)#)EMhJ=f)%2l&49vpD7c>dP9zSd~fO; zEO1lT7OE(XFPXaz{m{Qhtm%W7^n6U!YHo+f&`29;|Ijmc`*n6X{XH|>=J(yc;$Qpo z{qOYY=3r*}>U$@D@8-50ah%`2-Tu{o_ge1RuzmOE{jP!A_U6*x-));8ukI?}j(y9k zy{|gEZBD$+_vdo{j$3iKB+!=k=h^Z}-X1>PP3h4`)q@rAuokAK{-rn`hUD z@o~d!gzQrF3x5pTFV(@X|5|a)j|C*|pR%3E^u0WU?47MM+ehR_XPhieIjz#m(mq}N zH9HFB@`v`1Ha?Bq0eECwc5A0SJNBRBWy2Ug0R11gHAZ!dOP}&~tlpHhFM_X;*_J=9 z?3kJfR!y9>dti13pX+`S>bKeIFUF7TL%(U|{Be7A-5*bO{>+xe3A-m(s2<47W4Rw1 zY>f1ow`m+*5?b7T4NC_HA5ZlTu`^bE>&shj)2m7yoa|vSd3Wg?h(}f*w4Z)!KECaH zvV0!{PR`E+Vidfo?(SFK@x6b;cHPb+5SB3BpD&Pp6Y_d-dJEXEj>PUdNC+POx&4~; z>V69}hZ(T>es_4S?<}{Yet5e(zqvi)Ue_uuyIYxO@0>o_+Y_vY<5qL`jqD7&aTn$r zGZ*)}(J$v|FZy`;uYWc1t;~q)aP+=g`Z_yn=-#@IFL}9JWk`~}PhEbzmsvjfwfb|^ zzO+{ld%d>(^h++{4SRKac55e^*ZUo!eq2z}=`B6FHGhu#x$Ayf6Ad3JRgLeg*sqn( z&_7?k**SY_)!x3$NaYq@MEr5yIZ8~fMc0_iE?dejUiyoBlghYMt@E}%>u=?DS;mKV zlP!4p`hZkh>-9p7|A%)em_22MH_oP`cOz-*`Q_X#A%0zDXArjBk+JkXb*Up~@omvk z2cBKd^{9STpL1q1LfsJIduWG+>Ch?L_%nX3Tf03N*?q(1PO=~vd2Q9jp>e0rog2&X zu?sOTro(-QLY`cg>-BsxLK`y8@5qhe@KiJ0|CWuw@fC3G?-02jk!`N^yJ5>4R&}|` z-&ISo(`9z{XB$Cmn@h+A@%3uw^kZp7R2cpD@P*~@qtuLycJEV#p>_BLw0uw~YaK6} z5ApfqbXe-?0D<{1Pir~1`KGB?M|_~V@3fUnyA#k_|ckNYG(dM;FG}OhScqU`kHU}BLDUC{&(|c zja{t0V`6z&;vJD=u-|*VZn;wT_-o0j(^Prazg6eg=tl@b^T7#;5k}Jktx?_NG#R-K z{D*KWobp5KW1+z;<;c>%;v|%Mlc4k^*Si0#yP}UCbT9q%YHHr;xwY%=VNT?`z{O8s zg+AgJR-yvS1B3MAAijVuOtJ)HjMpGA&z@pU{4<#v_Hx-i~s=N=@O+gvAqcwTb!7YNUy}om)&D68qPSMQQyQud%>*nfn_j9&w z?Kwki>2S{YUFir@M!govVf%L2+lVo-C)_)h2OOC^&uQd1&wU2PpU1?z4Ey8$O~~zs zBy9U3R<7K9#s&XBMdB@twloXU1i9x_wS3PU@DK~r3zM>|;!o?T!ohwUT3)p*wD|GVXH!H~ey zq9czZer)zMx%R&r&iicIR8{P(Oaz-r9$_sMU4_iBAD#8V1ZG$}oFDG9B#qkV#AJGn zK)$ok-SeMkmqw;{9Bh^*>$a=Ay-^?kSNZ)V1;-kW6k1!ea+2WFrRc_UVmECA>V7Dh zHR9(bxxDnbHT+EzNGK6M-*WwiDXyTmy;0Kx+^=}q&ruNsD|vb(OB(^ zJ?heSQ(O6HIBSadPV=GwbnD8g4~pCgu21l?7Nz~p1*U+371cBV@%FvE4K=-WvZy|D z*UN&kW)%DY^>NDlgS>nz9}DL3VcP2((0F=?aB05q%PjFo|A485hcPG3A1S&f6Ubxh zp%Z9t54;qRhEVpN+Wef_`<&~}E9GF;w!iH*VZ>#_hJ_U@`nB2}t1*wLv}@C^ci)20 zh*@=UDgI9jlWC}qt(@G*rgbHtI{^{^;oQkGhm|!_WZE_$BH3jtBC`Jj?%Me&!?=zx zL8LN9Qr;<10^@|xY7&vAR?`e1 zB~6t!kKHj|9lWP)cjh9eKc$78!!6SC3ZYKdLFFnMnb;{uWD3 z+nZvU(-ex>pgrU!DZnOi8;54UbKX|z$XzFOKhIaaZz|Q!7Tg*&QM z$EnIbS91lC3BN}uzM)CKmx;e;Bo$^5F>=yH-(1nCo&WhL>V>R*fgW6Cn4WPD^V-=T z5=%iAa!7^mj#A7VIkLvz{QN}|VmmB=Mi|6lL{V{)*sVXAFHxUf&>y$ttYfE^n{lN5 zhaR>l!V9AB7TLZeF`a(pzr6RrQboV^I;Y?9M4c&Kf0HG5yZXwH?>R18&oP@@f2ptU zOoMv<1;ZtEZ|``Bih<9~gg;2WFDs$zee)zeR2O5ee8$F#CMxbuxd(GnB^ZV_;hv~3 zmMj=+IxxphsmVdCK2IEIEOwJ8ERHdoWTZckVHfEOpn$DR`^4CWf{AEBqCH`u%o!7L z45$AY&3}8KXN`lFIg(1<>H67_NQ>Ly!fzlt@MtLUq>y66*){Ks<^@S|G)Y*kPX_v_ ziZt0hI~!>1Io^Co!toE5eTPN64c~qXP*B&>rnJa;Gi-5T3&NGSsEmpu2p@^DI_1tp zmDyhgsW`9D+hBY%g3xFxAO64UBts&JQWjm1y$X_0CNBxg^FlT(KP$q%+J?M)8&uSDD`M) zft>~84v4^d8cXLmrw2mZM`=Zum(y8#mafu|%$R(YB0fWmqKTbK`o(VhEfr&n+q1$>8Q)a$Afz}X0`Jaw)$pi&L0uhv)8LPOM!(@h zO9+ecQSF;zFi?~aM`~BEIM&H||KK)6ou*siYwmF^VzoB0I#-W)+*2q%iZ&hmyVURB zyLagOAm_+oyDWT`t<(eQ!k=R#;M~lF>|C&{(NJiyoKsxKI~4O-%t3|7`g^Zty_2BHG#RHArGY>xj2*?40xseYQJg|uW1y8&!$Ik(?#o$i zxTIZT?GNC|sZmY6x7hv^TZ>=h#`_#iNuhjr<5V1*1ZysWQqxk&|KVlkk9Z;%%k+TG zfI?F8a-=xK>99Gql_zE6kK%C(LenG_jz z8!RNgwlw|pt|#lL@x5%Xzfm$-D4 zVqOSzL-MRv_yndMqT$3XpOHieu^W2|KL09Sz8;c@h9ZM0UxT<|XFq~FDyM@f&bLeI z-DL)<45y)><=U5}9azl5u?8-V8wA+I1HGF_5K1UM-O2s)&Vwd#K%u0DQsIB(JIN09 zfR(Ee+@mRAnW=G5k=BTHdpqefG;TS>7w&RIvnQ((h)}eQ7g*?4q~u-Z_N7tM-g#zJ zj7>CNi0trck1L1DU@3aC`rZwCiYx|TH6&dZ_2vzBekx_c5mO*tFc=E)IvswS+`j4dTTte8{T=CfZQ zyDuS)79qWO9te+&905@t-EVAM?$8uRc|6WSXiE7PSala5=MD0(i)0%+zsl&UY5N$M zr;oA98=^Z14Jl#%_jfnMy!uzFjN!w-=RW*^i2Oi+oG~DC`D!aamL6?l532JdaXfG> zVcf){5fYz^fo5vpVO@IyYm63Pj%&Gj-F^Fl??CNXKw-Q{6%I5TqK0s2QGqGu+(&c$ z4vZMcBfgCk{*%*h5HZZDlod*6Kj^D~cry&skDlni*_JXVAN14ZiBsNx^SVU|WdoSM z3TUc4;NUwHV>;cLso;kPPH5S;L+39B6xRNojJzC3?1Pk(n1BbmeH8@>S8Re`7mqF=8HmGOG8Abs%=taHYs2*x}7|T_40m?Awv@LJm-!msEjz}zgNfdiV zZ;t9nJfMCM*A|VW4D(&k0f@PDZt(YPtl|%?(5m|rWC1_b*OBscG|lD9$7fPZzrbGC zc0Z_sx1p1bD?_UoLB86{zaWs)qu%#_@S|AM?+oy;e^n1D`*Do+pJ3bFG{Rg+%XR)} z`ezRc6HGZyE9xM2COwPcdvX5EYybR2c{9$OAnF8A>Vqpc>7GNsV-ofRI!>xHpem{9 zo@FMOJP%8$6u&wV{r#3ChaNYeViHwpQVN=2)R$+~u~C4>%#L4l zXw=+wXnd!H!{lv#!(`Vve@dg69u>FkB;We5_||QlEBOY)a;xmO5kIt ziTQ%#?;Dz=OG;rjVNe;!_#nEQOq)9NYUUfl$3BWBs7cJ9YjSvzze7kphl(a5IApmv zm3Q|h&m8ZYHTw(4E>V@thEre2)?QT_T?V6z%vlDIu;p<{bQD}@*}w%h1BoJ_f`J=o_ODCpa-rO!LUX1kr4i!{q^q6K+LU_uBFL-CV%3){i%|aG7EdY z(3C4fZXn>@m4ER-dT@uj1Od7k%5v*!`#dfq7uqTXBCZxY$m)X6waw(FyGTqK%JC)Y z2r|P#^X!vVz)-%iX@J&V*pN#}5^{+`>A|dmBiB2{iU{R zh89MW$9nkq>;&bfAD81{{YNQEFX0n?QoR<1D3(05wG0}Ub_qiKfTB99$0&O02$xeq z4?5Ix7jQXu;D8Rkvsgh_IN%XlPDJb!%!E%$v@c4^CZ&sPBoA;dDs>`&6qHF~P>pv% z7o^6=ZCzh?-|zg`^GO}c{7}Z6AhF=7NXt+(y*7|5t-}NWlM{cPHB;!CpeY#6O{ zt%})b@U2+X=pcb9>hpC*j{TKr?4<1=d)rsd02TImXiPXn-WcA9`hV&Rp2#~5;;%y{ zJpqLPC!vc;d2o??yrJ1KWwO~McAeVmBqGeRqKGM6w#*SGdkvT)hv)*DL(zFUD*Zza zFNh2f=+ZgVJ=P;;a7dVLLm2l@eXXsi!3wnpQdmat93@6L3A>!^>B!kJ79{VN*DXGI zzmjWh@_WK09$$SxOSg{}k6%eN^1LCFPK7^?t>g7Ae?0jt3BsUYE8@p>El2?j5CgoA zepWqeup^QqO8V1yF;-lUh1y2*Bcaz6M*jVAxu@C-r(dDMy(}I8AB_lt@J7U&umFNX zUI&&2T~#l-wydFG03y)KOv+|rDZ{pSxlE8wTvbaTvbL03m>Uzi2|+*@T*25EiMH{+VZ?Erh*KFOB}xdX(%Op z8Drb9sOKxGZI;R01r#CgSJcw7X5FYzT|ed%tZq?oUP~f)Ck~o~{VF^tZZQxp!NMSli zmOxr7Kk`DOm(R>w75yC7_Z+w9j+D7}mR-8yTXPl9#P}tN$(EjEX?5GT}$QC%m6@%McC76;6kJa{I z(s07E?(a@~jE7Wyr*(-owUGlcJ>XJMka>jgA!6OEAw=b1Z5pvm+Emc#Izq^=j2DI^ z4Efr#@27_2_cPi5zR#rAvaH{lhq+8F6#xxv+gE$inLQIhp+ajP9rEj6VTfcvX9B^_ zlsu>gG9!#|ShZ@+#4lGn&p%~+5twYc6Lcq5TZ=@}KsYYw@5+J34=ZHF;CQz97NWN% zRDvb_GQ{`C2`Ew2$irgE9uFL(Ka8py%uFF4-xm#ieBVvGe1K(ZRx@dNgna8MEd|+Z zMMc!#Su+nStvGiHLf+B?fvlS=#OS|Am60=k)bQwINEjFq803-!s@K(F-RC@bZHMWe z63E}|ypIL=j{*ZyF5<4ef*hE;t&vP<6pAo9oJ#fZ*nmoV2Kg<@FA$dZ5D#04i&iSz zYI;RPRf|kHORe2BleEVgC)({ga6Aer-RhPfpSPu~;N|=Dqei|Qy<5A>*S#8dduz?= z7;^G@rk}Em#YSDBtU3(2+y*-1DMo&15l+$BL~WIdmze_BumKGZ^Rl-pj(zYz%)Tmr zblY|3WFAXUopT$RBz^2NiO-eN7sOm$+Co~1q&Oo`1U$YCGb7*Q%i_s?yn0y6c@2nE zqOd!&=UQXmcr|Oa5vAI7O#w5T?BF8UhL}p3YabWJ)D7sAes;j2)F#xs&`(AUXRjUK zcNOQBC`{>xu&c_m%2blIQTW;&o^qgvFmj&5xCz_qdxf%meavm`40w&~R2LaX4x(r1 zp8oC6_v&R`w%Pa0-n|O-2<1*-G*$$0xEi~NOkZGS&KfHF9rfWLtMGzNBVw?%2D!yd zq7kYMm0FSME7!SJD(0eQ(jZE%wkds%P|O9pS&FAw5^N`cf^Uv?oj=f3xlRb6+7WG~m`O=FNxaTSV zl2Dt$J`fi1rmL7${; z;WJqDm};2j;zlj&^bp(oSAKTKqe{mid=hkT+9&|024mE)&C_mL`<_gHWwiPO{uD8A z5wl2=cUbdZ{G=Y%v{3ZXcm9`Z%H+*Hoajju1pJ{PXqC{dQNWQK_&rq{3-T}~gr{hC zNnN#f;7nh3vIuRCLSH(n^d61U;Lnc=FQpqMMN0quRSt_hkZL^|VqG&<7gLBl@mloE zB4OnH0>dL{oi_5U`r;%Nd9#evP0+h!0dW)is@d;}->8&S>1$*TTMG=CBeQjsIGz9# z<;ddoTL$jMOS1Ao6TTF959k2f3M*Gdvb~n-tpKg>lEkc$>}icQ80jEaS1ZH`nT^qL zx(Uz>?L8WsB){BC{gDo_Q7pomg0Y|^LAv5YGPNf@jb2qqgJY%YA+J~zedB!1_Dg48 zmRzcbrj(QwfR;cN12Bj z;K^LqmwDrwrCV^|;?bFd@KfIe#F&7q9|#G+6V}cn>q-dPMa3=>IOr6mDMJy)h@>l@ z-{gy35r2Q5Em)0ZD9@+Oh>AP@73*Xqm0O7ftiTzpK+BUbPbr0D1HGl5356@Fi&D2n zwY(WGlF>^rO&Xbe{2D3S+mmm`xHM-j&$+!tWJN*l@#PYoL{wW67W_GQ*AfNb(*vc#Ka~I4Z#vp#yoSBUVLMRED2sJDJUi zSpv^nFCb7Lli}4TqB3GMmnx%P@i?skjMGAU`*h`%@B6p>>9S-BQgAsTlE(F3UK%;C zpK-XqpOZ1QK4HHt6xmmFFp&*+l5d@Q!2{l$e7s*zTl^lk73yX?w3s7N6ytCj4@mP~ z;@2I+-*(&!`XIM&G%-8N1z~t#(WZ9tIwPlPJwp-{P-hPJSh;+@pS{{U^MqKeRf@0+ z$OwQJY9J%YZ@4cgThB2Z#)9GS3h_Q8QyJ=$P+Rv>;8jnLPa0lo9>~~7BDB!qw(msd zI%5uH*bL95ypQTZF`2RQ=Bo4kxbo~ShY$QLn{bFdfam?vb%@My=I%%EO|ifzc&bjV zqNx@$%cZ5F#z~3(kf9mPSReZO-3x<))li3bERu9d;36qwhAm0Rn2pH9X5>X$3J%3F6hLTY z!StE{eha^+&rHZGmr*c^jVXw92$fBQ%J?_^?D*Fy!~<-#H<;tjk#wz4-y(YYYqYf@ zM3>R%PY9WCWHh5@jYdm3eGR@zUzWhzA_;#-gRv9vM^E0b(jL`W@P6p=Y9#|N<7o>>)9xWpAiCg*uXe&&!S1O~trLkU}>MsOP02DjC>xLzQk^&!`zT=Az(S7Y6M|l47HXf#RcX zTU@!-o*12QZ2as>-E14V0)7^FS1{z&xTgbIoDeB+EMl!U!8SOEjV8b*@~Tdp&MDyZ zC60x^$t~pe;b*=siP@CA9W1P()v*qa9LrfdIsrXHRV3c?X$;n6`N5azC+$OHTBvWF zl>GwBDVcmVvV^ZwlBiQMQ@S7$sYNNewDeEE8!K_MF{%pjujaHW@xArN23ANHOKUrT zy|`>XE(>Eejnx(hCRh7Bx$>`w`xKB#5c#S3ak~)tKU5~$jHXkf7Tl#4Bi~w)_FAl| zsXvU%H6}rR`;TV#6-y|JD$?+@3PoC*G$TPc61~b7DZ-OrMBTy&GYpb~Y+-07ZO4i4 zC4|8xgpZQI>UB)fC?<4d1$8xItl<=>Ca(^v`*6u9CdQP4X`9>_4iy4Y37!(EnF3V+ zVFkS27%_8HsNw9@2{~f1x9-Xd;BY<}f z%V`Jo6^ApyEqS;HJ7;T2a?aH*F)9V*B;-tdj7w5^TTdE$eelFwGf|+d*RGSyH!VSN z|4HZQm6N{zbm32$`b%1hl)+z=2C`IJGK!ZpG|9h17%mp#Fc&2zX+7zW(|QwjjFy6o zVHjw%vre)uFA*qIK?7E$&tCiLJ`1t;<2yDxop7fl&2Hrn)I3=(d(aqcLT; z)5=$wRk}g89GhUd3;y$q8j+QDDaOmONm}MgAD3d#E3u1H7tNtti*9z_cs1G`xdkm@ z$sbaHSG_pT+tTk{>EGV;yWaG?-m)FWX#?dhBh-Ir*%mP%WGFgx)H02gI3#SUZ4j#O zM#|u$WmD+cS!{7!3Z5`2(;hQ%qEre^enjMzHDd`=Q{<_s^3;DNsQ=0bR_TCOJwzFM z2kd!`8?jJsnGb07QsURjqNgsDH4)iLk-?`)#zixjx1mL6a&^5&SP+_D&8 zr(*6LZC+OZm&Ggu9sj7Ma#J-%YYr+&GgpTR?ALIPR$!ONZj6^Ol41*+WHH(bdmScc zmJy7no@s_&HDxAkk4W8@? z1zQr6Nm5i0gdTvA0y!^?1SQB?4?8RyU8zdQ2bE_0%}o3Q4cvBk+77R2sn`H9Gg?wR z8gTMv?TrfwFvyOPgvuBcH6v_W$w0DYBL`cLeZRf_rW*Kh(1x(=rwV@+{{z%0>O$-@ zRI+2DB94N6B1t@zN}7&*M}~Y^mcrnD)j?6Y!*y`NsJ-?zyUBH+$*4Wf8RSyB=;Lr! zAyQuezRr2WLDBLLY;tPtMn}FXwUwUsDMg1z8iZSYFgF=1-Ri8vv|)!6B3hfJzu7Hr zzc>1Fym~b!gH}pQo%>SG<6}YB!CTKM{xM&E0KN_zMe;L*y*QH-W(%( z;q?Ge^yN26c?<`-MTG9~k2v}z$^(_K*R`|HEpK$e!O)0V9N!!*Qd)6AQqhU>1KR$uu9mbjfd|JgHA|7D5kdQWR1!!)=nlKnh~Q%$sU8y*JyP^&G2_ z69$cTT5Dynd?34*&e{`E=wsOV6(}=+UG_C3-#J4dajm2aZ zVlgpSd^CnUj{;lQ5MdPaDN~W1sT~||W;v5El!vSb`gfXBxvUIETz6!D|7U`DTKTB! zW9%e+l07Vqj6>2hA=)ILN z>~AcyN>cK9T1fm84Wl=43v4Pdc%yKv<=(!Blrn*odD4nJb z63hW4G2a#T+8tyQS8`kq8Ct856?p8(rJhw4#{%7v_0;4%i|gAF&?P>$q9 z^?jg*x^n$ayA6(r4!VihD zzwne|M3V*51H0}Ea72gJ1F{+(S+j)LKMgNaLY)V?Hd0uK1nIJh_-*_V*jz^ zzA(Jq_r0O=?@y=ynl~$(!I7uuY&6CB(DNt`N100Vrq2^6Y?H&Popu~^krF~0oKWKx z{3jBYA*Ftx9=1wK*TYY|Ny732{H;UZ^-FvMe{wlz6`{k(0eks~c4Q$keL-+%j#*y; zltWLZzFzHX3L%+NN%CZG3t;E90_FnLSkgx|ekPYeqz(#0698O%WnLXV#f__z>AAhV zTSN+5dl~eWSPl~Pdk1yT`JL@VHz70 z%fcb~10Yh8rI2|UJ`ttrrj=Cilc?|L59T;Nf(gGgTANsmm@sEaR$v)0fKqyW5L>!5 zs1ftBXlQZ)-)Ueq5JcmGhesfAr+PcOW)!nR0|+aM6OQK!!S_D|k()~NPGn{$^8*=2 zDrh&E5z2y++5yfQRm9_r>`yWwZn9vjIe_SUxMF7w?{MRh->!_nZ2cJv1 zpeICuLH4gFfb~_3FBAJ>C?@^9G{NEToq!O1iYnqzj>oI zK7w9lU@H+@k))X;VS5lCD9u{HxhjPR5#t?i;HBE zN@}iHwv2ws162q%nzjV84;Ctyh;AS|X$oUUr6hD0;!dH~lbe{@yw-@V_$E0vrDLJ( zC4Q(`7&8W7#HpUa2_jo6>!AE9Qp&z))SJ)nX=Z5#F;eE=q6wWeTa2-Ttz;^cTwkCi zPD%@lfXZ$w!uYZ+K~H<<#5VMU2w>$io=8z=2p%LFI)+o1Y8_qEvK*^P-F&bvJ6QuH z>o?0}6F0gU#C&CepRCE?eiMFJW2i|ui4#rI#FDlzHX*6S0!LzGIFqSn_v&)Vv)ggv| z3$l5?bN+tvaG0h9kq#D6p^=c&l+NQamHycWaTWh41CH$y0k;#J_`**7yPF}0ojf|& zWg0!V`dBql)=d1Cj2$|xx@F_H8T6gjmzaOROJzI3i>UjbTyM>q9>pSoD0ki{t~)*A z{Sd7$jn^ekOox-}zmPK==>8ASoQ2{C_}MjK`Yt&GBW{_c({dQ*v=e9SU0Z*zaz3;` z-AIW{eIr$agZWO|?yjj}vx zYqtj$Z-e!?LA&TF-JuvPco-#?-ni&rDQ_AOphv3kSs1{Rh%uSHxeuh5r$xackYXy{ z?fP}G9~Rd7dnVn)GC#U%hU+j0kul!;&Tb+Y81M&Hl|KX7{t{$xk(hj$aLD%^D`NGMjWnWys#=FaaC;&6cZ9X-DCBo6o zv3g_JE$Y~vNsZeM^qikFyuZN+-T5?K23Q&vkKU(C}^2lmdih zuKKM6Ryx>?pAVuMAvEkrs=?p4I|w<@PA=naqAofTaJG`Tu9ztx&%{Hp51>E=S3N=q zBLS9FH}1+4gU5pTUgg}{2x-opUUPEvbQxZz-GlyKUk!p7Izvx--KbufcfDx}VK7*6 ztr4`zjN}qGXY;9LBb2MHQ{|0t#yU065#a|bM>hPl+S2}`lfDT5u45*irU7IfH;YZy z79kA{JBt^OYB}yOI!ppi@0P^JxWwpD#4e8>ZZ$XfSU!gaHK(=Vv2x1618#y>&#+ss z{kQTzczsui!M$02_==e?fceb521dyPY?z&KK;u>XVY^^K7YNE*MStO&aiQh%VdaRZ z@F7JncrB%(zi5|R{FHiy@^J5qzPW+9mkz{=n%D8xS0(+gNVubBu~agluCM14?CfEy zk3D4f_&Xmq`uv4lA861Mq~v*Lp9cgwoUGRnigW@-G=Z+=tk#z`g`UD2X|tV@dKDyd^hfvAYtd z69kj^!L0Ynii6P*4@Eg@8W$CtiSyUj&CgRIa^RF6g_}0WAhi&s&w6vQ;qB^g#sB)J zZgB=_uUBG1zmmHmFy1_E2LE#kyFUtD)h=)XuJrr$V&=b;dWxW2Fhx>~`4IH;;oE#1 znD2~|t#kr)E#LBUt#@|&SLq!IeV<*H(Yu2&94QoYfB_DDdT~@Z?tCr#ARI8#D#}s1 z4P%_q;Jz!k%icYaAJ6;t?k$Qw%4#J_f&eDR-VvX~0u~gTUvTXOqW zsaB^316ZDR{vnQAV;%Ox-S`c1upwkPl}mgh+ul&*mRct=!^a*flnxv`6B}uk$5RTx z&TXb!8;#Z7|A{dZ@58Pny>T4|ZqEy_MRrjD2~Y1u!vst zBNRK2lyY=U9u<62QE1N6mk&y*KY^+pdc4NT%%;F<3vA|7LA^;-%ALMMI50ZLSzS^S zP(Pl|^_5=LFY)v+&mjgDECi#}FsG+>9fGY?QcVI?JJMxPy4={-bS9L}z>s=0uzDvJ z1;jh1ocuQ$7|h6~q;~nkK`_kLyPYCtf9ULi1`NyQrYD0;Hq%O=on%bG5FvoEw}_sX zC}eW^@ZAyby|dM9lp_tRv7TZcEAhe^_IPZ;d$f9e z-XENvFJJopv$wByKi4Af$;0*U)}eQe=dMf7>eKJoUv?Y&CIwf*WT!J)0&~6e{N>#D z6T#YmNU(S}sqUr{d$zAIa zM>A;X&Pd<{;;wCGJcq{{@Nxg16AiDNH2*>>NCSiX0sVh57+C+Y89+e)K^8zIf&a7n jzlaR*|BuM{|Iru<(%=yPa~=4Yvjy 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 XC0R(Q|1k&sZ>ayLH~+&WKtTQv^H?iq diff --git a/internal/runtime/z_defer.go b/internal/runtime/z_defer.go index 7f59abb4..007d4888 100644 --- a/internal/runtime/z_defer.go +++ b/internal/runtime/z_defer.go @@ -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 } } diff --git a/ssa/decl.go b/ssa/decl.go index 4dc2badf..8abe0339 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -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. diff --git a/ssa/package.go b/ssa/package.go index 4cb779a3..98e471b6 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -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 diff --git a/ssa/stmt_builder.go b/ssa/stmt_builder.go index 9f92efea..17449b86 100644 --- a/ssa/stmt_builder.go +++ b/ssa/stmt_builder.go @@ -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) + } } // -----------------------------------------------------------------------------