Merge pull request #454 from visualfc/typec

cl: parser llgo:type C
This commit is contained in:
xushiwei
2024-07-09 12:18:44 +08:00
committed by GitHub
6 changed files with 821 additions and 6 deletions

150
cl/_testrt/qsortfn/in.go Normal file
View File

@@ -0,0 +1,150 @@
package main
import (
"unsafe"
"github.com/goplus/llgo/c"
q "github.com/goplus/llgo/cl/internal/qsort"
)
// llgo:type C
type Comp func(a, b c.Pointer) c.Int
//go:linkname qsort C.qsort
func qsort(base c.Pointer, count, elem uintptr, compar Comp)
//go:linkname qsort2 C.qsort
func qsort2(base c.Pointer, count, elem uintptr, compar func(a, b c.Pointer) c.Int)
func main() {
sort1a()
sort1b()
sort2a()
sort2b()
sort3a()
sort3b()
sort4a()
sort4b()
sort5a()
sort5b()
}
func sort1a() {
c.Printf(c.Str("Comp => Comp\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn Comp = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
qsort(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), fn)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort1b() {
c.Printf(c.Str("fn => Comp\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
qsort(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), fn)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort2a() {
c.Printf(c.Str("Comp => fn\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn Comp = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
qsort2(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), fn)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort2b() {
c.Printf(c.Str("fn => fn\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
qsort2(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), fn)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort3a() {
c.Printf(c.Str("qsort.Comp => qsort.Comp\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn q.Comp = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
q.Qsort(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), fn)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort3b() {
c.Printf(c.Str("fn => qsort.Comp\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
q.Qsort(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), fn)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort4a() {
c.Printf(c.Str("qsort.Comp => fn\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn q.Comp = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
qsort2(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), fn)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort4b() {
c.Printf(c.Str("Comp => qsort.fn\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn Comp = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
q.Qsort2(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), fn)
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort5a() {
c.Printf(c.Str("qsort.Comp => Comp()\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn q.Comp = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
qsort(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), Comp(fn))
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}
func sort5b() {
c.Printf(c.Str("Comp => qsort.Comp()\n"))
a := [...]int{100, 8, 23, 2, 7}
var fn Comp = func(a, b c.Pointer) c.Int {
return c.Int(*(*int)(a) - *(*int)(b))
}
q.Qsort(c.Pointer(&a[0]), 5, unsafe.Sizeof(0), q.Comp(fn))
for _, v := range a {
c.Printf(c.Str("%d\n"), v)
}
}

596
cl/_testrt/qsortfn/out.ll Normal file
View File

@@ -0,0 +1,596 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global i1 false, align 1
@__llgo_argc = global i32 0, align 4
@__llgo_argv = global ptr null, align 8
@0 = private unnamed_addr constant [14 x i8] c"Comp => Comp\0A\00", align 1
@1 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@2 = private unnamed_addr constant [12 x i8] c"fn => Comp\0A\00", align 1
@3 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@4 = private unnamed_addr constant [12 x i8] c"Comp => fn\0A\00", align 1
@5 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@6 = private unnamed_addr constant [10 x i8] c"fn => fn\0A\00", align 1
@7 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@8 = private unnamed_addr constant [26 x i8] c"qsort.Comp => qsort.Comp\0A\00", align 1
@9 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@10 = private unnamed_addr constant [18 x i8] c"fn => qsort.Comp\0A\00", align 1
@11 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@12 = private unnamed_addr constant [18 x i8] c"qsort.Comp => fn\0A\00", align 1
@13 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@14 = private unnamed_addr constant [18 x i8] c"Comp => qsort.fn\0A\00", align 1
@15 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@16 = private unnamed_addr constant [22 x i8] c"qsort.Comp => Comp()\0A\00", align 1
@17 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@18 = private unnamed_addr constant [22 x i8] c"Comp => qsort.Comp()\0A\00", align 1
@19 = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
define i32 @main(i32 %0, ptr %1) {
_llgo_0:
store i32 %0, ptr @__llgo_argc, align 4
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
call void @main.sort1a()
call void @main.sort1b()
call void @main.sort2a()
call void @main.sort2b()
call void @main.sort3a()
call void @main.sort3b()
call void @main.sort4a()
call void @main.sort4b()
call void @main.sort5a()
call void @main.sort5b()
ret i32 0
}
define void @main.sort1a() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @0)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort1a$1")
%8 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%10 = add i64 %9, 1
%11 = icmp slt i64 %10, 5
br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%12 = icmp slt i64 %10, 0
%13 = icmp sge i64 %10, 5
%14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%15 = getelementptr inbounds i64, ptr %1, i64 %10
%16 = load i64, ptr %15, align 4
%17 = call i32 (ptr, ...) @printf(ptr @1, i64 %16)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort1a$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort1b() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @2)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort1b$1")
%8 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%10 = add i64 %9, 1
%11 = icmp slt i64 %10, 5
br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%12 = icmp slt i64 %10, 0
%13 = icmp sge i64 %10, 5
%14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%15 = getelementptr inbounds i64, ptr %1, i64 %10
%16 = load i64, ptr %15, align 4
%17 = call i32 (ptr, ...) @printf(ptr @3, i64 %16)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort1b$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort2a() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @4)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort2a$1")
%8 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%10 = add i64 %9, 1
%11 = icmp slt i64 %10, 5
br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%12 = icmp slt i64 %10, 0
%13 = icmp sge i64 %10, 5
%14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%15 = getelementptr inbounds i64, ptr %1, i64 %10
%16 = load i64, ptr %15, align 4
%17 = call i32 (ptr, ...) @printf(ptr @5, i64 %16)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort2a$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort2b() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @6)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort2b$1")
%8 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%10 = add i64 %9, 1
%11 = icmp slt i64 %10, 5
br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%12 = icmp slt i64 %10, 0
%13 = icmp sge i64 %10, 5
%14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%15 = getelementptr inbounds i64, ptr %1, i64 %10
%16 = load i64, ptr %15, align 4
%17 = call i32 (ptr, ...) @printf(ptr @7, i64 %16)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort2b$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort3a() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @8)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = alloca { ptr, ptr }, align 8
%8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0
store ptr @"__llgo_stub.main.sort3a$1", ptr %8, align 8
%9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1
store ptr null, ptr %9, align 8
%10 = load { ptr, ptr }, ptr %7, align 8
%11 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %11, i64 5, i64 8, { ptr, ptr } %10)
%12 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%13 = phi i64 [ -1, %_llgo_0 ], [ %14, %_llgo_2 ]
%14 = add i64 %13, 1
%15 = icmp slt i64 %14, 5
br i1 %15, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%16 = icmp slt i64 %14, 0
%17 = icmp sge i64 %14, 5
%18 = or i1 %17, %16
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %18)
%19 = getelementptr inbounds i64, ptr %1, i64 %14
%20 = load i64, ptr %19, align 4
%21 = call i32 (ptr, ...) @printf(ptr @9, i64 %20)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort3a$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort3b() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @10)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = getelementptr inbounds i64, ptr %1, i64 0
%8 = alloca { ptr, ptr }, align 8
%9 = getelementptr inbounds { ptr, ptr }, ptr %8, i32 0, i32 0
store ptr @"__llgo_stub.main.sort3b$1", ptr %9, align 8
%10 = getelementptr inbounds { ptr, ptr }, ptr %8, i32 0, i32 1
store ptr null, ptr %10, align 8
%11 = load { ptr, ptr }, ptr %8, align 8
call void @qsort(ptr %7, i64 5, i64 8, { ptr, ptr } %11)
%12 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%13 = phi i64 [ -1, %_llgo_0 ], [ %14, %_llgo_2 ]
%14 = add i64 %13, 1
%15 = icmp slt i64 %14, 5
br i1 %15, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%16 = icmp slt i64 %14, 0
%17 = icmp sge i64 %14, 5
%18 = or i1 %17, %16
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %18)
%19 = getelementptr inbounds i64, ptr %1, i64 %14
%20 = load i64, ptr %19, align 4
%21 = call i32 (ptr, ...) @printf(ptr @11, i64 %20)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort3b$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort4a() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @12)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = alloca { ptr, ptr }, align 8
%8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0
store ptr @"__llgo_stub.main.sort4a$1", ptr %8, align 8
%9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1
store ptr null, ptr %9, align 8
%10 = load { ptr, ptr }, ptr %7, align 8
%11 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %11, i64 5, i64 8, { ptr, ptr } %10)
%12 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%13 = phi i64 [ -1, %_llgo_0 ], [ %14, %_llgo_2 ]
%14 = add i64 %13, 1
%15 = icmp slt i64 %14, 5
br i1 %15, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%16 = icmp slt i64 %14, 0
%17 = icmp sge i64 %14, 5
%18 = or i1 %17, %16
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %18)
%19 = getelementptr inbounds i64, ptr %1, i64 %14
%20 = load i64, ptr %19, align 4
%21 = call i32 (ptr, ...) @printf(ptr @13, i64 %20)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort4a$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort4b() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @14)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort4b$1")
%8 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%10 = add i64 %9, 1
%11 = icmp slt i64 %10, 5
br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%12 = icmp slt i64 %10, 0
%13 = icmp sge i64 %10, 5
%14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%15 = getelementptr inbounds i64, ptr %1, i64 %10
%16 = load i64, ptr %15, align 4
%17 = call i32 (ptr, ...) @printf(ptr @15, i64 %16)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort4b$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort5a() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @16)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = alloca { ptr, ptr }, align 8
%8 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 0
store ptr @"__llgo_stub.main.sort5a$1", ptr %8, align 8
%9 = getelementptr inbounds { ptr, ptr }, ptr %7, i32 0, i32 1
store ptr null, ptr %9, align 8
%10 = load { ptr, ptr }, ptr %7, align 8
%11 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %11, i64 5, i64 8, { ptr, ptr } %10)
%12 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%13 = phi i64 [ -1, %_llgo_0 ], [ %14, %_llgo_2 ]
%14 = add i64 %13, 1
%15 = icmp slt i64 %14, 5
br i1 %15, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%16 = icmp slt i64 %14, 0
%17 = icmp sge i64 %14, 5
%18 = or i1 %17, %16
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %18)
%19 = getelementptr inbounds i64, ptr %1, i64 %14
%20 = load i64, ptr %19, align 4
%21 = call i32 (ptr, ...) @printf(ptr @17, i64 %20)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort5a$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
define void @main.sort5b() {
_llgo_0:
%0 = call i32 (ptr, ...) @printf(ptr @18)
%1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40)
%2 = getelementptr inbounds i64, ptr %1, i64 0
%3 = getelementptr inbounds i64, ptr %1, i64 1
%4 = getelementptr inbounds i64, ptr %1, i64 2
%5 = getelementptr inbounds i64, ptr %1, i64 3
%6 = getelementptr inbounds i64, ptr %1, i64 4
store i64 100, ptr %2, align 4
store i64 8, ptr %3, align 4
store i64 23, ptr %4, align 4
store i64 2, ptr %5, align 4
store i64 7, ptr %6, align 4
%7 = getelementptr inbounds i64, ptr %1, i64 0
call void @qsort(ptr %7, i64 5, i64 8, ptr @"main.sort5b$1")
%8 = load [5 x i64], ptr %1, align 4
br label %_llgo_1
_llgo_1: ; preds = %_llgo_2, %_llgo_0
%9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ]
%10 = add i64 %9, 1
%11 = icmp slt i64 %10, 5
br i1 %11, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1
%12 = icmp slt i64 %10, 0
%13 = icmp sge i64 %10, 5
%14 = or i1 %13, %12
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14)
%15 = getelementptr inbounds i64, ptr %1, i64 %10
%16 = load i64, ptr %15, align 4
%17 = call i32 (ptr, ...) @printf(ptr @19, i64 %16)
br label %_llgo_1
_llgo_3: ; preds = %_llgo_1
ret void
}
define i32 @"main.sort5b$1"(ptr %0, ptr %1) {
_llgo_0:
%2 = load i64, ptr %0, align 4
%3 = load i64, ptr %1, align 4
%4 = sub i64 %2, %3
%5 = trunc i64 %4 to i32
ret i32 %5
}
declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i32 @printf(ptr, ...)
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64)
declare void @qsort(ptr, i64, i64, ptr)
declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1)
define linkonce i32 @"__llgo_stub.main.sort3a$1"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = tail call i32 @"main.sort3a$1"(ptr %1, ptr %2)
ret i32 %3
}
define linkonce i32 @"__llgo_stub.main.sort3b$1"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = tail call i32 @"main.sort3b$1"(ptr %1, ptr %2)
ret i32 %3
}
define linkonce i32 @"__llgo_stub.main.sort4a$1"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = tail call i32 @"main.sort4a$1"(ptr %1, ptr %2)
ret i32 %3
}
define linkonce i32 @"__llgo_stub.main.sort5a$1"(ptr %0, ptr %1, ptr %2) {
_llgo_0:
%3 = tail call i32 @"main.sort5a$1"(ptr %1, ptr %2)
ret i32 %3
}

View File

@@ -196,6 +196,15 @@ func (p *context) initFiles(pkgPath string, files []*ast.File) {
p.collectSkipNames(line) p.collectSkipNames(line)
} }
} }
case token.TYPE:
if len(decl.Specs) == 1 {
if hasTypec(decl.Doc) {
inPkgName := decl.Specs[0].(*ast.TypeSpec).Name.Name
if obj := p.goTyps.Scope().Lookup(inPkgName); obj != nil {
p.prog.Type(obj.Type(), llssa.InC)
}
}
}
} }
} }
} }
@@ -544,4 +553,43 @@ func (p *context) initPyModule() {
} }
} }
// ParsePkgSyntax: check llgo:type C
func ParsePkgSyntax(prog llssa.Program, pkg *types.Package, files []*ast.File) {
for _, file := range files {
for _, decl := range file.Decls {
switch decl := decl.(type) {
case *ast.GenDecl:
switch decl.Tok {
case token.TYPE:
if len(decl.Specs) == 1 {
if hasTypec(decl.Doc) {
inPkgName := decl.Specs[0].(*ast.TypeSpec).Name.Name
if obj := pkg.Scope().Lookup(inPkgName); obj != nil {
prog.Type(obj.Type(), llssa.InC)
}
}
}
}
}
}
}
}
const (
llgotypec = "//llgo:type C"
llgotypec2 = "// llgo:type C"
)
func hasTypec(doc *ast.CommentGroup) bool {
if doc != nil {
if n := len(doc.List); n > 0 {
line := doc.List[n-1].Text
if strings.HasPrefix(line, llgotypec) || strings.HasPrefix(line, llgotypec2) {
return true
}
}
}
return false
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@@ -0,0 +1,20 @@
package qsort
import (
_ "unsafe"
"github.com/goplus/llgo/c"
)
const (
LLGoPackage = "decl"
)
// llgo:type C
type Comp func(a, b c.Pointer) c.Int
//go:linkname Qsort C.qsort
func Qsort(base c.Pointer, count, elem uintptr, compar Comp)
//go:linkname Qsort2 C.qsort
func Qsort2(base c.Pointer, count, elem uintptr, compar func(a, b c.Pointer) c.Int)

View File

@@ -247,10 +247,12 @@ func buildAllPkgs(ctx *context, initial []*packages.Package, verbose bool) (pkgs
continue continue
} }
built[pkg.PkgPath] = none{} built[pkg.PkgPath] = none{}
//parsePkg(ctx, aPkg, verbose)
switch kind, param := cl.PkgKindOf(pkg.Types); kind { switch kind, param := cl.PkgKindOf(pkg.Types); kind {
case cl.PkgDeclOnly: case cl.PkgDeclOnly:
// skip packages that only contain declarations // skip packages that only contain declarations
// and set no export file // and set no export file
cl.ParsePkgSyntax(ctx.prog, pkg.Types, pkg.Syntax)
pkg.ExportFile = "" pkg.ExportFile = ""
case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule: case cl.PkgLinkIR, cl.PkgLinkExtern, cl.PkgPyModule:
if isPkgInLLGo(pkg.PkgPath) { if isPkgInLLGo(pkg.PkgPath) {
@@ -427,6 +429,7 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) {
llssa.SetDebug(llssa.DbgFlagAll) llssa.SetDebug(llssa.DbgFlagAll)
cl.SetDebug(cl.DbgFlagAll) cl.SetDebug(cl.DbgFlagAll)
} }
ret, err := cl.NewPackageEx(ctx.prog, ctx.patches, aPkg.SSA, syntax) ret, err := cl.NewPackageEx(ctx.prog, ctx.patches, aPkg.SSA, syntax)
if showDetail { if showDetail {
llssa.SetDebug(0) llssa.SetDebug(0)

View File

@@ -704,11 +704,9 @@ func (b Builder) ChangeType(t Type, x Expr) (ret Expr) {
if debugInstr { if debugInstr {
log.Printf("ChangeType %v, %v\n", t.RawType(), x.impl) log.Printf("ChangeType %v, %v\n", t.RawType(), x.impl)
} }
typ := t.raw.Type if t.kind == vkClosure && x.kind == vkFuncDecl {
switch t.kind { ret.impl = checkExpr(x, t.raw.Type.Underlying(), b).impl
case vkClosure: } else {
ret.impl = checkExpr(x, typ.Underlying(), b).impl
default:
ret.impl = x.impl ret.impl = x.impl
} }
ret.Type = t ret.Type = t
@@ -946,7 +944,7 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
raw = fn.raw.Type raw = fn.raw.Type
fallthrough fallthrough
case vkFuncPtr: case vkFuncPtr:
sig = raw.(*types.Signature) sig = raw.Underlying().(*types.Signature)
ll = b.Prog.FuncDecl(sig, InC).ll ll = b.Prog.FuncDecl(sig, InC).ll
case vkFuncDecl: case vkFuncDecl:
sig = raw.(*types.Signature) sig = raw.(*types.Signature)