From d444123062d9ff9c8c7ce4527a463d2627b9d250 Mon Sep 17 00:00:00 2001 From: visualfc Date: Fri, 3 May 2024 10:30:07 +0800 Subject: [PATCH] update ssa.Slice --- cl/_testrt/builtin/in.go | 20 +++++- cl/_testrt/builtin/out.ll | 96 +++++++++++++++++++++++---- cl/_testrt/concat/out.ll | 4 +- cl/_testrt/sum/out.ll | 4 +- internal/runtime/llgo_autogen.ll | 110 ++++++++++++++++++++++++++++++- internal/runtime/z_slice.go | 16 +++++ internal/runtime/z_string.go | 10 +++ ssa/expr.go | 42 ++++++++++-- 8 files changed, 276 insertions(+), 26 deletions(-) diff --git a/cl/_testrt/builtin/in.go b/cl/_testrt/builtin/in.go index 155a1331..a252a6d5 100644 --- a/cl/_testrt/builtin/in.go +++ b/cl/_testrt/builtin/in.go @@ -17,11 +17,29 @@ func main() { out(len(a)) out(len(&a)) out(len([4]int{1, 2, 3, 4})) - string_len("hello") out(cap(s)) out(cap(a)) out(cap(&a)) + + out(len(s[1:])) + out(cap(s[1:])) + out(len(s[1:2])) + out(cap(s[1:2])) + out(len(s[1:2:2])) + out(cap(s[1:2:2])) + + out(len(a[1:])) + out(cap(a[1:])) + out(len(a[1:2])) + out(cap(a[1:2])) + out(len(a[1:2:2])) + out(cap(a[1:2:2])) + + string_len("hello") + string_len("hello"[1:]) + string_len("hello"[1:2]) + string_len("hello"[5:]) } func string_len(s string) { diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll index 616dcd8c..a48e9c94 100644 --- a/cl/_testrt/builtin/out.ll +++ b/cl/_testrt/builtin/out.ll @@ -9,7 +9,10 @@ source_filename = "main" @"main.init$guard" = global ptr null @main.n = global ptr null @0 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 -@1 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 +@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 define void @main.init() { _llgo_0: @@ -40,8 +43,8 @@ _llgo_0: store i64 3, ptr %3, align 4 %4 = getelementptr inbounds i64, ptr %0, i64 3 store i64 4, ptr %4, align 4 - %5 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %0, i64 4, i64 4) - %6 = alloca [4 x i64], align 8 + %5 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 8, i64 4, i64 0, i64 4, i64 4) + %6 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 32) %7 = getelementptr inbounds i64, ptr %6, i64 0 %8 = getelementptr inbounds i64, ptr %6, i64 1 %9 = getelementptr inbounds i64, ptr %6, i64 2 @@ -61,24 +64,85 @@ _llgo_0: store i64 3, ptr %15, align 4 %16 = getelementptr inbounds i64, ptr %12, i64 3 store i64 4, ptr %16, align 4 - %17 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %12, i64 4, i64 4) + %17 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %12, i64 8, i64 4, i64 0, i64 4, i64 4) %18 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %17) call void @main.out(i64 %18) call void @main.out(i64 4) call void @main.out(i64 4) call void @main.out(i64 4) - %19 = 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" %19) + %19 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + call void @main.out(i64 %19) + call void @main.out(i64 4) + call void @main.out(i64 4) %20 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) - call void @main.out(i64 %20) - call void @main.out(i64 4) - call void @main.out(i64 4) + %21 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %22 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %23 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %22, i64 8, i64 %20, i64 1, i64 %21, i64 %20) + %24 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %23) + call void @main.out(i64 %24) + %25 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %26 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %27 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %28 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %27, i64 8, i64 %25, i64 1, i64 %26, i64 %25) + %29 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %28) + call void @main.out(i64 %29) + %30 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %31 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %32 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %31, i64 8, i64 %30, i64 1, i64 2, i64 %30) + %33 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %32) + call void @main.out(i64 %33) + %34 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %35 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %36 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %35, i64 8, i64 %34, i64 1, i64 2, i64 %34) + %37 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %36) + call void @main.out(i64 %37) + %38 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %39 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %40 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %39, i64 8, i64 %38, i64 1, i64 2, i64 2) + %41 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %40) + call void @main.out(i64 %41) + %42 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %43 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + %44 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %43, i64 8, i64 %42, i64 1, i64 2, i64 2) + %45 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %44) + call void @main.out(i64 %45) + %46 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 4, i64 4) + %47 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %46) + call void @main.out(i64 %47) + %48 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 4, i64 4) + %49 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %48) + call void @main.out(i64 %49) + %50 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 4) + %51 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %50) + call void @main.out(i64 %51) + %52 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 4) + %53 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %52) + call void @main.out(i64 %53) + %54 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 2) + %55 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %54) + call void @main.out(i64 %55) + %56 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %6, i64 8, i64 4, i64 1, i64 2, i64 2) + %57 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %56) + call void @main.out(i64 %57) + %58 = 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" %58) + %59 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 5) + %60 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %59) + %61 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %59, i64 1, i64 %60) + call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %61) + %62 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 5) + %63 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %62, i64 1, i64 2) + call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %63) + %64 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5) + %65 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %64) + %66 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %64, i64 5, i64 %65) + call void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %66) ret void } define void @main.out(i64 %0) { _llgo_0: - %1 = call i32 (ptr, ...) @printf(ptr @1, i64 %0) + %1 = call i32 (ptr, ...) @printf(ptr @4, i64 %0) ret void } @@ -93,14 +157,18 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"() declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64) -declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, 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 %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64) - declare i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice") -declare i32 @printf(ptr, ...) +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 i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String") + +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 i32 @printf(ptr, ...) diff --git a/cl/_testrt/concat/out.ll b/cl/_testrt/concat/out.ll index 0df4d5a3..1fdae7e9 100644 --- a/cl/_testrt/concat/out.ll +++ b/cl/_testrt/concat/out.ll @@ -74,7 +74,7 @@ _llgo_0: %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i64 2 %6 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 5) store %"github.com/goplus/llgo/internal/runtime.String" %6, ptr %5, align 8 - %7 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %0, i64 3, i64 3) + %7 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 16, i64 3, i64 0, i64 3, i64 3) %8 = call %"github.com/goplus/llgo/internal/runtime.String" @main.concat(%"github.com/goplus/llgo/internal/runtime.Slice" %7) %9 = load ptr, ptr @__stderrp, align 8 %10 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %8) @@ -97,7 +97,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"() declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64) -declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, 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.StringLen"(%"github.com/goplus/llgo/internal/runtime.String") diff --git a/cl/_testrt/sum/out.ll b/cl/_testrt/sum/out.ll index f5ae39db..a41f91c5 100644 --- a/cl/_testrt/sum/out.ll +++ b/cl/_testrt/sum/out.ll @@ -32,7 +32,7 @@ _llgo_0: store i64 3, ptr %3, align 4 %4 = getelementptr inbounds i64, ptr %0, i64 3 store i64 4, ptr %4, align 4 - %5 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %0, i64 4, i64 4) + %5 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 8, i64 4, i64 0, i64 4, i64 4) %6 = call i64 @main.sum(%"github.com/goplus/llgo/internal/runtime.Slice" %5) %7 = call i32 (ptr, ...) @printf(ptr @0, i64 %6) ret void @@ -65,7 +65,7 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"() declare ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64) -declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, 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, ...) diff --git a/internal/runtime/llgo_autogen.ll b/internal/runtime/llgo_autogen.ll index bf1294e7..66732ef6 100644 --- a/internal/runtime/llgo_autogen.ll +++ b/internal/runtime/llgo_autogen.ll @@ -13,8 +13,10 @@ source_filename = "github.com/goplus/llgo/internal/runtime" @"github.com/goplus/llgo/internal/runtime.init$guard" = global ptr null @"github.com/goplus/llgo/internal/runtime.sizeBasicTypes" = global ptr null @0 = private unnamed_addr constant [21 x i8] c"I2Int: type mismatch\00", align 1 +@1 = private unnamed_addr constant [26 x i8] c"slice index out of bounds\00", align 1 +@2 = private unnamed_addr constant [33 x i8] c"string slice index out of bounds\00", align 1 @__stderrp = external global ptr -@1 = private unnamed_addr constant [11 x i8] c"panic: %s\0A\00", align 1 +@3 = private unnamed_addr constant [11 x i8] c"panic: %s\0A\00", align 1 define ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 %0) { _llgo_0: @@ -224,6 +226,58 @@ _llgo_0: ret %"github.com/goplus/llgo/internal/runtime.Slice" %7 } +define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5) { +_llgo_0: + %6 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %7 = icmp slt i64 %3, 0 + br i1 %7, label %_llgo_1, label %_llgo_5 + +_llgo_1: ; preds = %_llgo_5, %_llgo_4, %_llgo_3, %_llgo_0 + %8 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 25) + %9 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %8) + call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %9) + unreachable + +_llgo_2: ; preds = %_llgo_3 + %10 = sub i64 %4, %3 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %6, i32 0, i32 1 + store i64 %10, ptr %11, align 4 + %12 = sub i64 %5, %3 + %13 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %6, i32 0, i32 2 + store i64 %12, ptr %13, align 4 + %14 = sub i64 %5, %3 + %15 = icmp sgt i64 %14, 0 + br i1 %15, label %_llgo_6, label %_llgo_8 + +_llgo_3: ; preds = %_llgo_4 + %16 = icmp sgt i64 %5, %2 + br i1 %16, label %_llgo_1, label %_llgo_2 + +_llgo_4: ; preds = %_llgo_5 + %17 = icmp slt i64 %5, %4 + br i1 %17, label %_llgo_1, label %_llgo_3 + +_llgo_5: ; preds = %_llgo_0 + %18 = icmp slt i64 %4, %3 + br i1 %18, label %_llgo_1, label %_llgo_4 + +_llgo_6: ; preds = %_llgo_2 + %19 = mul i64 %3, %1 + %20 = getelementptr i8, ptr %0, i64 %19 + %21 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %6, i32 0, i32 0 + store ptr %20, ptr %21, align 8 + br label %_llgo_7 + +_llgo_7: ; preds = %_llgo_8, %_llgo_6 + %22 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %6, align 8 + ret %"github.com/goplus/llgo/internal/runtime.Slice" %22 + +_llgo_8: ; preds = %_llgo_2 + %23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %6, i32 0, i32 0 + store ptr %0, ptr %23, align 8 + br label %_llgo_7 +} + define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr %0, i64 %1) { _llgo_0: %2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 @@ -235,6 +289,58 @@ _llgo_0: ret %"github.com/goplus/llgo/internal/runtime.String" %5 } +define %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %0, i64 %1, i64 %2) { +_llgo_0: + %3 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %3, align 8 + %4 = icmp slt i64 %1, 0 + br i1 %4, label %_llgo_1, label %_llgo_4 + +_llgo_1: ; preds = %_llgo_4, %_llgo_3, %_llgo_0 + %5 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 32) + %6 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String" %5) + call void @"github.com/goplus/llgo/internal/runtime.TracePanic"(%"github.com/goplus/llgo/internal/runtime.iface" %6) + unreachable + +_llgo_2: ; preds = %_llgo_3 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1 + %8 = load i64, ptr %7, align 4 + %9 = icmp slt i64 %1, %8 + br i1 %9, label %_llgo_5, label %_llgo_6 + +_llgo_3: ; preds = %_llgo_4 + %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 1 + %11 = load i64, ptr %10, align 4 + %12 = icmp sgt i64 %2, %11 + br i1 %12, label %_llgo_1, label %_llgo_2 + +_llgo_4: ; preds = %_llgo_0 + %13 = icmp slt i64 %2, %1 + br i1 %13, label %_llgo_1, label %_llgo_3 + +_llgo_5: ; preds = %_llgo_2 + %14 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %14, i32 0, i32 0 + %16 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %3, i32 0, i32 0 + %17 = load ptr, ptr %16, align 8 + %18 = getelementptr i8, ptr %17, i64 %1 + %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %14, i32 0, i32 1 + %20 = sub i64 %2, %1 + store ptr %18, ptr %15, align 8 + store i64 %20, ptr %19, align 4 + %21 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %14, align 8 + ret %"github.com/goplus/llgo/internal/runtime.String" %21 + +_llgo_6: ; preds = %_llgo_2 + %22 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 0 + %24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 1 + store ptr null, ptr %23, align 8 + store i64 0, ptr %24, align 4 + %25 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %22, align 8 + ret %"github.com/goplus/llgo/internal/runtime.String" %25 +} + define %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NilSlice"() { _llgo_0: %0 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 @@ -349,7 +455,7 @@ _llgo_2: ; preds = %_llgo_0 %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %1, i32 0, i32 1 %12 = load ptr, ptr %11, align 8 %13 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %12, align 8 - call void @"github.com/goplus/llgo/internal/runtime.stringTracef"(ptr %10, ptr @1, %"github.com/goplus/llgo/internal/runtime.String" %13) + call void @"github.com/goplus/llgo/internal/runtime.stringTracef"(ptr %10, ptr @3, %"github.com/goplus/llgo/internal/runtime.String" %13) br label %_llgo_1 } diff --git a/internal/runtime/z_slice.go b/internal/runtime/z_slice.go index 36d309e1..15fb1a8d 100644 --- a/internal/runtime/z_slice.go +++ b/internal/runtime/z_slice.go @@ -18,6 +18,8 @@ package runtime import ( "unsafe" + + "github.com/goplus/llgo/internal/runtime/c" ) // ----------------------------------------------------------------------------- @@ -54,4 +56,18 @@ func SliceData(s Slice) unsafe.Pointer { return s.data } +func NewSlice3(base unsafe.Pointer, eltSize, cap, i, j, k int) (s Slice) { + if i < 0 || j < i || k < j || k > cap { + panic("slice index out of bounds") + } + s.len = j - i + s.cap = k - i + if k-i > 0 { + s.data = c.Advance(base, i*eltSize) + } else { + s.data = base + } + return +} + // ----------------------------------------------------------------------------- diff --git a/internal/runtime/z_string.go b/internal/runtime/z_string.go index 34f2e1f0..69079149 100644 --- a/internal/runtime/z_string.go +++ b/internal/runtime/z_string.go @@ -80,4 +80,14 @@ func CStrDup(s String) *int8 { return CStrCopy(dest, s) } +func NewStringSlice(base String, i, j int) String { + if i < 0 || j < i || j > base.len { + panic("string slice index out of bounds") + } + if i < base.len { + return String{c.Advance(base.data, i), j - i} + } + return String{nil, 0} +} + // ----------------------------------------------------------------------------- diff --git a/ssa/expr.go b/ssa/expr.go index 5200bff4..5687054d 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -593,20 +593,52 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) { } prog := b.Prog pkg := b.fn.pkg + var nCap Expr + var nEltSize Expr + var base Expr + if low.IsNil() { + low = prog.IntVal(0, prog.Int()) + } switch t := x.t.Underlying().(type) { + case *types.Basic: + if t.Info()&types.IsString == 0 { + panic(fmt.Errorf("invalid operation: cannot slice %v", t)) + } + if !max.IsNil() { + panic("invalid operation: 3-index slice of string") + } + if high.IsNil() { + high = b.InlineCall(pkg.rtFunc("StringLen"), x) + } + ret.Type = x.Type + ret.impl = b.InlineCall(pkg.rtFunc("NewStringSlice"), x, low, high).impl + return + case *types.Slice: + nCap = b.InlineCall(pkg.rtFunc("SliceCap"), x) + nEltSize = prog.IntVal(uint64(prog.sizs.Sizeof(t.Elem())), prog.Int()) + if high.IsNil() { + high = b.InlineCall(pkg.rtFunc("SliceLen"), x) + } + ret.Type = x.Type + base = b.InlineCall(pkg.rtFunc("SliceData"), x) case *types.Pointer: telem := t.Elem() switch te := telem.Underlying().(type) { case *types.Array: ret.Type = prog.Type(types.NewSlice(te.Elem())) - if low.IsNil() && high.IsNil() && max.IsNil() { - n := prog.Val(int(te.Len())) - ret.impl = b.InlineCall(pkg.rtFunc("NewSlice"), x, n, n).impl - return ret + nCap = prog.IntVal(uint64(te.Len()), prog.Int()) + nEltSize = prog.IntVal(uint64(prog.sizs.Sizeof(te.Elem())), prog.Int()) + if high.IsNil() { + high = nCap } + base = x } } - panic("todo") + if max.IsNil() { + max = nCap + } + ret.impl = b.InlineCall(pkg.rtFunc("NewSlice3"), base, nEltSize, nCap, low, high, max).impl + return } // -----------------------------------------------------------------------------