diff --git a/cl/_testrt/allocstr/out.ll b/cl/_testrt/allocstr/out.ll index 8713016e..75049f25 100644 --- a/cl/_testrt/allocstr/out.ll +++ b/cl/_testrt/allocstr/out.ll @@ -2,7 +2,6 @@ source_filename = "main" %"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } -%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } @"main.init$guard" = global ptr null @0 = private unnamed_addr constant [13 x i8] c"Hello world\0A\00", align 1 @@ -43,7 +42,7 @@ declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/ll declare void @"github.com/goplus/llgo/internal/runtime.init"() -declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.Slice") +declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String") declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String") diff --git a/cl/_testrt/builtin/in.go b/cl/_testrt/builtin/in.go index 3a3acbd5..155a1331 100644 --- a/cl/_testrt/builtin/in.go +++ b/cl/_testrt/builtin/in.go @@ -1,11 +1,33 @@ package main +import ( + "github.com/goplus/llgo/internal/runtime/c" +) + var a int64 = 1<<63 - 1 var b int64 = -1 << 63 -var c uint64 = 1<<64 - 1 +var n uint64 = 1<<64 - 1 func main() { - var a = []int{1, 2, 3, 4} - _ = len(a) - _ = len([]int{1, 2, 3, 4}) + var s = []int{1, 2, 3, 4} + var a = [...]int{1, 2, 3, 4} + + out(len(s)) + out(len([]int{1, 2, 3, 4})) + 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)) +} + +func string_len(s string) { + out(len(s)) +} + +func out(n int) { + c.Printf(c.Str("%d\n"), n) } diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll index c1fb435e..616dcd8c 100644 --- a/cl/_testrt/builtin/out.ll +++ b/cl/_testrt/builtin/out.ll @@ -2,11 +2,14 @@ source_filename = "main" %"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } @main.a = global ptr null @main.b = global ptr null -@main.c = global ptr null @"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 define void @main.init() { _llgo_0: @@ -17,7 +20,7 @@ _llgo_1: ; preds = %_llgo_0 store i1 true, ptr @"main.init$guard", align 1 store i64 9223372036854775807, ptr @main.a, align 4 store i64 -9223372036854775808, ptr @main.b, align 4 - store i64 -1, ptr @main.c, align 4 + store i64 -1, ptr @main.n, align 4 br label %_llgo_2 _llgo_2: ; preds = %_llgo_1, %_llgo_0 @@ -38,18 +41,51 @@ _llgo_0: %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 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) - %7 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 32) - %8 = getelementptr inbounds i64, ptr %7, i64 0 - store i64 1, ptr %8, align 4 - %9 = getelementptr inbounds i64, ptr %7, i64 1 - store i64 2, ptr %9, align 4 - %10 = getelementptr inbounds i64, ptr %7, i64 2 - store i64 3, ptr %10, align 4 - %11 = getelementptr inbounds i64, ptr %7, i64 3 - store i64 4, ptr %11, align 4 - %12 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr %7, i64 4, i64 4) - %13 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %12) + %6 = alloca [4 x i64], align 8 + %7 = getelementptr inbounds i64, ptr %6, i64 0 + %8 = getelementptr inbounds i64, ptr %6, i64 1 + %9 = getelementptr inbounds i64, ptr %6, i64 2 + %10 = getelementptr inbounds i64, ptr %6, i64 3 + store i64 1, ptr %7, align 4 + store i64 2, ptr %8, align 4 + store i64 3, ptr %9, align 4 + store i64 4, ptr %10, align 4 + %11 = call i64 @"github.com/goplus/llgo/internal/runtime.SliceLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %5) + call void @main.out(i64 %11) + %12 = call ptr @"github.com/goplus/llgo/internal/runtime.Alloc"(i64 32) + %13 = getelementptr inbounds i64, ptr %12, i64 0 + store i64 1, ptr %13, align 4 + %14 = getelementptr inbounds i64, ptr %12, i64 1 + store i64 2, ptr %14, align 4 + %15 = getelementptr inbounds i64, ptr %12, i64 2 + 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) + %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) + %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) + ret void +} + +define void @main.out(i64 %0) { +_llgo_0: + %1 = call i32 (ptr, ...) @printf(ptr @1, i64 %0) + ret void +} + +define void @main.string_len(%"github.com/goplus/llgo/internal/runtime.String" %0) { +_llgo_0: + %1 = call i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0) + call void @main.out(i64 %1) ret void } @@ -60,3 +96,11 @@ 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 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 i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String") diff --git a/cl/_testrt/concat/out.ll b/cl/_testrt/concat/out.ll index 91d51114..0df4d5a3 100644 --- a/cl/_testrt/concat/out.ll +++ b/cl/_testrt/concat/out.ll @@ -99,7 +99,7 @@ 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 i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.Slice") +declare i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String") declare ptr @"github.com/goplus/llgo/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/internal/runtime.String") diff --git a/internal/runtime/llgo_autogen.ll b/internal/runtime/llgo_autogen.ll index bc8de7f7..bf1294e7 100644 --- a/internal/runtime/llgo_autogen.ll +++ b/internal/runtime/llgo_autogen.ll @@ -248,6 +248,15 @@ _llgo_0: ret %"github.com/goplus/llgo/internal/runtime.Slice" %4 } +define i64 @"github.com/goplus/llgo/internal/runtime.SliceCap"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) { +_llgo_0: + %1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + store %"github.com/goplus/llgo/internal/runtime.Slice" %0, ptr %1, align 8 + %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 2 + %3 = load i64, ptr %2, align 4 + ret i64 %3 +} + define ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) { _llgo_0: %1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 @@ -309,11 +318,11 @@ _llgo_0: ret ptr %3 } -define i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.Slice" %0) { +define i64 @"github.com/goplus/llgo/internal/runtime.StringLen"(%"github.com/goplus/llgo/internal/runtime.String" %0) { _llgo_0: - %1 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 - store %"github.com/goplus/llgo/internal/runtime.Slice" %0, ptr %1, align 8 - %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %1, i32 0, i32 1 + %1 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %1, align 8 + %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %1, i32 0, i32 1 %3 = load i64, ptr %2, align 4 ret i64 %3 } diff --git a/internal/runtime/z_slice.go b/internal/runtime/z_slice.go index dc83b0c7..36d309e1 100644 --- a/internal/runtime/z_slice.go +++ b/internal/runtime/z_slice.go @@ -44,6 +44,11 @@ func SliceLen(s Slice) int { return s.len } +// SliceCap returns the capacity of a slice. +func SliceCap(s Slice) int { + return s.cap +} + // SliceData returns the data pointer of a slice. func SliceData(s Slice) unsafe.Pointer { return s.data diff --git a/internal/runtime/z_string.go b/internal/runtime/z_string.go index e7726c36..34f2e1f0 100644 --- a/internal/runtime/z_string.go +++ b/internal/runtime/z_string.go @@ -46,7 +46,7 @@ func NewString(data unsafe.Pointer, len int) String { } // StringLen returns the length of a string. -func StringLen(s Slice) int { +func StringLen(s String) int { return s.len } diff --git a/ssa/expr.go b/ssa/expr.go index e7486ba9..5200bff4 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -975,9 +975,21 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { case "len": if len(args) == 1 { arg := args[0] - switch arg.t.Underlying().(type) { + switch t := arg.t.Underlying().(type) { case *types.Slice: return b.InlineCall(b.fn.pkg.rtFunc("SliceLen"), arg) + case *types.Basic: + if t.Info()&types.IsString != 0 { + return b.InlineCall(b.fn.pkg.rtFunc("StringLen"), arg) + } + } + } + case "cap": + if len(args) == 1 { + arg := args[0] + switch arg.t.Underlying().(type) { + case *types.Slice: + return b.InlineCall(b.fn.pkg.rtFunc("SliceCap"), arg) } } }