ssa: builtin len&cap
This commit is contained in:
@@ -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")
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
14
ssa/expr.go
14
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user