From 89af430329189ed379603e5747bd0a4d53dca708 Mon Sep 17 00:00:00 2001 From: visualfc Date: Tue, 9 Sep 2025 11:22:53 +0800 Subject: [PATCH] cl: embed struct support __llgo_va_list --- cl/_testrt/vamethod/in.go | 32 +++++++++++++++ cl/_testrt/vamethod/out.ll | 79 ++++++++++++++++++++++++++++++++++++++ cl/compile.go | 2 + 3 files changed, 113 insertions(+) create mode 100644 cl/_testrt/vamethod/in.go create mode 100644 cl/_testrt/vamethod/out.ll diff --git a/cl/_testrt/vamethod/in.go b/cl/_testrt/vamethod/in.go new file mode 100644 index 00000000..c2dbea83 --- /dev/null +++ b/cl/_testrt/vamethod/in.go @@ -0,0 +1,32 @@ +package main + +import ( + "unsafe" + _ "unsafe" + + "github.com/goplus/lib/c" +) + +type T c.Char + +//go:linkname Printf C.printf +func Printf(format *c.Char, __llgo_va_list ...any) c.Int + +//llgo:link (*T).Printf C.printf +func (*T) Printf(__llgo_va_list ...any) c.Int { return 0 } + +type CFmt struct { + *T +} + +func (f *CFmt) SetFormat(fmt string) { + f.T = (*T)(unsafe.Pointer(c.AllocaCStr(fmt))) +} + +func main() { + cfmt := &CFmt{} + cfmt.SetFormat("%s (%d)\n") + cfmt.Printf(c.Str("hello"), 100) + cfmt.SetFormat("(%d) %s\n") + cfmt.Printf(200, c.Str("world")) +} diff --git a/cl/_testrt/vamethod/out.ll b/cl/_testrt/vamethod/out.ll new file mode 100644 index 00000000..02eeeffa --- /dev/null +++ b/cl/_testrt/vamethod/out.ll @@ -0,0 +1,79 @@ +; ModuleID = 'github.com/goplus/llgo/cl/_testrt/vamethod' +source_filename = "github.com/goplus/llgo/cl/_testrt/vamethod" + +%"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" = type { ptr } +%"github.com/goplus/llgo/runtime/internal/runtime.String" = type { ptr, i64 } + +@"github.com/goplus/llgo/cl/_testrt/vamethod.init$guard" = global i1 false, align 1 +@0 = private unnamed_addr constant [8 x i8] c"%s (%d)\0A", align 1 +@1 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 +@2 = private unnamed_addr constant [8 x i8] c"(%d) %s\0A", align 1 +@3 = private unnamed_addr constant [6 x i8] c"world\00", align 1 + +define i32 @"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt.Printf"(%"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" %0, ...) { +_llgo_0: + %1 = alloca %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", align 8 + call void @llvm.memset(ptr %1, i8 0, i64 8, i1 false) + store %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt" %0, ptr %1, align 8 + %2 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %1, i32 0, i32 0 + %3 = load ptr, ptr %2, align 8 + %4 = call i32 (ptr, ...) @printf(ptr %3) + ret i32 %4 +} + +define i32 @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).Printf"(ptr %0, ...) { +_llgo_0: + %1 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + %2 = load ptr, ptr %1, align 8 + %3 = call i32 (ptr, ...) @printf(ptr %2) + ret i32 %3 +} + +define void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" %1) { +_llgo_0: + %2 = extractvalue %"github.com/goplus/llgo/runtime/internal/runtime.String" %1, 1 + %3 = add i64 %2, 1 + %4 = alloca i8, i64 %3, align 1 + %5 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.CStrCopy"(ptr %4, %"github.com/goplus/llgo/runtime/internal/runtime.String" %1) + %6 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + store ptr %5, ptr %6, align 8 + ret void +} + +define void @"github.com/goplus/llgo/cl/_testrt/vamethod.init"() { +_llgo_0: + %0 = load i1, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"github.com/goplus/llgo/cl/_testrt/vamethod.init$guard", align 1 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define void @"github.com/goplus/llgo/cl/_testrt/vamethod.main"() { +_llgo_0: + %0 = call ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64 8) + call void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @0, i64 8 }) + %1 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + %2 = load ptr, ptr %1, align 8 + %3 = call i32 (ptr, ...) @printf(ptr %2, ptr @1, i64 100) + call void @"github.com/goplus/llgo/cl/_testrt/vamethod.(*CFmt).SetFormat"(ptr %0, %"github.com/goplus/llgo/runtime/internal/runtime.String" { ptr @2, i64 8 }) + %4 = getelementptr inbounds %"github.com/goplus/llgo/cl/_testrt/vamethod.CFmt", ptr %0, i32 0, i32 0 + %5 = load ptr, ptr %4, align 8 + %6 = call i32 (ptr, ...) @printf(ptr %5, i64 200, ptr @3) + ret void +} + +; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write) +declare void @llvm.memset(ptr nocapture writeonly, i8, i64, i1 immarg) #0 + +declare i32 @printf(ptr, ...) + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.CStrCopy"(ptr, %"github.com/goplus/llgo/runtime/internal/runtime.String") + +declare ptr @"github.com/goplus/llgo/runtime/internal/runtime.AllocZ"(i64) + +attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) } diff --git a/cl/compile.go b/cl/compile.go index c8ff8d08..5bb20025 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -935,6 +935,8 @@ func (p *context) compileVArg(ret []llssa.Expr, b llssa.Builder, v ssa.Value) [] if v.Value == nil { return ret } + case *ssa.Parameter: + return ret } panic(fmt.Sprintf("compileVArg: unknown value - %T\n", v)) }