diff --git a/cl/_testdata/print/out.ll b/cl/_testdata/print/out.ll index af0ea398..2e91fdad 100644 --- a/cl/_testdata/print/out.ll +++ b/cl/_testdata/print/out.ll @@ -51,7 +51,7 @@ _llgo_0: define void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %0) { _llgo_0: - %1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 %2 = icmp eq i64 %1, 0 br i1 %2, label %_llgo_1, label %_llgo_2 @@ -680,7 +680,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %0) { _llgo_0: - %1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 br label %_llgo_1 _llgo_1: ; preds = %_llgo_5, %_llgo_0 @@ -690,7 +690,7 @@ _llgo_1: ; preds = %_llgo_5, %_llgo_0 br i1 %4, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %5 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %5, i64 %3 %7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8 %8 = icmp ne i64 %3, 0 @@ -783,8 +783,6 @@ _llgo_0: declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) -declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice") - declare i32 @printf(ptr, ...) declare void @"github.com/goplus/llgo/internal/runtime.init"() @@ -802,5 +800,3 @@ declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llg declare { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr) declare { %"github.com/goplus/llgo/internal/runtime.String", i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2String"(%"github.com/goplus/llgo/internal/runtime.iface", ptr) - -declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice") diff --git a/cl/_testdata/vargs/out.ll b/cl/_testdata/vargs/out.ll index 56930b8e..4657338e 100644 --- a/cl/_testdata/vargs/out.ll +++ b/cl/_testdata/vargs/out.ll @@ -48,7 +48,7 @@ _llgo_0: define void @main.test(%"github.com/goplus/llgo/internal/runtime.Slice" %0) { _llgo_0: - %1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 br label %_llgo_1 _llgo_1: ; preds = %_llgo_2, %_llgo_0 @@ -58,7 +58,7 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %4, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %5 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %5, i64 %3 %7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8 %8 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) @@ -80,10 +80,6 @@ declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llg declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64) -declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice") - -declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice") - declare i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr) declare i32 @printf(ptr, ...) diff --git a/cl/_testrt/builtin/in.go b/cl/_testrt/builtin/in.go index a252a6d5..e5416b37 100644 --- a/cl/_testrt/builtin/in.go +++ b/cl/_testrt/builtin/in.go @@ -40,6 +40,12 @@ func main() { string_len("hello"[1:]) string_len("hello"[1:2]) string_len("hello"[5:]) + + s = append(s, 5, 6, 7, 8) + out(len(s)) + data := []byte{'a', 'b', 'c'} + data = append(data, "def"...) + out(len(data)) } func string_len(s string) { diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll index 9201f246..e446abe4 100644 --- a/cl/_testrt/builtin/out.ll +++ b/cl/_testrt/builtin/out.ll @@ -14,7 +14,8 @@ source_filename = "main" @1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 @2 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 @3 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 -@4 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@4 = private unnamed_addr constant [4 x i8] c"def\00", align 1 +@5 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 define void @main.init() { _llgo_0: @@ -57,7 +58,7 @@ _llgo_0: store i64 2, ptr %10, align 4 store i64 3, ptr %11, align 4 store i64 4, ptr %12, align 4 - %13 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %13 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 call void @main.out(i64 %13) %14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32) %15 = getelementptr inbounds i64, ptr %14, i64 0 @@ -69,64 +70,64 @@ _llgo_0: %18 = getelementptr inbounds i64, ptr %14, i64 3 store i64 4, ptr %18, align 4 %19 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %14, i64 8, i64 4, i64 0, i64 4, i64 4) - %20 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %19) + %20 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %19, 1 call void @main.out(i64 %20) call void @main.out(i64 4) call void @main.out(i64 4) call void @main.out(i64 4) - %21 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %21 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 call void @main.out(i64 %21) call void @main.out(i64 4) call void @main.out(i64 4) - %22 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) - %23 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) - %24 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %22 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 + %23 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 + %24 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 %25 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %24, i64 8, i64 %22, i64 1, i64 %23, i64 %22) - %26 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %25) + %26 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %25, 1 call void @main.out(i64 %26) - %27 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) - %28 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) - %29 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %27 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 + %28 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 + %29 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 %30 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %29, i64 8, i64 %27, i64 1, i64 %28, i64 %27) - %31 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %30) + %31 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %30, 2 call void @main.out(i64 %31) - %32 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) - %33 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %32 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 + %33 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 %34 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %33, i64 8, i64 %32, i64 1, i64 2, i64 %32) - %35 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %34) + %35 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %34, 1 call void @main.out(i64 %35) - %36 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) - %37 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %36 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 + %37 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 %38 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %37, i64 8, i64 %36, i64 1, i64 2, i64 %36) - %39 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %38) + %39 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %38, 2 call void @main.out(i64 %39) - %40 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) - %41 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %40 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 + %41 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 %42 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %41, i64 8, i64 %40, i64 1, i64 2, i64 2) - %43 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %42) + %43 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %42, 1 call void @main.out(i64 %43) - %44 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) - %45 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %44 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 2 + %45 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 %46 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %45, i64 8, i64 %44, i64 1, i64 2, i64 2) - %47 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %46) + %47 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %46, 2 call void @main.out(i64 %47) %48 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 4, i64 4) - %49 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %48) + %49 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %48, 1 call void @main.out(i64 %49) %50 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 4, i64 4) - %51 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %50) + %51 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %50, 2 call void @main.out(i64 %51) %52 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 4) - %53 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %52) + %53 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %52, 1 call void @main.out(i64 %53) %54 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 4) - %55 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %54) + %55 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %54, 2 call void @main.out(i64 %55) %56 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 2) - %57 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %56) + %57 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %56, 1 call void @main.out(i64 %57) %58 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %8, i64 8, i64 4, i64 1, i64 2, i64 2) - %59 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %58) + %59 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %58, 2 call void @main.out(i64 %59) %60 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 5) call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %60) @@ -141,12 +142,41 @@ _llgo_0: %67 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %66, 1 %68 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %66, i64 5, i64 %67) call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %68) + %69 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 32) + %70 = getelementptr inbounds i64, ptr %69, i64 0 + store i64 5, ptr %70, align 4 + %71 = getelementptr inbounds i64, ptr %69, i64 1 + store i64 6, ptr %71, align 4 + %72 = getelementptr inbounds i64, ptr %69, i64 2 + store i64 7, ptr %72, align 4 + %73 = getelementptr inbounds i64, ptr %69, i64 3 + store i64 8, ptr %73, align 4 + %74 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %69, i64 8, i64 4, i64 0, i64 4, i64 4) + %75 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %74, 0 + %76 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %74, 1 + %77 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice" %7, ptr %75, i64 %76, i64 8) + %78 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %77, 1 + call void @main.out(i64 %78) + %79 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 3) + %80 = getelementptr inbounds i8, ptr %79, i64 0 + store i8 97, ptr %80, align 1 + %81 = getelementptr inbounds i8, ptr %79, i64 1 + store i8 98, ptr %81, align 1 + %82 = getelementptr inbounds i8, ptr %79, i64 2 + store i8 99, ptr %82, align 1 + %83 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %79, i64 1, i64 3, i64 0, i64 3, i64 3) + %84 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 3) + %85 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %84, 0 + %86 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %84, 1 + %87 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice" %83, ptr %85, i64 %86, i64 1) + %88 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %87, 1 + call void @main.out(i64 %88) ret void } define void @main.out(i64 %0) { _llgo_0: - %1 = call i32 (ptr, ...) @printf(ptr @4, i64 %0) + %1 = call i32 (ptr, ...) @printf(ptr @5, i64 %0) ret void } @@ -163,14 +193,10 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64) -declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice") - -declare i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice") - -declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice") - declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64) declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64) +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) + declare i32 @printf(ptr, ...) diff --git a/cl/_testrt/concat/out.ll b/cl/_testrt/concat/out.ll index 2ebd426d..af3e1e82 100644 --- a/cl/_testrt/concat/out.ll +++ b/cl/_testrt/concat/out.ll @@ -18,7 +18,7 @@ source_filename = "main" define %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %0) { _llgo_0: - %1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 %2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 0) %3 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 0 %4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 1 @@ -39,7 +39,7 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %13, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %14 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %14 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %14, i64 %12 %16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %15, align 8 %17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %11, %"github.com/goplus/llgo/internal/runtime.String" %16) @@ -100,10 +100,6 @@ _llgo_0: ret void } -declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice") - -declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice") - declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String") declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64) diff --git a/cl/_testrt/intgen/out.ll b/cl/_testrt/intgen/out.ll index e4ffe19d..8d91dd12 100644 --- a/cl/_testrt/intgen/out.ll +++ b/cl/_testrt/intgen/out.ll @@ -16,7 +16,7 @@ _llgo_0: %2 = mul i64 %0, 4 %3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %2) %4 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %3, i64 %0, i64 %0) - %5 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %4) + %5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %4, 1 br label %_llgo_1 _llgo_1: ; preds = %_llgo_2, %_llgo_0 @@ -29,7 +29,7 @@ _llgo_2: ; preds = %_llgo_1 %9 = extractvalue { ptr, ptr } %1, 1 %10 = extractvalue { ptr, ptr } %1, 0 %11 = call i32 %10(ptr %9) - %12 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4) + %12 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %4, 0 %13 = getelementptr inbounds i32, ptr %12, i64 %7 store i32 %11, ptr %13, align 4 br label %_llgo_1 @@ -76,7 +76,7 @@ _llgo_0: store ptr null, ptr %4, align 8 %5 = load { ptr, ptr }, ptr %2, align 8 %6 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %5) - %7 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %6) + %7 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %6, 1 br label %_llgo_1 _llgo_1: ; preds = %_llgo_2, %_llgo_0 @@ -86,7 +86,7 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %10, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %11 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %6) + %11 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %6, 0 %12 = getelementptr inbounds i32, ptr %11, i64 %9 %13 = load i32, ptr %12, align 4 %14 = call i32 (ptr, ...) @printf(ptr @0, i32 %13) @@ -105,7 +105,7 @@ _llgo_3: ; preds = %_llgo_1 store ptr %16, ptr %20, align 8 %21 = load { ptr, ptr }, ptr %18, align 8 %22 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %21) - %23 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %22) + %23 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %22, 1 br label %_llgo_4 _llgo_4: ; preds = %_llgo_5, %_llgo_3 @@ -115,7 +115,7 @@ _llgo_4: ; preds = %_llgo_5, %_llgo_3 br i1 %26, label %_llgo_5, label %_llgo_6 _llgo_5: ; preds = %_llgo_4 - %27 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %22) + %27 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %22, 0 %28 = getelementptr inbounds i32, ptr %27, i64 %25 %29 = load i32, ptr %28, align 4 %30 = call i32 (ptr, ...) @printf(ptr @1, i32 %29) @@ -135,7 +135,7 @@ _llgo_6: ; preds = %_llgo_4 store ptr %33, ptr %37, align 8 %38 = load { ptr, ptr }, ptr %35, align 8 %39 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %38) - %40 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %39) + %40 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %39, 1 br label %_llgo_7 _llgo_7: ; preds = %_llgo_8, %_llgo_6 @@ -145,7 +145,7 @@ _llgo_7: ; preds = %_llgo_8, %_llgo_6 br i1 %43, label %_llgo_8, label %_llgo_9 _llgo_8: ; preds = %_llgo_7 - %44 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %39) + %44 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %39, 0 %45 = getelementptr inbounds i32, ptr %44, i64 %42 %46 = load i32, ptr %45, align 4 %47 = call i32 (ptr, ...) @printf(ptr @2, i32 %46) @@ -159,10 +159,6 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, i64) -declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice") - -declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice") - declare void @"github.com/goplus/llgo/internal/runtime.init"() declare i32 @rand() diff --git a/cl/_testrt/sum/out.ll b/cl/_testrt/sum/out.ll index ed29adf4..e414fa91 100644 --- a/cl/_testrt/sum/out.ll +++ b/cl/_testrt/sum/out.ll @@ -44,7 +44,7 @@ _llgo_0: define i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %0) { _llgo_0: - %1 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %1 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 br label %_llgo_1 _llgo_1: ; preds = %_llgo_2, %_llgo_0 @@ -55,7 +55,7 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %5, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %6 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) + %6 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 %7 = getelementptr inbounds i64, ptr %6, i64 %4 %8 = load i64, ptr %7, align 4 %9 = add i64 %2, %8 @@ -72,7 +72,3 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64) declare i32 @printf(ptr, ...) - -declare i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice") - -declare ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice") diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index 452cc462..fdd1ba93 100644 Binary files a/internal/runtime/llgo_autogen.lla and b/internal/runtime/llgo_autogen.lla differ diff --git a/internal/runtime/slice.go b/internal/runtime/slice.go new file mode 100644 index 00000000..d692a710 --- /dev/null +++ b/internal/runtime/slice.go @@ -0,0 +1,40 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +// nextslicecap computes the next appropriate slice length. +func nextslicecap(newLen, oldCap int) int { + newcap := oldCap + doublecap := newcap + newcap + if newLen > doublecap { + return newLen + } + + const threshold = 256 + if oldCap < threshold { + return doublecap + } + for { + // Transition from growing 2x for small slices + // to growing 1.25x for large slices. This formula + // gives a smooth-ish transition between the two. + newcap += (newcap + 3*threshold) >> 2 + + // We need to check `newcap >= newLen` and whether `newcap` overflowed. + // newLen is guaranteed to be larger than zero, hence + // when newcap overflows then `uint(newcap) > uint(newLen)`. + // This allows to check for both with the same comparison. + if uint(newcap) >= uint(newLen) { + break + } + } + + // Set newcap to the requested cap when + // the newcap calculation overflowed. + if newcap <= 0 { + return newLen + } + return newcap +} diff --git a/internal/runtime/z_slice.go b/internal/runtime/z_slice.go index f20924fb..e6f9845c 100644 --- a/internal/runtime/z_slice.go +++ b/internal/runtime/z_slice.go @@ -70,4 +70,25 @@ func SliceData(s Slice) unsafe.Pointer { return s.data } +// SliceAppend append elem data and returns a slice. +func SliceAppend(src Slice, data unsafe.Pointer, num, etSize int) Slice { + if etSize == 0 { + return src + } + oldLen := src.len + newLen := src.len + num + if newLen > src.cap { + newCap := nextslicecap(newLen, src.cap) + p := AllocZ(uintptr(newCap * etSize)) + if oldLen != 0 { + c.Memcpy(p, src.data, uintptr(oldLen*etSize)) + } + src.data = p + src.cap = newCap + } + src.len = newLen + c.Memcpy(c.Advance(src.data, oldLen*etSize), data, uintptr(num*etSize)) + return src +} + // ----------------------------------------------------------------------------- diff --git a/ssa/expr.go b/ssa/expr.go index b532984a..420ceb97 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -632,6 +632,36 @@ func (b Builder) StringLen(x Expr) Expr { return Expr{ptr, prog.Int()} } +// SliceData returns the data pointer of a slice. +func (b Builder) SliceData(x Expr) Expr { + if debugInstr { + log.Printf("SliceData %v\n", x.impl) + } + prog := b.Prog + ptr := llvm.CreateExtractValue(b.impl, x.impl, 0) + return Expr{ptr, prog.CStr()} +} + +// SliceLen returns the length of a slice. +func (b Builder) SliceLen(x Expr) Expr { + if debugInstr { + log.Printf("SliceLen %v\n", x.impl) + } + prog := b.Prog + ptr := llvm.CreateExtractValue(b.impl, x.impl, 1) + return Expr{ptr, prog.Int()} +} + +// SliceCap returns the length of a slice cap. +func (b Builder) SliceCap(x Expr) Expr { + if debugInstr { + log.Printf("SliceCap %v\n", x.impl) + } + prog := b.Prog + ptr := llvm.CreateExtractValue(b.impl, x.impl, 2) + return Expr{ptr, prog.Int()} +} + // The IndexAddr instruction yields the address of the element at // index `idx` of collection `x`. `idx` is an integer expression. // @@ -653,8 +683,7 @@ func (b Builder) IndexAddr(x, idx Expr) Expr { pt := prog.Pointer(telem) switch x.raw.Type.Underlying().(type) { case *types.Slice: - pkg := b.Func.Pkg - ptr := b.InlineCall(pkg.rtFunc("SliceData"), x) + ptr := b.SliceData(x) indices := []llvm.Value{idx.impl} return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt} } @@ -757,12 +786,12 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) { return case *types.Slice: nEltSize = b.SizeOf(prog.Index(x.Type)) - nCap = b.InlineCall(pkg.rtFunc("SliceCap"), x) + nCap = b.SliceCap(x) if high.IsNil() { - high = b.InlineCall(pkg.rtFunc("SliceLen"), x) + high = b.SliceCap(x) } ret.Type = x.Type - base = b.InlineCall(pkg.rtFunc("SliceData"), x) + base = b.SliceData(x) case *types.Pointer: telem := t.Elem() switch te := telem.Underlying().(type) { @@ -1297,21 +1326,40 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { case "len": if len(args) == 1 { arg := args[0] - switch t := arg.raw.Type.Underlying().(type) { - case *types.Slice: - return b.InlineCall(b.Func.Pkg.rtFunc("SliceLen"), arg) - case *types.Basic: - if t.Kind() == types.String { - return b.StringLen(arg) - } + switch arg.kind { + case vkSlice: + return b.SliceLen(arg) + case vkString: + return b.StringLen(arg) } } case "cap": if len(args) == 1 { arg := args[0] - switch arg.raw.Type.Underlying().(type) { - case *types.Slice: - return b.InlineCall(b.Func.Pkg.rtFunc("SliceCap"), arg) + switch arg.kind { + case vkSlice: + return b.SliceCap(arg) + } + } + case "append": + if len(args) == 2 { + src := args[0] + if src.kind == vkSlice { + elem := args[1] + switch elem.kind { + case vkSlice: + etSize := b.Prog.SizeOf(b.Prog.Elem(elem.Type)) + ret.Type = src.Type + ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("SliceAppend"), + src, b.SliceData(elem), b.SliceLen(elem), b.Prog.Val(int(etSize))).impl + return + case vkString: + etSize := b.Prog.SizeOf(b.Prog.Type(types.Typ[types.Byte], InGo)) + ret.Type = src.Type + ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("SliceAppend"), + src, b.StringData(elem), b.StringLen(elem), b.Prog.Val(int(etSize))).impl + return + } } } } diff --git a/ssa/type.go b/ssa/type.go index 735a3d90..c10e7da6 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -45,6 +45,7 @@ const ( vkClosure vkPyFuncRef vkTuple + vkSlice vkPhisExpr = -1 ) @@ -103,7 +104,10 @@ func (p Program) Pointer(typ Type) Type { } func (p Program) Elem(typ Type) Type { - elem := typ.raw.Type.(*types.Pointer).Elem() + elem := typ.raw.Type.(interface { + types.Type + Elem() types.Type + }).Elem() return p.rawType(elem) } @@ -237,7 +241,7 @@ func (p Program) toType(raw types.Type) Type { case *types.Interface: return &aType{p.rtIface(), typ, vkInvalid} case *types.Slice: - return &aType{p.rtSlice(), typ, vkInvalid} + return &aType{p.rtSlice(), typ, vkSlice} case *types.Map: return &aType{p.rtMap(), typ, vkInvalid} case *types.Struct: