From e61ebb4eb9926e3230782585f6b440abcfb031b4 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 20 May 2024 08:46:39 +0800 Subject: [PATCH 1/3] abi.Name; runtime: MakeAnyInt => MakeAnyIntptr; llgo/ssa: AllocU; builtin unsafe.String; MakeInterface; prog.PointerSize --- README.md | 2 +- go.mod | 2 +- internal/abi/llgo_autogen.lla | Bin 1680 -> 4424 bytes internal/abi/type.go | 195 +++++++++++++++++++++++++----- internal/runtime/llgo_autogen.lla | Bin 6918 -> 6919 bytes internal/runtime/z_iface.go | 2 +- internal/runtime/z_string.go | 1 + ssa/_abi/abi.go | 73 +++++++++++ ssa/cl_test.go | 3 + ssa/expr.go | 23 +++- ssa/interface.go | 91 ++++++++++---- ssa/package.go | 9 +- ssa/type.go | 4 + 13 files changed, 342 insertions(+), 63 deletions(-) create mode 100644 ssa/_abi/abi.go diff --git a/README.md b/README.md index cdb38794..97e95bb9 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ See [github.com/goplus/llgo/py](https://pkg.go.dev/github.com/goplus/llgo/py) fo LLGo can easily import any libraries from the C ecosystem. Currently, this import process is still manual, but in the future, it will be automated similar to Python library imports. -The currently imported libraries include: +The currently supported libraries include: * [llama2.c](https://pkg.go.dev/github.com/goplus/llgo/c/llama2) * [cjson](https://pkg.go.dev/github.com/goplus/llgo/c/cjson) diff --git a/go.mod b/go.mod index d1455dbd..5e702b52 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/goplus/llgo -go 1.18 +go 1.20 require ( github.com/aykevl/go-wasm v0.0.1 diff --git a/internal/abi/llgo_autogen.lla b/internal/abi/llgo_autogen.lla index cccf2f81e2804574b2566ee466b99e79cfe3bc60..4f8bcd999012ee293df371a59bbd1d0db0936bcf 100644 GIT binary patch delta 4401 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 I1^@s60Q=ts00000 diff --git a/internal/abi/type.go b/internal/abi/type.go index 549a135a..17b61967 100644 --- a/internal/abi/type.go +++ b/internal/abi/type.go @@ -213,36 +213,6 @@ type StructType struct { Fields []StructField } -// Name is an encoded type Name with optional extra data. -// -// The first byte is a bit field containing: -// -// 1<<0 the name is exported -// 1<<1 tag data follows the name -// 1<<2 pkgPath nameOff follows the name and tag -// 1<<3 the name is of an embedded (a.k.a. anonymous) field -// -// Following that, there is a varint-encoded length of the name, -// followed by the name itself. -// -// If tag data is present, it also has a varint-encoded length -// followed by the tag itself. -// -// If the import path follows, then 4 bytes at the end of -// the data form a nameOff. The import path is only set for concrete -// methods that are defined in a different package than their type. -// -// If a name starts with "*", then the exported bit represents -// whether the pointed to type is exported. -// -// Note: this encoding must match here and in: -// cmd/compile/internal/reflectdata/reflect.go -// cmd/link/internal/ld/decodesym.go - -type Name struct { - Bytes *byte -} - type InterfaceType struct { Type PkgPath Name // import path @@ -330,3 +300,168 @@ func (t *Type) InterfaceType() *InterfaceType { } // ----------------------------------------------------------------------------- + +// addChecked returns p+x. +// +// The whySafe string is ignored, so that the function still inlines +// as efficiently as p+x, but all call sites should use the string to +// record why the addition is safe, which is to say why the addition +// does not cause x to advance to the very end of p's allocation +// and therefore point incorrectly at the next block in memory. +func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer { + _ = whySafe + return unsafe.Pointer(uintptr(p) + x) +} + +// Name is an encoded type Name with optional extra data. +// +// The first byte is a bit field containing: +// +// 1<<0 the name is exported +// 1<<1 tag data follows the name +// 1<<2 pkgPath nameOff follows the name and tag +// 1<<3 the name is of an embedded (a.k.a. anonymous) field +// +// Following that, there is a varint-encoded length of the name, +// followed by the name itself. +// +// If tag data is present, it also has a varint-encoded length +// followed by the tag itself. +// +// If the import path follows, then 4 bytes at the end of +// the data form a nameOff. The import path is only set for concrete +// methods that are defined in a different package than their type. +// +// If a name starts with "*", then the exported bit represents +// whether the pointed to type is exported. +// +// Note: this encoding must match here and in: +// cmd/compile/internal/reflectdata/reflect.go +// cmd/link/internal/ld/decodesym.go + +type Name struct { + Bytes *byte +} + +// DataChecked does pointer arithmetic on n's Bytes, and that arithmetic is asserted to +// be safe for the reason in whySafe (which can appear in a backtrace, etc.) +func (n Name) DataChecked(off int, whySafe string) *byte { + return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe)) +} + +// Data does pointer arithmetic on n's Bytes, and that arithmetic is asserted to +// be safe because the runtime made the call (other packages use DataChecked) +func (n Name) Data(off int) *byte { + return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason")) +} + +// IsExported returns "is n exported?" +func (n Name) IsExported() bool { + return (*n.Bytes)&(1<<0) != 0 +} + +// HasTag returns true iff there is tag data following this name +func (n Name) HasTag() bool { + return (*n.Bytes)&(1<<1) != 0 +} + +// IsEmbedded returns true iff n is embedded (an anonymous field). +func (n Name) IsEmbedded() bool { + return (*n.Bytes)&(1<<3) != 0 +} + +// ReadVarint parses a varint as encoded by encoding/binary. +// It returns the number of encoded bytes and the encoded value. +func (n Name) ReadVarint(off int) (int, int) { + v := 0 + for i := 0; ; i++ { + x := *n.DataChecked(off+i, "read varint") + v += int(x&0x7f) << (7 * i) + if x&0x80 == 0 { + return i + 1, v + } + } +} + +// IsBlank indicates whether n is "_". +func (n Name) IsBlank() bool { + if n.Bytes == nil { + return false + } + _, l := n.ReadVarint(1) + return l == 1 && *n.Data(2) == '_' +} + +// writeVarint writes n to buf in varint form. Returns the +// number of bytes written. n must be nonnegative. +// Writes at most 10 bytes. +func writeVarint(buf []byte, n int) int { + for i := 0; ; i++ { + b := byte(n & 0x7f) + n >>= 7 + if n == 0 { + buf[i] = b + return i + 1 + } + buf[i] = b | 0x80 + } +} + +// Name returns the tag string for n, or empty if there is none. +func (n Name) Name() string { + if n.Bytes == nil { + return "" + } + i, l := n.ReadVarint(1) + return unsafe.String(n.DataChecked(1+i, "non-empty string"), l) +} + +// Tag returns the tag string for n, or empty if there is none. +func (n Name) Tag() string { + if !n.HasTag() { + return "" + } + i, l := n.ReadVarint(1) + i2, l2 := n.ReadVarint(1 + i + l) + return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2) +} + +func NewName(n, tag string, exported, embedded bool) Name { + if len(n) >= 1<<29 { + panic("abi.NewName: name too long: " + n[:1024] + "...") + } + if len(tag) >= 1<<29 { + panic("abi.NewName: tag too long: " + tag[:1024] + "...") + } + var nameLen [10]byte + var tagLen [10]byte + nameLenLen := writeVarint(nameLen[:], len(n)) + tagLenLen := writeVarint(tagLen[:], len(tag)) + + var bits byte + l := 1 + nameLenLen + len(n) + if exported { + bits |= 1 << 0 + } + if len(tag) > 0 { + l += tagLenLen + len(tag) + bits |= 1 << 1 + } + if embedded { + bits |= 1 << 3 + } + + b := make([]byte, l) + b[0] = bits + copy(b[1:], nameLen[:nameLenLen]) + copy(b[1+nameLenLen:], n) + if len(tag) > 0 { + tb := b[1+nameLenLen+len(n):] + copy(tb, tagLen[:tagLenLen]) + copy(tb[tagLenLen:], tag) + } + + return Name{Bytes: &b[0]} +} + +// ----------------------------------------------------------------------------- diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index 6257d02dcf6df798f320d4ec2621762c94edb2e5..94569d3013459d3fc524e9367f2ac91e08697462 100644 GIT binary patch delta 1099 zcmV-R1ho5xHitGjP)h>@6aWAK2mo$Hv{*wA1#MFr002l10RRsG8~|)=XK!C&b#!lM zWo|BPY*kbV00Xd`N@lX0O0hZc27l()_(D{#-Gx10*z<)wU)Xa<_Dq;-JFMB@6)>AY z?ydH>q1-#^VBZd&_3-RFos@lh7$PSM9-WwcpsYyc<}JD69oYK9f!`bX=`g(s;cK#p zzA#Q9iU0QU33-XW;9|+*FbOV}5>xaY5lbP~;IibT=qs(FFSEJtEG#iUE`R!p?6S*dna;J`@{{v1d;6ieik#$MDXzSFTVOPcYzxwh2id?wMea1xYYyQGb;Fl=7dFTO<8o z@)&tW&nml7Rf><=H8np|h&&#nV?)B#uKnST)7dNurzR=fsp!y>c-@+&1*KdI;^1W* zyf7^Qy1|1QcwCE9TL9ozgck5}PWn$QJ2F#fA2pX%h+Y4^WLKQ{TrmN%FrYz@LJ69p zZ?047#fmUACR;?%q%jgSrx;_xpvnC6gUoISj0PAq^Apgd44T{r8f>%T7L2RIl1mGm zk2ZrA(@5{107>_gRS7j9TCb)a9FO>atbK0A?@SZUMR%(IO+R0iV(ny#Y|MR=ld1_E z0tE4s$O$eEG(sxP7^y)Zv$>?U>iv@h3MejQg6zo&Y#qpr)i9;ljy<>Z$a&nr+2ybaQ<|43@ECzJ`Fh5qk z+?fN(XdwGK+A{ZU>_4<5*L=0vEWI8>NIvn$5NH-s>S~bTQ}n4Wy|FkKVHm@V8w}^H zZ4&N59>TowZ-0{=3nv0vvy(;(DFFzRa0^op>CJZwbO>))gGKg*2)%og(hG$F-;-Dj zjsazp=M1s|#gm#1cns`LstCorJteXs^%avI4jBPglQ<4g0i?5u4ov|8SCiKdAp*Wz zlll+pAVWMh4JJezHpkxQdJ&FK8K?f(klMm5d<)B7J=L`*kCOxuK@B$AZKJA6XspWl z>7EvoQV}o#5tD-vUIIR5lj9Mv0UMK)5+MN*v$hiP2MumTv{*wA1#MFr002mnv>GV` Ru$)Sh;2IzXoEiWC0064O?nnRt delta 1098 zcmV-Q1hxBzHikAiP)h>@6aWAK2ms)lvsec4&M;CM002b}0RRsG8~|)=XK!C&b#!lM zWo|BPY*kbV00Z;lNoMroNwGQb27hMk%#mGo7v6l~%@^K$;msj=GvTc5ux5i-z-$Kj zw%Xr@vhJjVcRRS%!}IQRQr_)hg`B8%bYk*>QX-X`wx{2)Ebhk9eTwH)6`C zF1|iJMm;uX9hrNNV^ml;tA|k$pWv(vn=VGhr)X5z_-dEc0IiJoBXsx-yKKZNe?px} zzN@zOlrRSjTD6m|s_ol7nt!;R^{S&JY;f(_F%B ziD0~*!OGZ~PH|ysB)b<0r>h@X1on6NP;5BHo;l4ciZK=^Lu0QR$j*^hLIz5i*aSqB zbWsugm!j(|<>jjyb>)Gms|Z3}xk6n$yMR~OCM0vXXLdmrB)gzRQGfbV%7033jogFD z1LPS!tL#QqDL!h~)cj2G@pz1O4GCAf_J=!8XR{=nnxt^2qC-pKMQfTClyWVIgO_pe z!qoqFg9kP6xE80@|KmP{7VvUT`cEu1GE-EU7-Pbq$^4Up%vK1D1{gH+6VRj#n%oB(Y_sD2i>t$uOADNg zHiH(^NN=71N$ZnV2{j;2ucjUxkNAJAO>V|-OB2pTcdGeKKVOw%?PQ8<%zZPHs|g$e z?C_Jx2`&zFK`PA{sX-vKxumx0&65QRC@x`w?8ymi9mtK3D4Y%~jdZtEz!Z>l& zYLwg(0ver&g=wkxkt~&SgqHSrlUoWnf49L1{V8E)qB&36lQ2ya+-MfQaVJ$jSV3xxsGlUWRo z0a=si46*^alba2A4CYR%2*tcTC9)y)36mcV838AgISx<(p|gq(O#uNXlh_X-0zO)k z`w!|MD?Bz0CPW)H$KL095spt8r~cBA+QKY+3(H 0 { b.InlineCall(b.Pkg.rtFunc("PrintString"), b.Str(" ")) + // TODO(visualfc): maybe use PrintCStr is more efficient } var fn string - var typ Type + var typ Type // TODO(visualfc): typ uninitialized in some cases switch arg.kind { case vkBool: fn = "PrintBool" @@ -1002,6 +1014,8 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { case vkSlice: fn = "PrintSlice" case vkPtr, vkFuncPtr, vkFuncDecl, vkClosure, vkPyVarRef, vkPyFuncRef: + // TODO(visualfc): vkClosure is not a pointer + // TODO(visualfc): vkPyVarRef, vkPyFuncRef is pointer of pointer fn = "PrintPointer" typ = b.Prog.VoidPtr() case vkString: @@ -1037,8 +1051,11 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { } } } + case "String": // unsafe.String + // TODO(xsw): make this a builtin + return b.InlineCall(b.Pkg.rtFunc("NewString"), args[0], args[1]) } - panic("todo") + panic("todo: " + fn) } // ----------------------------------------------------------------------------- diff --git a/ssa/interface.go b/ssa/interface.go index ee9a451e..16004054 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -27,19 +27,29 @@ import ( // ----------------------------------------------------------------------------- -// AbiBasic returns the abi type of the specified basic kind. -func (b Builder) AbiBasic(kind types.BasicKind) Expr { +// abiBasic returns the abi type of the specified basic kind. +func (b Builder) abiBasic(kind types.BasicKind) Expr { return b.InlineCall(b.Pkg.rtFunc("Basic"), b.Prog.Val(int(kind))) } /* -// AbiStruct returns the abi type of the specified struct type. -func (b Builder) AbiStruct(t *types.Struct) Expr { - panic("todo") - // return b.InlineCall(b.Pkg.rtFunc("Struct"), b.Prog.Val(t.NumFields())) +// abiStruct returns the abi type of the specified struct type. +func (b Builder) abiStruct(t *types.Struct) Expr { + // name := "__llgo_" + b.Prog.abi.StructName(t) } */ +// AbiType returns the abi type of the specified type. +func (b Builder) AbiType(t Type) Expr { + switch tx := t.raw.Type.(type) { + case *types.Basic: + return b.abiBasic(tx.Kind()) + //case *types.Struct: + // return b.abiStruct(tx) + } + panic("todo") +} + // ----------------------------------------------------------------------------- // MakeInterface constructs an instance of an interface type from a @@ -57,37 +67,66 @@ func (b Builder) AbiStruct(t *types.Struct) Expr { // t1 = make interface{} <- int (42:int) // t2 = make Stringer <- t0 func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) { - raw := tinter.raw.Type + rawIntf := tinter.raw.Type.Underlying().(*types.Interface) if debugInstr { - log.Printf("MakeInterface %v, %v\n", raw, x.impl) + log.Printf("MakeInterface %v, %v\n", rawIntf, x.impl) } prog := b.Prog - pkg := b.Pkg - switch tx := x.raw.Type.Underlying().(type) { + typ := x.Type + switch tx := typ.raw.Type.Underlying().(type) { case *types.Basic: kind := tx.Kind() switch { case kind >= types.Bool && kind <= types.Uintptr: - t := b.AbiBasic(kind) - tptr := prog.Uintptr() - vptr := Expr{llvm.CreateIntCast(b.impl, x.impl, tptr.ll), tptr} - return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} + if prog.is32Bits && (kind == types.Int64 || kind == types.Uint64) { + return b.makeIntfAlloc(tinter, rawIntf, typ, x) + } + return b.makeIntfByIntptr(tinter, rawIntf, typ, x.impl) case kind == types.Float32: - t := b.AbiBasic(kind) - tptr := prog.Uintptr() - i32 := llvm.CreateBitCast(b.impl, x.impl, prog.tyInt32()) // TODO(xsw): more effective - vptr := Expr{llvm.CreateIntCast(b.impl, i32, tptr.ll), tptr} - return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} + i32 := llvm.CreateBitCast(b.impl, x.impl, prog.tyInt32()) + return b.makeIntfByIntptr(tinter, rawIntf, typ, i32) case kind == types.Float64: - t := b.AbiBasic(kind) - tptr := prog.Uintptr() - vptr := Expr{llvm.CreateBitCast(b.impl, x.impl, tptr.ll), tptr} - return Expr{b.InlineCall(pkg.rtFunc("MakeAnyInt"), t, vptr).impl, tinter} + if prog.is32Bits { + return b.makeIntfAlloc(tinter, rawIntf, typ, x) + } + i64 := llvm.CreateBitCast(b.impl, x.impl, prog.tyInt64()) + return b.makeIntfByIntptr(tinter, rawIntf, typ, i64) case kind == types.String: - return Expr{b.InlineCall(pkg.rtFunc("MakeAnyString"), x).impl, tinter} + return Expr{b.InlineCall(b.Pkg.rtFunc("MakeAnyString"), x).impl, tinter} } - // case *types.Struct: - // t := b.AbiStruct(tx) + /* case *types.Struct: + size := int(prog.SizeOf(typ)) + if size > prog.PointerSize() { + return b.makeIntfAlloc(tinter, rawIntf, typ, x) + } + tv := prog.ctx.IntType(size * 8) + iv := llvm.CreateBitCast(b.impl, x.impl, tv) + return b.makeIntfByIntptr(tinter, rawIntf, typ, iv) */ + } + panic("todo") +} + +func (b Builder) makeIntfAlloc(tinter Type, rawIntf *types.Interface, typ Type, x Expr) (ret Expr) { + vptr := b.AllocU(typ) + b.Store(vptr, x) + return b.makeIntfByPtr(tinter, rawIntf, typ, vptr) +} + +func (b Builder) makeIntfByPtr(tinter Type, rawIntf *types.Interface, typ Type, vptr Expr) (ret Expr) { + if rawIntf.Empty() { + ret = b.InlineCall(b.Pkg.rtFunc("MakeAny"), b.AbiType(typ), vptr) + ret.Type = tinter + return + } + panic("todo") +} + +func (b Builder) makeIntfByIntptr(tinter Type, rawIntf *types.Interface, typ Type, x llvm.Value) (ret Expr) { + if rawIntf.Empty() { + tptr := b.Prog.Uintptr() + x = llvm.CreateIntCast(b.impl, x, tptr.ll) + impl := b.InlineCall(b.Pkg.rtFunc("MakeAnyIntptr"), b.AbiType(typ), Expr{x, tptr}).impl + return Expr{impl, tinter} } panic("todo") } diff --git a/ssa/package.go b/ssa/package.go index bc9cb7cc..ca8ec18c 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -99,6 +99,7 @@ type aProgram struct { ctx llvm.Context typs typeutil.Map // rawType -> Type gocvt goTypes + //abi *abi.Builder rt *types.Package rtget func() *types.Package @@ -158,6 +159,7 @@ type aProgram struct { NeedRuntime bool NeedPyInit bool + is32Bits bool } // A Program presents a program. @@ -180,7 +182,12 @@ func NewProgram(target *Target) Program { // TODO(xsw): Finalize may cause panic, so comment it. ctx.Finalize() */ - return &aProgram{ctx: ctx, gocvt: newGoTypes(), target: target, td: td, named: make(map[string]llvm.Type)} + is32Bits := (td.PointerSize() == 4) + return &aProgram{ + ctx: ctx, gocvt: newGoTypes(), // abi: abi.New(), + target: target, td: td, is32Bits: is32Bits, + named: make(map[string]llvm.Type), + } } // SetPython sets the Python package. diff --git a/ssa/type.go b/ssa/type.go index 17f5bd07..b7307c39 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -99,6 +99,10 @@ func (p Program) SizeOf(typ Type, n ...int64) uint64 { return size } +func (p Program) PointerSize() int { + return p.td.PointerSize() +} + func (p Program) Slice(typ Type) Type { return p.rawType(types.NewSlice(typ.raw.Type)) } From 6335ac6a47165c31e3fed7de8f1aad06c3f0c54d Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 20 May 2024 08:51:27 +0800 Subject: [PATCH 2/3] runtime.MakeAnyIntptr --- cl/_testdata/print/out.ll | 44 +++++++++++++++++++-------------------- cl/_testdata/vargs/out.ll | 10 ++++----- cl/_testrt/any/out.ll | 4 ++-- cl/_testrt/builtin/out.ll | 6 +++--- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/cl/_testdata/print/out.ll b/cl/_testdata/print/out.ll index dd88c08e..5aa0ca70 100644 --- a/cl/_testdata/print/out.ll +++ b/cl/_testdata/print/out.ll @@ -99,11 +99,11 @@ _llgo_0: call void @main.prinfsub(double 1.001000e+02) call void @main.printnl() %3 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 13) - %4 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %3, i64 1315859240) + %4 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %3, i64 1315859240) call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %4) call void @main.printnl() %5 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14) - %6 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %5, i64 4746175415993761792) + %6 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %5, i64 4746175415993761792) call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %6) call void @main.printnl() br i1 true, label %_llgo_3, label %_llgo_2 @@ -116,7 +116,7 @@ _llgo_1: ; preds = %_llgo_3 store %"github.com/goplus/llgo/internal/runtime.iface" %10, ptr %8, align 8 %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %7, i64 1 %12 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1) - %13 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %12, i64 -1) + %13 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %12, i64 -1) store %"github.com/goplus/llgo/internal/runtime.iface" %13, ptr %11, align 8 %14 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %7, i64 16, i64 2, i64 0, i64 2, i64 2) call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %14) @@ -130,74 +130,74 @@ _llgo_2: ; preds = %_llgo_3, %_llgo_1, store %"github.com/goplus/llgo/internal/runtime.iface" %18, ptr %16, align 8 %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %15, i64 1 %20 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1) - %21 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %20, i64 -1) + %21 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %20, i64 -1) store %"github.com/goplus/llgo/internal/runtime.iface" %21, ptr %19, align 8 %22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %15, i64 2 %23 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1) - %24 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %23, i64 -1) + %24 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %23, i64 -1) store %"github.com/goplus/llgo/internal/runtime.iface" %24, ptr %22, align 8 %25 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %15, i64 16, i64 3, i64 0, i64 3, i64 3) call void @main.println(%"github.com/goplus/llgo/internal/runtime.Slice" %25) %26 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 256) %27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 0 %28 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1) - %29 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %28, i64 -1) + %29 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %28, i64 -1) store %"github.com/goplus/llgo/internal/runtime.iface" %29, ptr %27, align 8 %30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 1 %31 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 1) - %32 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %31, i64 0) + %32 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %31, i64 0) store %"github.com/goplus/llgo/internal/runtime.iface" %32, ptr %30, align 8 %33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 2 %34 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5) - %35 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %34, i64 97) + %35 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %34, i64 97) store %"github.com/goplus/llgo/internal/runtime.iface" %35, ptr %33, align 8 %36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 3 %37 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5) - %38 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %37, i64 65) + %38 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %37, i64 65) store %"github.com/goplus/llgo/internal/runtime.iface" %38, ptr %36, align 8 %39 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 4 %40 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5) - %41 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %40, i64 20013) + %41 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %40, i64 20013) store %"github.com/goplus/llgo/internal/runtime.iface" %41, ptr %39, align 8 %42 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 5 %43 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3) - %44 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %43, i64 1) + %44 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %43, i64 1) store %"github.com/goplus/llgo/internal/runtime.iface" %44, ptr %42, align 8 %45 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 6 %46 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 4) - %47 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %46, i64 2) + %47 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %46, i64 2) store %"github.com/goplus/llgo/internal/runtime.iface" %47, ptr %45, align 8 %48 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 7 %49 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 5) - %50 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %49, i64 3) + %50 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %49, i64 3) store %"github.com/goplus/llgo/internal/runtime.iface" %50, ptr %48, align 8 %51 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 8 %52 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6) - %53 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %52, i64 4) + %53 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %52, i64 4) store %"github.com/goplus/llgo/internal/runtime.iface" %53, ptr %51, align 8 %54 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 9 %55 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) - %56 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %55, i64 5) + %56 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %55, i64 5) store %"github.com/goplus/llgo/internal/runtime.iface" %56, ptr %54, align 8 %57 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 10 %58 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 8) - %59 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %58, i64 1) + %59 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %58, i64 1) store %"github.com/goplus/llgo/internal/runtime.iface" %59, ptr %57, align 8 %60 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 11 %61 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 9) - %62 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %61, i64 2) + %62 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %61, i64 2) store %"github.com/goplus/llgo/internal/runtime.iface" %62, ptr %60, align 8 %63 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 12 %64 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 10) - %65 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %64, i64 3) + %65 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %64, i64 3) store %"github.com/goplus/llgo/internal/runtime.iface" %65, ptr %63, align 8 %66 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 13 %67 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 11) - %68 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %67, i64 4) + %68 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %67, i64 4) store %"github.com/goplus/llgo/internal/runtime.iface" %68, ptr %66, align 8 %69 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 14 %70 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 12) - %71 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %70, i64 5) + %71 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %70, i64 5) store %"github.com/goplus/llgo/internal/runtime.iface" %71, ptr %69, align 8 %72 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %26, i64 15 %73 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @4, i64 4) @@ -801,9 +801,9 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"() declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64) -declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) +declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr, i64) -declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64) +declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyString"(%"github.com/goplus/llgo/internal/runtime.String") diff --git a/cl/_testdata/vargs/out.ll b/cl/_testdata/vargs/out.ll index def89a93..86c098c9 100644 --- a/cl/_testdata/vargs/out.ll +++ b/cl/_testdata/vargs/out.ll @@ -31,15 +31,15 @@ _llgo_0: %2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 48) %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 0 %4 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) - %5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %4, i64 1) + %5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %4, i64 1) store %"github.com/goplus/llgo/internal/runtime.iface" %5, ptr %3, align 8 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 1 %7 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) - %8 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %7, i64 2) + %8 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %7, i64 2) store %"github.com/goplus/llgo/internal/runtime.iface" %8, ptr %6, align 8 %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %2, i64 2 %10 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) - %11 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %10, i64 3) + %11 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %10, i64 3) store %"github.com/goplus/llgo/internal/runtime.iface" %11, ptr %9, align 8 %12 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %2, i64 16, i64 3, i64 0, i64 3, i64 3) call void @main.test(%"github.com/goplus/llgo/internal/runtime.Slice" %12) @@ -76,9 +76,9 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"() declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) -declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) +declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr, i64) -declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64) +declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64) diff --git a/cl/_testrt/any/out.ll b/cl/_testrt/any/out.ll index fdd52ad1..fbf58289 100644 --- a/cl/_testrt/any/out.ll +++ b/cl/_testrt/any/out.ll @@ -36,7 +36,7 @@ _llgo_0: call void @"github.com/goplus/llgo/internal/runtime.init"() call void @main.init() %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) - %3 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %2, i64 100) + %3 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %2, i64 100) %4 = call i64 @main.incVal(%"github.com/goplus/llgo/internal/runtime.iface" %3) %5 = call i32 (ptr, ...) @printf(ptr @0, i64 %4) ret i32 0 @@ -48,6 +48,6 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) declare void @"github.com/goplus/llgo/internal/runtime.init"() -declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64) +declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr, i64) declare i32 @printf(ptr, ...) diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll index 2af18d2b..39388613 100644 --- a/cl/_testrt/builtin/out.ll +++ b/cl/_testrt/builtin/out.ll @@ -288,7 +288,7 @@ _llgo_0: call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %121) %122 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16) %123 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) - %124 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr %123, i64 100) + %124 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr %123, i64 100) store %"github.com/goplus/llgo/internal/runtime.iface" %124, ptr %122, align 8 %125 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %122, align 8 %126 = ptrtoint ptr %122 to i64 @@ -392,9 +392,9 @@ declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/ll declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.SliceAppend"(%"github.com/goplus/llgo/internal/runtime.Slice", ptr, i64, i64) -declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) +declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyIntptr"(ptr, i64) -declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAnyInt"(ptr, i64) +declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) declare void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1) From cc357b2b7dc935ccc90bf6a5a912efb871a22ea1 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 20 May 2024 10:23:24 +0800 Subject: [PATCH 3/3] llgo/ssa: TestMakeInterface (32bits); ssa/ssatest --- chore/llvmtargets/llvm_targets.go | 18 ++++++++++ cl/cltest/cltest.go | 17 ++------- ssa/cl_test.go | 37 ++++++++++++++++++++ ssa/package.go | 2 +- ssa/ssa_test.go | 8 +++++ ssa/ssatest/ssautil.go | 58 +++++++++++++++++++++++++++++++ 6 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 chore/llvmtargets/llvm_targets.go create mode 100644 ssa/ssatest/ssautil.go diff --git a/chore/llvmtargets/llvm_targets.go b/chore/llvmtargets/llvm_targets.go new file mode 100644 index 00000000..936ae7e9 --- /dev/null +++ b/chore/llvmtargets/llvm_targets.go @@ -0,0 +1,18 @@ +package main + +import ( + "fmt" + + "github.com/goplus/llvm" +) + +func main() { + llvm.InitializeAllTargetInfos() + llvm.InitializeAllTargets() + llvm.InitializeAllTargetMCs() + llvm.InitializeNativeTarget() + fmt.Println("targets:") + for it := llvm.FirstTarget(); it.C != nil; it = it.NextTarget() { + fmt.Printf("- %s: %s\n", it.Name(), it.Description()) + } +} diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go index 3b8c60b2..a0d0b750 100644 --- a/cl/cltest/cltest.go +++ b/cl/cltest/cltest.go @@ -32,6 +32,7 @@ import ( "github.com/goplus/gogen/packages" "github.com/goplus/llgo/cl" "github.com/goplus/llgo/internal/llgen" + "github.com/goplus/llgo/ssa/ssatest" "golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa/ssautil" @@ -139,21 +140,7 @@ func TestCompileEx(t *testing.T, src any, fname, expected string) { t.Fatal("BuildPackage failed:", err) } foo.WriteTo(os.Stderr) - prog := llssa.NewProgram(nil) - prog.SetRuntime(func() *types.Package { - rt, err := imp.Import(llssa.PkgRuntime) - if err != nil { - t.Fatal("load runtime failed:", err) - } - return rt - }) - prog.SetPython(func() *types.Package { - rt, err := imp.Import(llssa.PkgPython) - if err != nil { - t.Fatal("load python failed:", err) - } - return rt - }) + prog := ssatest.NewProgramEx(t, nil, imp) ret, err := cl.NewPackage(prog, foo, files) if err != nil { diff --git a/ssa/cl_test.go b/ssa/cl_test.go index 21c8bf85..c89a0958 100644 --- a/ssa/cl_test.go +++ b/ssa/cl_test.go @@ -17,9 +17,12 @@ package ssa_test import ( + "go/types" "testing" "github.com/goplus/llgo/cl/cltest" + "github.com/goplus/llgo/ssa" + "github.com/goplus/llgo/ssa/ssatest" ) func TestFromTestpy(t *testing.T) { @@ -42,6 +45,40 @@ func TestAbi(t *testing.T) { cltest.Pkg(t, "github.com/goplus/llgo/internal/abi", "../internal/abi/llgo_autogen.ll") } +func TestMakeInterface(t *testing.T) { + prog := ssatest.NewProgram(t, &ssa.Target{GOARCH: "x86"}) + pkg := prog.NewPackage("foo", "foo") + fn := pkg.NewFunc("main", types.NewSignatureType(nil, nil, nil, nil, nil, false), ssa.InC) + b := fn.MakeBody(1) + b.MakeInterface(prog.Any(), prog.IntVal(100, prog.Int64())) + b.MakeInterface(prog.Any(), prog.FloatVal(100, prog.Float64())) + b.Return() + ssatest.Assert(t, pkg, `; ModuleID = 'foo' +source_filename = "foo" + +%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr } + +define void @main() { +_llgo_0: + %0 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) + store i64 100, ptr %0, align 4 + %1 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 6) + %2 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %1, ptr %0) + %3 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) + store double 1.000000e+02, ptr %3, align 8 + %4 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 14) + %5 = call %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr %4, ptr %3) + ret void +} + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64) + +declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llgo/internal/runtime.MakeAny"(ptr, ptr) + +declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) +`) +} + /* func TestCallback(t *testing.T) { ctx := llvm.NewContext() diff --git a/ssa/package.go b/ssa/package.go index ca8ec18c..9e9356bb 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -182,7 +182,7 @@ func NewProgram(target *Target) Program { // TODO(xsw): Finalize may cause panic, so comment it. ctx.Finalize() */ - is32Bits := (td.PointerSize() == 4) + is32Bits := (td.PointerSize() == 4 || target.GOARCH == "x86") // TODO(xsw): remove temp code return &aProgram{ ctx: ctx, gocvt: newGoTypes(), // abi: abi.New(), target: target, td: td, is32Bits: is32Bits, diff --git a/ssa/ssa_test.go b/ssa/ssa_test.go index 05496769..103ee79e 100644 --- a/ssa/ssa_test.go +++ b/ssa/ssa_test.go @@ -21,10 +21,18 @@ import ( "go/token" "go/types" "testing" + "unsafe" "github.com/goplus/llvm" ) +func TestPointerSize(t *testing.T) { + expected := unsafe.Sizeof(uintptr(0)) + if size := NewProgram(nil).PointerSize(); size != int(expected) { + t.Fatal("bad PointerSize:", size) + } +} + func TestSetBlock(t *testing.T) { defer func() { if r := recover(); r == nil { diff --git a/ssa/ssatest/ssautil.go b/ssa/ssatest/ssautil.go new file mode 100644 index 00000000..bbb8ae9a --- /dev/null +++ b/ssa/ssatest/ssautil.go @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ssatest + +import ( + "go/token" + "go/types" + "testing" + + "github.com/goplus/gogen/packages" + "github.com/goplus/llgo/ssa" +) + +func NewProgram(t *testing.T, target *ssa.Target) ssa.Program { + fset := token.NewFileSet() + imp := packages.NewImporter(fset) + return NewProgramEx(t, target, imp) +} + +func NewProgramEx(t *testing.T, target *ssa.Target, imp types.Importer) ssa.Program { + prog := ssa.NewProgram(target) + prog.SetRuntime(func() *types.Package { + rt, err := imp.Import(ssa.PkgRuntime) + if err != nil { + t.Fatal("load runtime failed:", err) + } + return rt + }) + prog.SetPython(func() *types.Package { + rt, err := imp.Import(ssa.PkgPython) + if err != nil { + t.Fatal("load python failed:", err) + } + return rt + }) + return prog +} + +func Assert(t *testing.T, p ssa.Package, expected string) { + t.Helper() + if v := p.String(); v != expected { + t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) + } +}