From 165a99fd83696654fc48b6fce20b2c69f2c7c50e Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 27 May 2024 08:07:34 +0800 Subject: [PATCH 1/7] llgo/ssa: unsafeInterface; runtime.PointerTo --- cl/compile.go | 6 ++ internal/runtime/z_face.go | 164 +++++++++++++++++++++++-------------- internal/runtime/z_type.go | 25 +++--- ssa/cl_test.go | 2 +- ssa/expr.go | 20 +++-- ssa/interface.go | 82 +++++++++++++++++-- ssa/package.go | 9 +- ssa/type.go | 1 + 8 files changed, 220 insertions(+), 89 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index 7105730d..00f63ee9 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -558,6 +558,12 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue switch v := iv.(type) { case *ssa.Call: cv := v.Call.Value + if mthd := v.Call.Method; mthd != nil { + o := p.compileValue(b, cv) + args := p.compileValues(b, v.Call.Args, fnNormal) + ret = b.Icall(o, v.Call.Method, args...) + break + } kind := p.funcKind(cv) if kind == fnIgnore { return diff --git a/internal/runtime/z_face.go b/internal/runtime/z_face.go index c7611fd3..149c06c6 100644 --- a/internal/runtime/z_face.go +++ b/internal/runtime/z_face.go @@ -43,6 +43,8 @@ type ( Itab = itab ) +type Imethod = abi.Imethod +type Method = abi.Method type FuncType = abi.FuncType type InterfaceType = abi.InterfaceType @@ -54,14 +56,105 @@ func ToEface(i Iface) Eface { // ----------------------------------------------------------------------------- const ( - typeHdrSize = unsafe.Sizeof(abi.Type{}) - funcTypeHdrSize = unsafe.Sizeof(abi.FuncType{}) - uncommonTypeHdrSize = unsafe.Sizeof(abi.UncommonType{}) - methodSize = unsafe.Sizeof(abi.Method{}) - pointerSize = unsafe.Sizeof(uintptr(0)) - itabHdrSize = unsafe.Sizeof(itab{}) - pointerSize + typeHdrSize = unsafe.Sizeof(abi.Type{}) + arrayTypeHdrSize = unsafe.Sizeof(abi.ArrayType{}) + chanTypeHdrSize = unsafe.Sizeof(abi.ChanType{}) + funcTypeHdrSize = unsafe.Sizeof(abi.FuncType{}) + interfaceTypeHdrSize = unsafe.Sizeof(abi.InterfaceType{}) + mapTypeHdrSize = unsafe.Sizeof(abi.MapType{}) + ptrTypeHdrSize = unsafe.Sizeof(abi.PtrType{}) + sliceTypeHdrSize = unsafe.Sizeof(abi.SliceType{}) + structTypeHdrSize = unsafe.Sizeof(abi.StructType{}) + uncommonTypeHdrSize = unsafe.Sizeof(abi.UncommonType{}) + methodSize = unsafe.Sizeof(abi.Method{}) + pointerSize = unsafe.Sizeof(uintptr(0)) + itabHdrSize = unsafe.Sizeof(itab{}) - pointerSize ) +var hdrSizes = [...]uintptr{ + arrayTypeHdrSize, + chanTypeHdrSize, + funcTypeHdrSize, + interfaceTypeHdrSize, + mapTypeHdrSize, + ptrTypeHdrSize, + sliceTypeHdrSize, + typeHdrSize, + structTypeHdrSize, +} + +func hdrSizeOf(kind abi.Kind) uintptr { + if kind >= abi.Array && kind <= abi.Struct { + return hdrSizes[kind-abi.Array] + } + return typeHdrSize +} + +// Named returns a named type. +func Named(pkgPath, name string, underlying *Type, methods []abi.Method) *Type { + tflag := underlying.TFlag + if tflag&abi.TFlagUncommon != 0 { + panic("runtime: underlying type is already named") + } + + kind := underlying.Kind() + n := len(methods) + if kind == abi.Interface { + if n > 0 { + panic("runtime: interface type cannot have methods") + } + ret := *underlying.InterfaceType() + ret.PkgPath_ = pkgPath + ret.Str_ = name + return &ret.Type + } + + baseSize := hdrSizeOf(kind) + extraSize := uintptr(0) + if kind == abi.Func { + f := underlying.FuncType() + extraSize = uintptr(f.In()+f.Out()) * pointerSize + } + + size := baseSize + extraSize + if n > 0 || pkgPath != "" { + size += uncommonTypeHdrSize + uintptr(n)*methodSize + tflag |= abi.TFlagUncommon + } + + ptr := AllocU(size) + c.Memcpy(ptr, unsafe.Pointer(underlying), baseSize) + + ret := (*Type)(ptr) + ret.TFlag = tflag | abi.TFlagNamed + ret.Str_ = name + + xcount := 0 + for _, m := range methods { + if !m.Exported() { + break + } + xcount++ + } + uncommon := (*abi.UncommonType)(c.Advance(ptr, int(baseSize))) + uncommon.PkgPath_ = pkgPath + uncommon.Mcount = uint16(n) + uncommon.Xcount = uint16(xcount) + uncommon.Moff = uint32(uncommonTypeHdrSize + extraSize) + + extraOff := int(baseSize + uncommonTypeHdrSize) + if extraSize > 0 { + src := c.Advance(unsafe.Pointer(underlying), int(baseSize)) + dest := c.Advance(unsafe.Pointer(ptr), extraOff) + c.Memcpy(dest, src, extraSize) + extraOff += int(extraSize) + } + + data := (*abi.Method)(c.Advance(ptr, extraOff)) + copy(unsafe.Slice(data, n), methods) + return ret +} + // Func returns a function type. func Func(in, out []*Type, variadic bool) *FuncType { n := len(in) + len(out) @@ -85,61 +178,8 @@ func Func(in, out []*Type, variadic bool) *FuncType { return ret } -// Imethod returns an interface method. -func Imethod(name string, typ *FuncType) abi.Imethod { - return abi.Imethod{ - Name_: name, - Typ_: typ, - } -} - -// Method returns a method. -func Method(name string, typ *FuncType, ifn, tfn abi.Text) abi.Method { - return abi.Method{ - Name_: name, - Mtyp_: typ, - Ifn_: ifn, - Tfn_: tfn, - } -} - -// Named returns a named type. -func Named(pkgPath, name string, underlying *Type, methods []abi.Method) *Type { - tflag := underlying.TFlag - size := typeHdrSize - n := len(methods) - if n > 0 || pkgPath != "" { - size += uncommonTypeHdrSize + uintptr(n)*methodSize - tflag |= abi.TFlagUncommon - } - ptr := AllocU(size) - - ret := (*Type)(ptr) - *ret = *underlying - ret.TFlag = tflag | abi.TFlagNamed - ret.Str_ = name - - xcount := 0 - for _, m := range methods { - if !m.Exported() { - break - } - xcount++ - } - - uncommon := (*abi.UncommonType)(c.Advance(ptr, int(typeHdrSize))) - uncommon.PkgPath_ = pkgPath - uncommon.Mcount = uint16(n) - uncommon.Xcount = uint16(xcount) - uncommon.Moff = uint32(uncommonTypeHdrSize) - - data := (*abi.Method)(c.Advance(ptr, int(typeHdrSize+uncommonTypeHdrSize))) - copy(unsafe.Slice(data, n), methods) - return ret -} - // Interface returns an interface type. -func Interface(pkgPath string, methods []abi.Imethod) *Type { +func Interface(pkgPath string, methods []abi.Imethod) *InterfaceType { ret := &abi.InterfaceType{ Type: Type{ Size_: unsafe.Sizeof(eface{}), @@ -149,7 +189,7 @@ func Interface(pkgPath string, methods []abi.Imethod) *Type { PkgPath_: pkgPath, Methods: methods, } - return &ret.Type + return ret } // NewItab returns a new itab. @@ -158,7 +198,7 @@ func NewItab(inter *InterfaceType, typ *Type) *Itab { size := itabHdrSize + uintptr(n)*pointerSize ptr := AllocU(size) - ret := (*Itab)(ptr) + ret := (*itab)(ptr) ret.inter = inter ret._type = typ ret.hash = typ.Hash diff --git a/internal/runtime/z_type.go b/internal/runtime/z_type.go index d39ad954..3693a8f4 100644 --- a/internal/runtime/z_type.go +++ b/internal/runtime/z_type.go @@ -112,17 +112,22 @@ func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *Type { // ----------------------------------------------------------------------------- -// Pointer returns a pointer type. -func Pointer(elem *Type) *Type { - ret := &abi.PtrType{ - Type: Type{ - Size_: unsafe.Sizeof(uintptr(0)), - Hash: uint32(abi.Pointer), // TODO(xsw): hash - Kind_: uint8(abi.Pointer), - }, - Elem: elem, +// PointerTo returns the pointer type with element elem. +func PointerTo(elem *Type) *Type { + ret := elem.PtrToThis_ + if ret == nil { + ptr := &abi.PtrType{ + Type: Type{ + Size_: unsafe.Sizeof(uintptr(0)), + Hash: uint32(abi.Pointer), // TODO(xsw): hash + Kind_: uint8(abi.Pointer), + }, + Elem: elem, + } + ret = &ptr.Type + elem.PtrToThis_ = ret } - return &ret.Type + return ret } // ----------------------------------------------------------------------------- diff --git a/ssa/cl_test.go b/ssa/cl_test.go index 513944c1..488a36bc 100644 --- a/ssa/cl_test.go +++ b/ssa/cl_test.go @@ -26,7 +26,7 @@ import ( ) func TestFromTestgo(t *testing.T) { - cltest.FromDir(t, "", "../cl/_testgo", false) + cltest.FromDir(t, "errors", "../cl/_testgo", false) } func TestFromTestpy(t *testing.T) { diff --git a/ssa/expr.go b/ssa/expr.go index 0a4d47ea..436d40fa 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -193,12 +193,6 @@ func (b Builder) Str(v string) (ret Expr) { return Expr{aggregateValue(b.impl, prog.rtString(), data, size), prog.String()} } -func (b Builder) pkgName(pkgPath string) Expr { - // TODO(xsw): use a global cache - // return b.Call(b.Pkg.rtFunc("NewPkgName"), b.Str(pkgPath)) - return b.Str(pkgPath) -} - // unsafeString(data *byte, size int) string func (b Builder) unsafeString(data, size llvm.Value) Expr { prog := b.Prog @@ -906,7 +900,16 @@ func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) { return b.Call(fn, args...) } -// The Call instruction represents a function or method call. +// The Icall instruction represents a interface method call. +// +// Example printed form: +// +// t7 = invoke t5.Println(...t6) +func (b Builder) Icall(o Expr, method *types.Func, args ...Expr) (ret Expr) { + panic("todo") +} + +// The Call instruction represents a function call. // // The Call instruction yields the function result if there is exactly // one. Otherwise it returns a tuple, the components of which are @@ -916,7 +919,6 @@ func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) { // // t2 = println(t0, t1) // t4 = t3() -// t7 = invoke t5.Println(...t6) func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { if debugInstr { var b bytes.Buffer @@ -954,7 +956,7 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { sig = raw.(*types.Signature) ll = fn.ll default: - panic("unreachable") + log.Panicf("unreachable: %d(%T)\n", kind, raw) } ret.Type = prog.retType(sig) ret.impl = llvm.CreateCall(b.impl, ll, fn.impl, llvmParamsEx(data, args, sig.Params(), b)) diff --git a/ssa/interface.go b/ssa/interface.go index 217d231a..52b4669b 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -55,23 +55,74 @@ func (b Builder) abiTypeOf(t types.Type) Expr { return b.abiStructOf(t) case *types.Named: return b.abiNamedOf(t) + case *types.Interface: + return b.abiInterfaceOf(t) + case *types.Signature: + return b.abiFuncOf(t) } panic("todo") } +func (b Builder) abiTupleOf(t *types.Tuple) Expr { + n := t.Len() + prog := b.Prog + tSlice := prog.Slice(prog.AbiTypePtr()) + tuple := make([]Expr, n) + for i := 0; i < n; i++ { + tuple[i] = b.abiType(t.At(i).Type()) + } + return b.SliceLit(tSlice, tuple...) +} + +// func Func(in, out []*Type, variadic bool) +func (b Builder) abiFuncOf(sig *types.Signature) Expr { + prog := b.Prog + pkg := b.Pkg + fn := pkg.rtFunc("Func") + params := b.abiTupleOf(sig.Params()) + results := b.abiTupleOf(sig.Results()) + variadic := prog.Val(sig.Variadic()) + return b.Call(fn, params, results, variadic) +} + +// Imethod{name string, typ *FuncType} +func (b Builder) abiImethodOf(m *types.Func) Expr { + prog := b.Prog + name := b.Str(m.Name()) + typ := b.abiType(m.Type()) + return b.aggregateValue(prog.rtType("Imethod"), name.impl, typ.impl) +} + +// func Interface(pkgPath string, methods []abi.Imethod) +func (b Builder) abiInterfaceOf(t *types.Interface) Expr { + prog := b.Prog + n := t.NumMethods() + methods := make([]Expr, n) + for i := 0; i < n; i++ { + m := t.Method(i) + methods[i] = b.abiImethodOf(m) + } + pkg := b.Pkg + fn := pkg.rtFunc("Interface") + pkgPath := pkg.Path() + tSlice := lastParamType(prog, fn) + methodSlice := b.SliceLit(tSlice, methods...) + return b.Call(fn, b.Str(pkgPath), methodSlice) +} + // func Named(pkgPath, name string, underlying *Type, methods []abi.Method) func (b Builder) abiNamedOf(t *types.Named) Expr { under := b.abiTypeOf(t.Underlying()) + path := abi.PathOf(t.Obj().Pkg()) name := NameOf(t) prog := b.Prog pkg := b.Pkg - pkgPath := b.pkgName(pkg.Path()) fn := pkg.rtFunc("Named") tSlice := lastParamType(prog, fn) // TODO(xsw): methods methods := prog.Zero(tSlice) - return b.Call(fn, pkgPath, b.Str(name), under, methods) + return b.Call(fn, b.Str(path), b.Str(name), under, methods) } func (b Builder) abiPointerOf(t *types.Pointer) Expr { @@ -93,7 +144,7 @@ func (b Builder) abiStructOf(t *types.Struct) Expr { off := uintptr(prog.OffsetOf(typ, i)) flds[i] = b.structField(sfAbi, prog, f, off, t.Tag(i)) } - pkgPath := b.pkgName(pkg.Path()) + pkgPath := b.Str(pkg.Path()) tSlice := lastParamType(prog, strucAbi) fldSlice := b.SliceLit(tSlice, flds...) size := prog.IntVal(prog.SizeOf(typ), prog.Uintptr()) @@ -156,6 +207,25 @@ func (b Builder) unsafeEface(t, data llvm.Value) llvm.Value { return aggregateValue(b.impl, b.Prog.rtEface(), t, data) } +// unsafeIface(itab *runtime.Itab, data unsafe.Pointer) Eface +func (b Builder) unsafeIface(itab, data llvm.Value) llvm.Value { + return aggregateValue(b.impl, b.Prog.rtIface(), itab, data) +} + +// func NewItab(tintf *InterfaceType, typ *Type) *runtime.Itab +func (b Builder) newItab(tintf, typ Expr) Expr { + return b.Call(b.Pkg.rtFunc("NewItab"), tintf, typ) +} + +func (b Builder) unsafeInterface(rawIntf *types.Interface, t Expr, data llvm.Value) llvm.Value { + if rawIntf.Empty() { + return b.unsafeEface(t.impl, data) + } + tintf := b.abiType(rawIntf) + itab := b.newItab(tintf, t) + return b.unsafeIface(itab.impl, data) +} + // ----------------------------------------------------------------------------- // MakeInterface constructs an instance of an interface type from a @@ -185,7 +255,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) { case abi.Indirect: vptr := b.AllocU(typ) b.Store(vptr, x) - return Expr{b.unsafeEface(tabi.impl, vptr.impl), tinter} + return Expr{b.unsafeInterface(rawIntf, tabi, vptr.impl), tinter} } ximpl := x.impl if lvl > 0 { @@ -194,7 +264,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) { var u llvm.Value switch kind { case abi.Pointer: - return Expr{b.unsafeEface(tabi.impl, ximpl), tinter} + return Expr{b.unsafeInterface(rawIntf, tabi, ximpl), tinter} case abi.Integer: tu := prog.Uintptr() u = llvm.CreateIntCast(b.impl, ximpl, tu.ll) @@ -205,7 +275,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) { panic("todo") } data := llvm.CreateIntToPtr(b.impl, u, prog.tyVoidPtr()) - return Expr{b.unsafeEface(tabi.impl, data), tinter} + return Expr{b.unsafeInterface(rawIntf, tabi, data), tinter} } func (b Builder) valFromData(typ Type, data llvm.Value) Expr { diff --git a/ssa/package.go b/ssa/package.go index 5df247db..c7347a7f 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -125,6 +125,7 @@ type aProgram struct { rtStringTy llvm.Type rtEfaceTy llvm.Type + rtIfaceTy llvm.Type rtSliceTy llvm.Type rtMapTy llvm.Type @@ -149,7 +150,6 @@ type aProgram struct { pyObjPPtr Type abiTyptr Type abiTypptr Type - //efaceTy Type pyImpTy *types.Signature pyNewList *types.Signature @@ -256,6 +256,13 @@ func (p Program) rtEface() llvm.Type { return p.rtEfaceTy } +func (p Program) rtIface() llvm.Type { + if p.rtIfaceTy.IsNil() { + p.rtIfaceTy = p.rtType("Iface").ll + } + return p.rtIfaceTy +} + func (p Program) rtMap() llvm.Type { if p.rtMapTy.IsNil() { p.rtMapTy = p.rtType("Map").ll diff --git a/ssa/type.go b/ssa/type.go index 2b1f3608..6f8b2161 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -274,6 +274,7 @@ func (p Program) toType(raw types.Type) Type { if t.Empty() { return &aType{p.rtEface(), typ, vkEface} } + return &aType{p.rtIface(), typ, vkIface} case *types.Slice: return &aType{p.rtSlice(), typ, vkSlice} case *types.Map: From eba08334d12a46c2e6fef350f2cdb41491dfbc00 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 27 May 2024 08:50:30 +0800 Subject: [PATCH 2/7] abi InterfaceName/FuncName --- ssa/abi/abi.go | 72 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/ssa/abi/abi.go b/ssa/abi/abi.go index 48badc0c..e6da942e 100644 --- a/ssa/abi/abi.go +++ b/ssa/abi/abi.go @@ -22,6 +22,7 @@ import ( "fmt" "go/types" "hash" + "log" "github.com/goplus/llgo/internal/abi" ) @@ -92,7 +93,6 @@ func KindOf(raw types.Type, lvl int, is32Bits bool) (Kind, types.Type, int) { // Builder is a helper for constructing ABI types. type Builder struct { - h hash.Hash buf []byte Pkg string } @@ -106,7 +106,6 @@ func New(pkg string) *Builder { func (b *Builder) Init(pkg string) { b.Pkg = pkg - b.h = sha256.New() b.buf = make([]byte, sha256.Size) } @@ -120,11 +119,19 @@ func (b *Builder) TypeName(t types.Type) (ret string, pub bool) { return "*" + ret, pub case *types.Struct: return b.StructName(t) + case *types.Signature: + return b.FuncName(t), true case *types.Named: o := t.Obj() return TypeName(o), o.Exported() + case *types.Interface: + if t.Empty() { + return "_llgo_any", true + } + return b.InterfaceName(t) } - panic("todo") + log.Panicf("todo: %T\n", t) + return } // PathOf returns the package path of the specified package. @@ -150,6 +157,57 @@ func BasicName(t *types.Basic) string { return "_llgo_" + t.Name() } +// FuncName returns the ABI type name for the specified function type. +func (b *Builder) FuncName(t *types.Signature) string { + hash := b.funcHash(t) + hashStr := base64.RawURLEncoding.EncodeToString(hash) + return "_llgo_func$" + hashStr +} + +func (b *Builder) funcHash(t *types.Signature) []byte { + h := sha256.New() + params, results := t.Params(), t.Results() + fmt.Fprintln(h, "func", params.Len(), results.Len(), t.Variadic()) + b.tuple(h, params) + b.tuple(h, results) + return h.Sum(b.buf[:0]) +} + +func (b *Builder) tuple(h hash.Hash, t *types.Tuple) { + n := t.Len() + for i := 0; i < n; i++ { + v := t.At(i) + ft, _ := b.TypeName(v.Type()) + fmt.Fprintln(h, ft) + } +} + +// InterfaceName returns the ABI type name for the specified interface type. +func (b *Builder) InterfaceName(t *types.Interface) (ret string, pub bool) { + hash, private := b.interfaceHash(t) + hashStr := base64.RawURLEncoding.EncodeToString(hash) + if private { + return b.Pkg + ".iface$" + hashStr, false + } + return "_llgo_iface$" + hashStr, true +} + +func (b *Builder) interfaceHash(t *types.Interface) (ret []byte, private bool) { + h := sha256.New() + n := t.NumMethods() + fmt.Fprintln(h, "interface", n) + for i := 0; i < n; i++ { + m := t.Method(i) + if !m.Exported() { + private = true + } + ft := b.FuncName(m.Type().(*types.Signature)) + fmt.Fprintln(h, m.Name(), ft) + } + ret = h.Sum(b.buf[:0]) + return +} + // StructName returns the ABI type name for the specified struct type. func (b *Builder) StructName(t *types.Struct) (ret string, pub bool) { hash, private := b.structHash(t) @@ -161,8 +219,7 @@ func (b *Builder) StructName(t *types.Struct) (ret string, pub bool) { } func (b *Builder) structHash(t *types.Struct) (ret []byte, private bool) { - h := b.h - h.Reset() + h := sha256.New() n := t.NumFields() fmt.Fprintln(h, "struct", n) for i := 0; i < n; i++ { @@ -174,10 +231,7 @@ func (b *Builder) structHash(t *types.Struct) (ret []byte, private bool) { if f.Embedded() { name = "-" } - ft, pub := b.TypeName(f.Type()) - if !pub { - private = true - } + ft, _ := b.TypeName(f.Type()) fmt.Fprintln(h, name, ft) } ret = h.Sum(b.buf[:0]) From 8536fe498724a22785db2098cc8143f113cf5517 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 27 May 2024 09:46:07 +0800 Subject: [PATCH 3/7] llgo/ssa: Imethod --- cl/compile.go | 3 ++- internal/runtime/z_closure.go | 44 ----------------------------------- ssa/expr.go | 14 ++--------- ssa/interface.go | 29 +++++++++++++++++++++++ ssa/package.go | 8 +++++++ ssa/type_cvt.go | 21 ----------------- 6 files changed, 41 insertions(+), 78 deletions(-) delete mode 100644 internal/runtime/z_closure.go diff --git a/cl/compile.go b/cl/compile.go index 00f63ee9..9db16bcb 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -560,8 +560,9 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue cv := v.Call.Value if mthd := v.Call.Method; mthd != nil { o := p.compileValue(b, cv) + fn := b.Imethod(o, v.Call.Method) args := p.compileValues(b, v.Call.Args, fnNormal) - ret = b.Icall(o, v.Call.Method, args...) + b.Call(fn, args...) break } kind := p.funcKind(cv) diff --git a/internal/runtime/z_closure.go b/internal/runtime/z_closure.go deleted file mode 100644 index d47818b3..00000000 --- a/internal/runtime/z_closure.go +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 runtime - -/* -import ( - "unsafe" -) - -// Closure represents a closure. -type Closure struct { - f unsafe.Pointer - data unsafe.Pointer // means no context if data is nil -} - -// NewClosure creates a closure. -func NewClosure(f, data unsafe.Pointer) Closure { - return Closure{f, data} -} - -// ClosureF returns the function of a closure. -func ClosureF(c Closure) unsafe.Pointer { - return c.f -} - -// ClosureData returns the data of a closure. -func ClosureData(c Closure) unsafe.Pointer { - return c.data -} -*/ diff --git a/ssa/expr.go b/ssa/expr.go index 436d40fa..c013da55 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -900,15 +900,6 @@ func (b Builder) InlineCall(fn Expr, args ...Expr) (ret Expr) { return b.Call(fn, args...) } -// The Icall instruction represents a interface method call. -// -// Example printed form: -// -// t7 = invoke t5.Println(...t6) -func (b Builder) Icall(o Expr, method *types.Func, args ...Expr) (ret Expr) { - panic("todo") -} - // The Call instruction represents a function call. // // The Call instruction yields the function result if there is exactly @@ -1079,11 +1070,10 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { typ = prog.Float64() case vkSlice: fn = "PrintSlice" - case vkPtr, vkFuncPtr, vkFuncDecl: - fn = "PrintPointer" - typ = prog.VoidPtr() case vkClosure: arg = b.Field(arg, 0) + fallthrough + case vkPtr, vkFuncPtr, vkFuncDecl: fn = "PrintPointer" typ = prog.VoidPtr() case vkString: diff --git a/ssa/interface.go b/ssa/interface.go index 52b4669b..a318a78d 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -226,6 +226,31 @@ func (b Builder) unsafeInterface(rawIntf *types.Interface, t Expr, data llvm.Val return b.unsafeIface(itab.impl, data) } +func iMethodOf(rawIntf *types.Interface, method *types.Func) int { + name := method.Name() + n := rawIntf.NumMethods() + for i := 0; i < n; i++ { + m := rawIntf.Method(i) + if m.Name() == name { + // TODO(xsw): check signature + return i + } + } + return -1 +} + +// Imethod returns closure of an interface method. +func (b Builder) Imethod(intf Expr, method *types.Func) Expr { + prog := b.Prog + rawIntf := intf.raw.Type.Underlying().(*types.Interface) + i := iMethodOf(rawIntf, method) + impl := intf.impl + itab := Expr{b.faceItab(impl), prog.VoidPtrPtr()} + pfn := b.Advance(itab, prog.IntVal(uint64(i+3), prog.Int())) + tclosure := prog.Type(method.Type(), InGo) + return b.aggregateValue(tclosure, b.Load(pfn).impl, b.faceData(impl)) +} + // ----------------------------------------------------------------------------- // MakeInterface constructs an instance of an interface type from a @@ -427,6 +452,10 @@ func (b Builder) faceData(x llvm.Value) llvm.Value { return llvm.CreateExtractValue(b.impl, x, 1) } +func (b Builder) faceItab(x llvm.Value) llvm.Value { + return llvm.CreateExtractValue(b.impl, x, 0) +} + func (b Builder) faceAbiType(x Expr) Expr { if x.kind == vkIface { panic("todo") diff --git a/ssa/package.go b/ssa/package.go index c7347a7f..dd562f4b 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -132,6 +132,7 @@ type aProgram struct { anyTy Type voidTy Type voidPtr Type + voidPPtr Type boolTy Type cstrTy Type cintTy Type @@ -371,6 +372,13 @@ func (p Program) VoidPtr() Type { return p.voidPtr } +func (p Program) VoidPtrPtr() Type { + if p.voidPPtr == nil { + p.voidPPtr = p.rawType(types.NewPointer(types.Typ[types.UnsafePointer])) + } + return p.voidPPtr +} + // Bool returns bool type. func (p Program) Bool() Type { if p.boolTy == nil { diff --git a/ssa/type_cvt.go b/ssa/type_cvt.go index 9bf505b6..aa578b5d 100644 --- a/ssa/type_cvt.go +++ b/ssa/type_cvt.go @@ -66,27 +66,6 @@ func (p Program) FuncDecl(sig *types.Signature, bg Background) Type { return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl} } -/* -// cvtCxFunc converts a C extended function type into raw type. -func cvtCxFunc(sig *types.Signature, recv *types.Var) *types.Signature { - if sig.Variadic() { - // convert printf-like function type - tParams := sig.Params() - n := tParams.Len() - params := make([]*types.Var, n) - n-- - for i := 0; i < n; i++ { - params[i] = tParams.At(i) - } - params[n] = VArg() - sig = types.NewSignatureType(nil, nil, nil, types.NewTuple(params...), sig.Results(), true) - panic("todo") - } - sig = FuncAddCtx(recv, sig) - return sig -} -*/ - // Closure creates a closture type for a function. func (p Program) Closure(fn Type) Type { sig := fn.raw.Type.(*types.Signature) From df13e3ab8294d23b428fb0772fa8cbc5ffb93ce4 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 27 May 2024 09:56:42 +0800 Subject: [PATCH 4/7] PrintIface --- cl/_testgo/errors/in.go | 21 +++++++++++++++++++++ cl/_testgo/errors/out.ll | 0 internal/runtime/z_print.go | 4 ++++ ssa/expr.go | 2 ++ ssa/interface.go | 2 +- 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 cl/_testgo/errors/in.go create mode 100644 cl/_testgo/errors/out.ll diff --git a/cl/_testgo/errors/in.go b/cl/_testgo/errors/in.go new file mode 100644 index 00000000..ada33367 --- /dev/null +++ b/cl/_testgo/errors/in.go @@ -0,0 +1,21 @@ +package main + +// New returns an error that formats as the given text. +// Each call to New returns a distinct error value even if the text is identical. +func New(text string) error { + return &errorString{text} +} + +// errorString is a trivial implementation of error. +type errorString struct { + s string +} + +func (e *errorString) Error() string { + return e.s +} + +func main() { + err := New("an error") + println(err, err.Error()) +} diff --git a/cl/_testgo/errors/out.ll b/cl/_testgo/errors/out.ll new file mode 100644 index 00000000..e69de29b diff --git a/internal/runtime/z_print.go b/internal/runtime/z_print.go index 27a47ac7..8edbbb69 100644 --- a/internal/runtime/z_print.go +++ b/internal/runtime/z_print.go @@ -69,3 +69,7 @@ func PrintSlice(s Slice) { func PrintEface(e Eface) { print("(", e._type, ",", e.data, ")") } + +func PrintIface(i Iface) { + print("(", i.tab, ",", i.data, ")") +} diff --git a/ssa/expr.go b/ssa/expr.go index c013da55..bdaa64df 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -1080,6 +1080,8 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { fn = "PrintString" case vkEface: fn = "PrintEface" + case vkIface: + fn = "PrintIface" // case vkComplex: // fn = "PrintComplex" default: diff --git a/ssa/interface.go b/ssa/interface.go index a318a78d..86fa5762 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -127,7 +127,7 @@ func (b Builder) abiNamedOf(t *types.Named) Expr { func (b Builder) abiPointerOf(t *types.Pointer) Expr { elem := b.abiTypeOf(t.Elem()) - return b.Call(b.Pkg.rtFunc("Pointer"), elem) + return b.Call(b.Pkg.rtFunc("PointerTo"), elem) } // func Struct(pkgPath string, size uintptr, fields []abi.StructField) From 877b397e04cf4dc51ba765ff80a361b61d8003ff Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 27 May 2024 11:18:43 +0800 Subject: [PATCH 5/7] cl: call intf.method --- cl/_testgo/errors/out.ll | 213 ++++++++++++++++++++++++++++++++++++ cl/_testgo/struczero/out.ll | 4 +- cl/_testrt/any/out.ll | 4 +- cl/compile.go | 2 +- ssa/cl_test.go | 2 +- 5 files changed, 219 insertions(+), 6 deletions(-) diff --git a/cl/_testgo/errors/out.ll b/cl/_testgo/errors/out.ll index e69de29b..2e203fa4 100644 --- a/cl/_testgo/errors/out.ll +++ b/cl/_testgo/errors/out.ll @@ -0,0 +1,213 @@ +; ModuleID = 'main' +source_filename = "main" + +%"github.com/goplus/llgo/internal/runtime.iface" = type { ptr, ptr } +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } +%main.errorString = type { %"github.com/goplus/llgo/internal/runtime.String" } +%"github.com/goplus/llgo/internal/abi.StructField" = type { %"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1 } +%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } +%"github.com/goplus/llgo/internal/abi.Imethod" = type { %"github.com/goplus/llgo/internal/runtime.String", ptr } + +@"main.init$guard" = global ptr null +@"*main.errorString" = global ptr null +@"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU" = linkonce global ptr null +@__llgo_argc = global ptr null +@__llgo_argv = global ptr null +@0 = private unnamed_addr constant [9 x i8] c"an error\00", align 1 +@1 = private unnamed_addr constant [2 x i8] c"s\00", align 1 +@2 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@3 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@4 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@5 = private unnamed_addr constant [17 x i8] c"main.errorString\00", align 1 +@6 = private unnamed_addr constant [6 x i8] c"Error\00", align 1 +@"_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to" = linkonce global ptr null +@7 = private unnamed_addr constant [5 x i8] c"main\00", align 1 + +define %"github.com/goplus/llgo/internal/runtime.iface" @main.New(%"github.com/goplus/llgo/internal/runtime.String" %0) { +_llgo_0: + %1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 16) + %2 = getelementptr inbounds %main.errorString, ptr %1, i32 0, i32 0 + store %"github.com/goplus/llgo/internal/runtime.String" %0, ptr %2, align 8 + %3 = load ptr, ptr @"*main.errorString", align 8 + %4 = load ptr, ptr @"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU", align 8 + %5 = call ptr @"github.com/goplus/llgo/internal/runtime.NewItab"(ptr %4, ptr %3) + %6 = alloca %"github.com/goplus/llgo/internal/runtime.iface", align 8 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, i32 0, i32 0 + store ptr %5, ptr %7, align 8 + %8 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, i32 0, i32 1 + store ptr %1, ptr %8, align 8 + %9 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8 + ret %"github.com/goplus/llgo/internal/runtime.iface" %9 +} + +define %"github.com/goplus/llgo/internal/runtime.String" @"(*main.errorString).Error"(ptr %0) { +_llgo_0: + %1 = getelementptr inbounds %main.errorString, ptr %0, i32 0, i32 0 + %2 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %1, align 8 + ret %"github.com/goplus/llgo/internal/runtime.String" %2 +} + +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 + call void @"main.init$abi"() + 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() + %2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0 + store ptr @0, ptr %3, align 8 + %4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1 + store i64 8, ptr %4, align 4 + %5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8 + %6 = call %"github.com/goplus/llgo/internal/runtime.iface" @main.New(%"github.com/goplus/llgo/internal/runtime.String" %5) + %7 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %6, 0 + %8 = getelementptr ptr, ptr %7, i64 3 + %9 = load ptr, ptr %8, align 8 + %10 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %6, 1 + %11 = alloca { ptr, ptr }, align 8 + %12 = getelementptr inbounds { ptr, ptr }, ptr %11, i32 0, i32 0 + store ptr %9, ptr %12, align 8 + %13 = getelementptr inbounds { ptr, ptr }, ptr %11, i32 0, i32 1 + store ptr %10, ptr %13, align 8 + %14 = load { ptr, ptr }, ptr %11, align 8 + %15 = extractvalue { ptr, ptr } %14, 1 + %16 = extractvalue { ptr, ptr } %14, 0 + %17 = call %"github.com/goplus/llgo/internal/runtime.String" %16(ptr %15) + call void @"github.com/goplus/llgo/internal/runtime.PrintIface"(%"github.com/goplus/llgo/internal/runtime.iface" %6) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %17) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret i32 0 +} + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) + +declare ptr @"github.com/goplus/llgo/internal/runtime.NewItab"(ptr, ptr) + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare void @"github.com/goplus/llgo/internal/runtime.PrintIface"(%"github.com/goplus/llgo/internal/runtime.iface") + +declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String") + +define void @"main.init$abi"() { +_llgo_0: + %0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0 + store ptr @1, ptr %1, align 8 + %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1 + store i64 1, ptr %2, align 4 + %3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8 + %4 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24) + %5 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 0 + store ptr @2, ptr %6, align 8 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %5, i32 0, i32 1 + store i64 0, ptr %7, align 4 + %8 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %5, align 8 + %9 = call %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String" %3, ptr %4, i64 0, %"github.com/goplus/llgo/internal/runtime.String" %8, i1 false) + %10 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %10, i32 0, i32 0 + store ptr @3, ptr %11, align 8 + %12 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %10, i32 0, i32 1 + store i64 4, ptr %12, align 4 + %13 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %10, align 8 + %14 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 56) + %15 = getelementptr %"github.com/goplus/llgo/internal/abi.StructField", ptr %14, i64 0 + store %"github.com/goplus/llgo/internal/abi.StructField" %9, ptr %15, align 8 + %16 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, i32 0, i32 0 + store ptr %14, ptr %17, align 8 + %18 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, i32 0, i32 1 + store i64 1, ptr %18, align 4 + %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, i32 0, i32 2 + store i64 1, ptr %19, align 4 + %20 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %16, align 8 + %21 = call ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String" %13, i64 16, %"github.com/goplus/llgo/internal/runtime.Slice" %20) + %22 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %23 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 0 + store ptr @4, ptr %23, align 8 + %24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %22, i32 0, i32 1 + store i64 4, ptr %24, align 4 + %25 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %22, align 8 + %26 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 0 + store ptr @5, ptr %27, align 8 + %28 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %26, i32 0, i32 1 + store i64 16, ptr %28, align 4 + %29 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %26, align 8 + %30 = call ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String" %25, %"github.com/goplus/llgo/internal/runtime.String" %29, ptr %21, { ptr, i64, i64 } zeroinitializer) + %31 = call ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr %30) + store ptr %31, ptr @"*main.errorString", align 8 + %32 = load ptr, ptr @"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU", align 8 + %33 = icmp eq ptr %32, null + br i1 %33, label %_llgo_1, label %_llgo_2 + +_llgo_1: ; preds = %_llgo_0 + %34 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %35 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %34, i32 0, i32 0 + store ptr @6, ptr %35, align 8 + %36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %34, i32 0, i32 1 + store i64 5, ptr %36, align 4 + %37 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %34, align 8 + %38 = load ptr, ptr @"_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to", align 8 + %39 = alloca %"github.com/goplus/llgo/internal/abi.Imethod", align 8 + %40 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Imethod", ptr %39, i32 0, i32 0 + store %"github.com/goplus/llgo/internal/runtime.String" %37, ptr %40, align 8 + %41 = getelementptr inbounds %"github.com/goplus/llgo/internal/abi.Imethod", ptr %39, i32 0, i32 1 + store ptr %38, ptr %41, align 8 + %42 = load %"github.com/goplus/llgo/internal/abi.Imethod", ptr %39, align 8 + %43 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 24) + %44 = getelementptr %"github.com/goplus/llgo/internal/abi.Imethod", ptr %43, i64 0 + store %"github.com/goplus/llgo/internal/abi.Imethod" %42, ptr %44, align 8 + %45 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 + %46 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %45, i32 0, i32 0 + store ptr %43, ptr %46, align 8 + %47 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %45, i32 0, i32 1 + store i64 1, ptr %47, align 4 + %48 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %45, i32 0, i32 2 + store i64 1, ptr %48, align 4 + %49 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %45, align 8 + %50 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %51 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %50, i32 0, i32 0 + store ptr @7, ptr %51, align 8 + %52 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %50, i32 0, i32 1 + store i64 4, ptr %52, align 4 + %53 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %50, align 8 + %54 = call ptr @"github.com/goplus/llgo/internal/runtime.Interface"(%"github.com/goplus/llgo/internal/runtime.String" %53, %"github.com/goplus/llgo/internal/runtime.Slice" %49) + store ptr %54, ptr @"_llgo_iface$Fh8eUJ-Gw4e6TYuajcFIOSCuqSPKAt5nS4ow7xeGXEU", align 8 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +declare ptr @"github.com/goplus/llgo/internal/runtime.Struct"(%"github.com/goplus/llgo/internal/runtime.String", i64, %"github.com/goplus/llgo/internal/runtime.Slice") + +declare %"github.com/goplus/llgo/internal/abi.StructField" @"github.com/goplus/llgo/internal/runtime.StructField"(%"github.com/goplus/llgo/internal/runtime.String", ptr, i64, %"github.com/goplus/llgo/internal/runtime.String", i1) + +declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) + +declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64) + +declare ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String", ptr, %"github.com/goplus/llgo/internal/runtime.Slice") + +declare ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr) + +declare ptr @"github.com/goplus/llgo/internal/runtime.Interface"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.Slice") diff --git a/cl/_testgo/struczero/out.ll b/cl/_testgo/struczero/out.ll index 8299781b..20514bcb 100644 --- a/cl/_testgo/struczero/out.ll +++ b/cl/_testgo/struczero/out.ll @@ -20,7 +20,7 @@ source_filename = "main" @3 = private unnamed_addr constant [2 x i8] c"F\00", align 1 @4 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 @5 = private unnamed_addr constant [5 x i8] c"main\00", align 1 -@6 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@6 = private unnamed_addr constant [39 x i8] c"github.com/goplus/llgo/cl/internal/foo\00", align 1 @7 = private unnamed_addr constant [43 x i8] c"github.com/goplus/llgo/cl/internal/foo.Foo\00", align 1 @8 = private unnamed_addr constant [3 x i8] c"pb\00", align 1 @9 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 @@ -257,7 +257,7 @@ _llgo_1: ; preds = %_llgo_0 %36 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 0 store ptr @6, ptr %36, align 8 %37 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 1 - store i64 4, ptr %37, align 4 + store i64 38, ptr %37, align 4 %38 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %35, align 8 %39 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %40 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %39, i32 0, i32 0 diff --git a/cl/_testrt/any/out.ll b/cl/_testrt/any/out.ll index 612c682e..50a3b9db 100644 --- a/cl/_testrt/any/out.ll +++ b/cl/_testrt/any/out.ll @@ -115,7 +115,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 %2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 3) - %3 = call ptr @"github.com/goplus/llgo/internal/runtime.Pointer"(ptr %2) + %3 = call ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr %2) store ptr %3, ptr @"*_llgo_int8", align 8 br label %_llgo_2 @@ -123,4 +123,4 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 ret void } -declare ptr @"github.com/goplus/llgo/internal/runtime.Pointer"(ptr) +declare ptr @"github.com/goplus/llgo/internal/runtime.PointerTo"(ptr) diff --git a/cl/compile.go b/cl/compile.go index 9db16bcb..f5708851 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -562,7 +562,7 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue o := p.compileValue(b, cv) fn := b.Imethod(o, v.Call.Method) args := p.compileValues(b, v.Call.Args, fnNormal) - b.Call(fn, args...) + ret = b.Call(fn, args...) break } kind := p.funcKind(cv) diff --git a/ssa/cl_test.go b/ssa/cl_test.go index 488a36bc..513944c1 100644 --- a/ssa/cl_test.go +++ b/ssa/cl_test.go @@ -26,7 +26,7 @@ import ( ) func TestFromTestgo(t *testing.T) { - cltest.FromDir(t, "errors", "../cl/_testgo", false) + cltest.FromDir(t, "", "../cl/_testgo", false) } func TestFromTestpy(t *testing.T) { From cdb1cf1b637b3909339a29f66faf4acbb805bf84 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 27 May 2024 11:21:22 +0800 Subject: [PATCH 6/7] runtime --- internal/abi/llgo_autogen.lla | Bin 3353 -> 3353 bytes internal/runtime/llgo_autogen.lla | Bin 11825 -> 12810 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/internal/abi/llgo_autogen.lla b/internal/abi/llgo_autogen.lla index 2eb6053511a49bb313d97512712d91116676dc0d..fefd48723d89c6558412e0b71ba38072952c3ffa 100644 GIT binary patch delta 49 zcmbO!HB*W=z?+#xgn@y9gJD+G?uopr>>_`H)5QJ+Z?tUWVFn6K-pgam3>2IEnMVx( DQrZu% delta 49 zcmbO!HB*W=z?+#xgn@y9gW*r-u8F*=?5F<*rJem7w9&GWhZ!g|c`uJKGf-^uXC5^G DmeLaR diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index 6b78845551b7b49e62343c1d21c6b722bb3c9053..349f274ce7acc5eadfa16dbf5eb12a53d8c81020 100644 GIT binary patch literal 12810 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 C5Tx}0 literal 11825 zcmZ{qV{;`8(57SC$;7s;iEZ1q?MZUtNlt9r*2K20iFq=yvCqEyZMU|%`tGi-uKodi zUn=sDP*`AKU~piT30*pMXiX)7OkiM6b>LvAV1!@}4%W`brk)%KF;v6JwRqc~%-T)ok>cHUpotAgl@XM6+Nw z=Kg`_#3IJX)MMLL z4JZqI-stzvH#B4d2)`dVkA3>Rf9Y<0+%B0nzj)sIZ0|9yO7^~-MrmceuQ(p^EPioR zCG|P3no@vdB2ld$ojwmP%R!)LM@TL4A)_Of*1*EBZ;lS}dJe9?Pb6Vm!Sv7HPn+9O zbHzONFN;mLJwY}JBwpUds}!~3Pp|@LbX%;ZamC7;^YA^Py8YR%YhjNc&yMf+LrwyI zRKLDf8c)XDmRk)-wEvN7>*xI=xf>aKGWlK)61!4Q`sTe}ya(@f>Ql_wgTuH5x#qiZ zjyaeJ^pJDRT?JaQ;wZ`; zdP_fH*)cy%H%ef#4-VL_4>lsoeqx~R-0m^l*#Y6UcZ2pjHi`B5RS|)W9f565#%~?# zLPWUT?;}C2fqNg`X|4KyHf#2ranCNO_;(0LyE+~3gFFqsw;54LR-ea4E=<>y`t8wC z@d_Mn(yjW;rKQy3Rr7`7n_S#E(dEZ2)^{DUo%ENus(kt~jryT{g^1UFZK;mff+-&=I65QX#Kf4K? z9NT|Kq43^y2EAvm@O-^P&US1(TDpkC5ZW|52M6@@JpaIR$xwtemLR}$aZ-ewnmH-n z>#rzY<90daVf}lhEB|uVCwy`A`L|E#;wcsC(MsU zhtCwk6szMga6o=O-Fb7G_CW<$1qaOVj(NvDwoyp$_wRvlKQ6OJtRCw&7}E}Tjy~h- zkL1skV+X$9+n@S5y#Zb)O{ogCSjKrPSm!D^g>p>i?cOKgk4@u=(gvu z&vMYQ%Qom(cH&5U9UnT=A4}$UST3r@1R#n)a#m`<=E17HOa6Q*3rn-yQ*iO&ZsUHS z0fPeNpyv{|ew}14@Ap5K%zH#FUR(zk27_ztbb{E(Nn7NNBY5mJza?sgs7WEZT%pRc z?H{4re4u4CSgqEnG2O@QEK4$ys$5Z*O1oKAQg5tM{*z1rB+jqhm)xwAmr8uu(!Ra+ z+Q6xo>x^a=@C~nzs{$d%=b4MAp^Kd|RSSZ0pzUbrx`x{89FLmy`w#UE;pPGfobVt- zM!4cR#xoAYx9PC|MtiV`Z%Q9j&g~XlnAcEUynBOvG+E8-0W<*;8%SIg=3M0%lZ$ zf`_`Z#G($+oB{*o0t^`vRYE71X786&HV_4^Xt`$`*TZI~9lZO+pA7X4akglol!W-QtN_ytj>C#A z@(*7rcCJ^9gE}txD`QS_K^VQv)0ca@d(I1k?AtSnv~{d5whvK~(We|{E_ENDO`E~0 z2(3q(1+`wwBp2bFU;1`HVxAq{H{pNpl%~Yzhnw(DaLc5XnB9;mo)riVdNJvwM=FRZ z;ejZ*Rv5NOW#?*=4rLQI7PWb9mE>|jK;&$4*er*)AFacQbD6B;b>ERNj)+BwfC1r_ zvGa(e{H zQOG!2bDzUZlVb_CH#Wnj5QZ)V*W9|8t-G(g#~}B~DOl7+7jA;}bv1sAfXd7C!cj2* z6$tjr%Q|-_szN=L%VxIs<<~J~XZ9YP_LWlCY0!|_&ZMve;w7X?CnR_y_XF}U*KgY` z_&OpfF_A0ez{CDq*TiX}F{oeS^VPLICTOz*zv;lSq@tzbHtdkn!F&b8B=Pq67BXVO zZ8qtmQN?&Ev0TEy7_;NklV#P!xU~j2sb|B}`lNZ-1D5)1zXtZm)L1Biv|4t!h>xLF zsHI=B>on|Wp<&8=(k_Ft2`sM2DJhu@Q1sHPTv1iC6hk|aa}qu5@M&s`<`|?7r~$&9 z>+C61@LX0Uh84C=+sj)KrseQIPVmkd=|mT-3Gnt{nucF)3^7N?i~lfEQ^?eB;BMb= z-g+pLGB#GTV%sKtEyI~QGARk@*a~0Ee=GB-Yb7yvu#MJ`Zqvy#FgY_3#_8xk1Kd$Ig0JEs=t`-Gz>dD2Uh1-+W!+>W|Cf$dEf~R3d(BC+j@)GndWA1A*W{>l+tqb9{Z>qOyq0xqY&xm4Eq%uFlVdsmxiZ{XqwA#4f_RN1oM2EExl@d( z3KJz}nZGnD3_MW)qc5hjD~56>59Sn&OMDsQ8d+aW49v^W=Y}vrIWS3nllvm;#ntT$ z!^=FqA+1DTivz;#*s=HR+_sgk7>>+T+==X?BiZX9EufK*H0`(p&yIgqJ;Be{d{cc@ zW=IUFyC3*VrKXP_8g}1H`hF6Z)(5b0{Kwk?XBq^M(Z4dVR{COYJAyj^1gre}CsvE7 zsEcdfi8uy%X((s04HKgIdtFONfC69R-kWa|Hg~PN#xsoLoMMpekOfQjNaKJxuturjMEbh6p*mSGc< z7wRL-N?^{iEd&P7diewP8c+H>!CWj(cfPu(7i>2?MqiEB(?Zr$uZV--+a39Onf`;a znawmgR<>H&5+nP7V~F*@y$%$6xhU9S_}Huk zg9^SXh?hO2KV%7UzYFBPt%@{c`8_+3uBMwtD>I&10)B!Y{Zpp(4oyPyMD z?bp+`aPZ?r^p(&*`41hCI&4QJzn_x>(Ecf}ealD?u;0m^6I(W9A19e!%$s;JXNWyw*)heDkJWKVf7dH-0{ zY%b6O^T=c=9ulbSl|NXkR4n~-?j3TW>pwe<~}q#34lx2WEngr^NsheHJSygCag>k*S! z^5Q!^aBycp&k*Jdl!}F%yVY4y4f`5Xe8+yX1B43*oexI;jzyJ;oaezg|H3*ZS4wna zX(mw*kX)>D1dN;7LnOPQGpWo>jofYkJCEXJ10}|GpC`PQeKiD)j?t(@pZ&2b0u9~$ zxnylxCWM&PKX^(cP7LqA{kGhvv8ycvd(YuZl&TfB_c@TwF|^?Y1=uQ^bFA(iQ%{K$ z`8gPHZfI0J>RkDe&Jtb_Fr@AtOU%kDy=yzVBi2L_42sF5H*DHI(m*Yv@Cw*CtvsWxttVoAcV#oQm%~k zuLwW8#NU{Z{-Z#3SC>1f$5(rW9VmrFEuwEZ{Az0v^D0K7cvB_yJ>ut`*~4>IgR(|6B#23$8=Ppib=O!BY-Yv}#H2}tZ+e)t(A!uVZ`uQ!%S zRuAct0lFA-%jFdA;C1|GFNLo@N3weC*Re7Un~S2!luwjfvO+}8`LSU5k}h@iq;__9 znSThf-8AT~SS|C&|IRuWOeW`xXmrM2mY6@fa(7ugZ^ z-;vi;u!tP*>s9Tj5rF%g;=;|7Dcuba=dU4|0|R?Tq3l&}1d7=% z=+O?lnm*aVw3Mv5gG!}7PhAWyiDbr%QpsMj+O#JU>~oGMrD!zGP6&37@(i&#mF*ZT zacqUUn`xQ3V-Zx4-n)b{YR}x-{r%c)`NOOIVPt-`5}lPhNw67N^7G~sb10^PaMw%8 z-!Lp^yTXRC7@}iX_OCw|j0UeHN59uT*qU*co@pOGSM7K~fTRz99M$uG47h#6iP`xN z^~*bt>TIddQMwZ4K$4crl^a8rmAdxwm7K3}aG9oJG^*{9YZV_btC@bumbftr=Y<1+ z*E0`*I;w|j0z`}2qq(*{#t@*6rNE5CB0F5kByEm{2(25XhyE3&O==XPW!FD$TeXyK z#cC5ORe&@3{#`mA@Pk>AAp73ayR4 zLxb4q?mgayv($~{$6^K7Er$f>;MFoxq&F79E~vH%Q~OP1{tw0ZI>R%4kwtg+KX!N+ z{BkPG3p@uF8wWWjX|?q^0bs(+-S!zU$((2Pp1c7;3Bn^z!-vm@0U5~7(Sg?zL1ro? zlfh`JBm%UYuD-j2nff}T7_X>|&1QU$+}~t;FPTbW#gXsy|Ni~?w$7WnpmCL~Rw&nB z{Pp~3`JkVZJMU~geKu(Pa(`&voSTB90BidKZvwQtdZbM)uzWH}nQS1alk>unCFbbB zkm(vJ$RW*KN7xRRbNRwZC2fPM6&R$iNHUA?lo{Vf<0S358)mJM7@!WI0MhE5h95l+ zAxZI{f;HNQx5J!moDY>CM+r>mM`I*9^N|^L_yH$iAqh^EnWp=rO5kme+h@iOLp_71 zCc7`7u}LJf6zZ_f9}pGHn}CIse*6NRX0N?YmRRB-Y8d!M(;0K3dpn|mQ{uCGZ&ukv zvsaB1LO=tw^pWrtLeRP_mGNcrym}-ILvpCh!}u>Z4@8}I6+Y|pLf?+S56YQ|2o~gV zi&}LE?@&JUy8W6g4obRc2X=T#B^LQ;xGH#_jo3ujHkmQM3L$dUUw;{KbPDjYzdV~E z8wMq+%37AUYx=2i_>D|l$d@^^2wxco$0S}hEdN9m{GEi?B>kD{v{zGhN>vxJ*l zI97=vP3g|=E6MVk-&ctUjR_BW#W>b@f!O#xxNP&ubQreR7FAc%ezS__F2-wKD-C>h zVbV^7)cbd@H{$(AGbfi&t$On`)ah_>nsp)jQp;rv5P*<2(+Ix#B7CWk_wz}{2qIiC zefQ;2$@DfQF^#Y!s&cFTw)rQ4iq$V&ly^qJ=Xc5wVZYIYnW5fYfC$9eQzBe%2nX`) zzBxW7B<#iR{S+l_*!R0|@bac7Q=`%3+bTQ@~ZQeZRz!B`n%;c;lX{DO-S1rUXuI;UMa+e%jkCV`_x@aVJ)PAuWGKs-3 z_qr9%Y5-@UdTPz94>5Hlg#l8x0}=qAQ!-PQA%a>sRSdIE$2Ts5QnFT+NhKR2o6`ur zg_l9<^)cwVziF3HSo$$8{^GTkS~Op1-MT}d?66pi*D6^ZS{y8J8Hgz%a@1M#S3)(T zA{_HQmV6_yCxDwnX4n*A8BYa0R)Ale{0xrsB)tW;B8M7e)+~V#Ve48PF<_wR{Ux|X zcR&{aR+!{a8!8b~KNke;IxN0a|8eXl2OGOG5Y`HGS!iWAFai>{LELv9=lsiSW9%l8 z?|kl#A;?7d*vLyQii9fhp4n~#Y+H#ifRJy08tnc5Lik zUuOyRnI1-5$xVCFG1YN^!5XgcqeEz z{ALzEV5ywUOCsYW`Tf2Ex;UVv+_srNot*z&H8E}?!@-?z0WjQao4TH-A*G>AcIQt}(jcJNJeaSRoDe4N7 zTJkWiNK=BTmNZ}HJJA&9Uv5q+1oa4htD+90+Z3^ON9l>)jV-`4AD#;XOCt&foE~uX zz$y+Ido8jpiDut2k`MuVCBwbaM|nQWOwIH9Ecad*`1+6Bi-Z`7|hI!$KPo?qKH&(S##UC2zXY#%e!bWptyQ2d7HtMo;#5-0 zytcSa{7V#WYlm5iy#4Xc^qWJ#OW$jIgb69?t$wmtiSTS}=dEEYhGgV)6QCq+sk^fOe<-VI5@vG z1+|5iP&KOXHcSQHk70b=^h*w=@q8Z@EbksD*M(z~XmJC-d#E_nu9vwJR+PwZLiby~ zlLPnZk>LzP8s8zyFlMV;m{?1uSh~BO6o)iH3}Pb^S<2841&pr_6A9a@)MO4QG@H;N zx464S{pXUPMQoe~Sv-&}V?=f1bkKs@N6$lny|rH2QX0$~yS1J{oHsUGp2tYjoJrqP z?CdkuYBWDp!`_bc#9g3S#!s6Nv*VR-yk zQD3a>!p{$JGtE$vZVWWsZn4za?acj1Io5ZliLSFZ{#o^tvZ0nxqLan&nAr2!WGtSPNxpt9nJ<~!$u45*vUt5GnY>d%mGlMHP)=lSvH%qu#Jxn#*_xjY z)?A{f)Yy2k4d>CMfPLC0r;BNp$)Sp47~EX3C{H5}ArO<|ESQ*J5r276Vpu`JJx<)- z6a#Rdn-Uk+;>+8J{$VWN@o@VOmHQP2f4=CUQ1H)1{-mr`nsiQ-3=!3Ku?j;&6_E<< zhyWAwoLG+(FU|oa{=P^TGyqb)B!jUFF;8?Z&jkbiR8E4__CcmK=5EY^l|0DU(?eiW ziMeH>B1 zT*>f9@7}30%n8}!vJwbaRlWZl#60}Tm2-F-7*+5|RY)Ad(xoqOhHLb`u>`1b9KQO% z&<&brUb#@3W9i#;YrBe4%HK|2DM>Cb&$TFf0p0%@3S($9Fex@tHWSVvHrzDP)K@}$ z{yh)ildgCOCsJW-MNhF}Dw0^L`&z%$r6$wxDtRAt*gE>{;LS=oJ4zOJeM;TtA2NSc z)y#=#nM1Jv`!;E``x}$g8C_sajjh8^cX|D9R)!8m_%ZeIIjoB&Y>K6&IK%K_kzEBz zP-YhXkb6u2u`P!6x$EDpMY+@uvW^hqlMBY&pHM4EmW3Y=SPT=}Too5-t)7VDX#FaE zjn&H;;^@3$MhCe&X4{tOpf70s*xa2I)%BuQalwpu=#KFO(N%TM?HN?K=)R=vg(9S< z8E&(}K&Eu^kuuvxMjIN@E>Y{gY@ldF_#dkV^xojF%~~B8;EHBcZ^RpqBo(Hh33zA$ zrY37p*soTa9$G+yjp|V!n3<`;W;Fr>XAYs$`5}FjhK`Fh>K}a?6zP==s@pl?G=b$f z+7%0ZT_d~-4eLvh$ssIwh9G2|%No6;BO8gD3b(^fks2L0%smlCXIKV>LAnOL|gDooEl#5GdOd z??cQ?VW;v!M7Ww@7*h-*+4_1yH#g2417^XRF1M>fQYhFmq_`)Hup*(rRQ_BYp+i$c z=p)!v=FiH&x1oB$CZdavM|kZ9FxNO)Z=5^rnl=4#6i80nF_#9j^;QUzrken?%&}SA zg#Z$41&d_d=rjfZS<8#)Fn_L>@Fjid(YIkpxFT6eU}S$=6RbA3z9gs?2~xN5$M__X zpVpQ@V=RarvxLa4g+c#4QI*Z7V{3m%%I~3t=T|Z-F`1VQz{~z%j_@<|*x7sze8F`= zCx5Yg$)p+!_9I?U2VE=&n`~JReUUgpOyU*$DW(Ngmtj!Lw>`btLLoDXs!}kLAN^NQw{Y`vOrMAkWB=$4F`FG9g=bBrTD z1sMdgm#`XU!HflnXnlU8gV(Fo>-?OFjFg>1{3MA`NhY_LR zY-EkpLCEY-9&f>9XvGy}R(Qub_mAbNK0vJ^W?P=N2oFNLvkI!bM^Mq2LS|Aa(%V%U zMo5_bWq6(B%X1GZ*$%zEYg#_v%+oSxJ8o$1U z$ixC-%#)>roIJ%yBGEHb6^J?sO}bxVvxRIiPQ!Kn6qJ{`#j-EChY4TIy8Bm_7Af!O z8lOjBYcohT54RxjXUD7+Li#8i#ON2tY1M6KFA&QrF1>GcM%zG@i>2^1SepDq zMv;rv$yATch}->=mxr+)eq0-}yca|Ermw2=rw;D1eQ;$jX442L2k&5c!YJ!ld^BzZ zWKSk{h*qwZp^Hly20kNrt;;VkQZms3=EKw$Ar=B<5as5&^z;}sar{c@{Yy6iHK|p# zm1zpa^byX{*~w}RHI}93ODQ(79Mo1VGdgLTU{z1>ZTmJ99-}v6hz%HOI~9=?Kd{@L zN)T4!CpCHKyP^=#SH$`l8u!4MXhUW5oi#_D7G?iuk@}j_a0V4dKQR4C%OBL0I_IQClP@f ztKu@2j>(h!l&P)q^p_%`Re{h|C>O&pbTN-Hr8X*UGa)iPv?Mi(sjUlTXLOEoBehz( zzqu_h&`NF81!dfI^~rJu1r_M57(fki{5RLPYyu8y=cP8HW`UQRBv{6hdcf_)=?it+ z>KeAv3j8KNc^Fx974GoymcUIBKOA6Y8_`?}F6j`+9@JAwz8R@H!G(zw!&E z*nmoO8c8^gD84vwuWvmU13^iZFDgoZoRrNh1sObgOE@<-{zzc@PdFeG8LQoSn^Eqz z2lv52d<2e9$MxMoUMpM`E;l?jX_^?-@+G+z8GRqEiOf7)j0}ZLJ4Sq5Djt2YflUm> zX*#cYt=wZ30Bbm9T(xvb!40-S&VRsdN{NfVoEQ$H3ru9Ens75m&kFra#4uwaYNnhh zJ=7v@_5iuBF1k*|=<<)Ehtpx>(rBYhO=FifyG^?!G&n%P9VavJP@=-&nr%!*Pb9OV z!wnkIqa~#(*Aj}u98aS25Cy;Iw7Lyz8ApJ?EAs=4Nkmnm_1hKSAXUDKM$pl3A5(4+ z6?xS)1i186rr7Z<^r$16Wzi4WZ)>JX#0_nY+tQg6sk?lYVq$2f{o$5Re!<`es$8o? zMs2|QdXX$!zKFIR!$OylEZQ8ey^p%zv7TCxzutE_AnS7G_ej~U&2{FH#is$L3^0;cro#ldU975xe) zwS&}+k_soifEQgJYg)G-n1nXbqL~)~PJ6P~lF=p?{K|mx%z%n#g}-2fzu(ra)7 zuULWSO~hi#P>IIH`lSjZ5fzF*sm>~17yv7qPtu^oC84%#%~*0Ys6na1FGS+bz2nN9kOIg#MRefec~_YxG>R zpXi9)RKoz%u;5^~lEjeI2P*uMukVo+yG?OPUaFE)bKL_D2Z4;-0i?vTI=lkwck|310HnpfuYNR^- zBw1nac?X6W&&|i3)Ad+77n+^h6-XbdK`c&bE~8jpS>t+XTf1|=EymjS>A2cgcj5*>45c&<)sV4u*tYSeKxi;j)Vb5K*u zzlaH}wW9+5%78y;B1=r6F43rSP*pO#ryfg+xy2T0GX{lH-@$>sLaX-2<4@*^ zc#emR<7_LJ`c^&{<+xs%TnyY_LRx8IQ7tR>SoY&y6yB(g2hTR zQJGkSb1pf-7MXVK zc^)lRU5P1`7Zs$~Y43C(lSEO1kPI^xz(@|%j*N0~kXA+X;&DsJRS7{r)dS(F{S7U` zGcTYA!HyJ4R|}{s%~aC#s+r9!rx{nK8QYTfsVNE37JSG7#_Kuh`_zbDK%>En9b#%e z2=J|(z(MW+tj+6zT#8(1+He4=h>>e6n51%=W^qCiULUQ-WInk!5uR;%*K0!jzSzq6WOEB$0XCYfIA){;aoGlMc(iJZ8zws~_+og*WDHygxePw8{L2*TELgyw{1Eu)^taFO*Dubp&NkiO@{@Y7l z35HGgDu!o~XQj_|(B((Jvh9sK{g()TUX7Oea}V}6{1L4uksu*jjaKE$)zrV&6c~HW zfC}3ED2l!Zy8p|TtzP|v(&l^&>3&R%ZQQz}ZepMsuamiyoaNiXkcx~?jm@BdC*>*6 z*rYPnS?OpkuguLB+0tvt)~vnr>R8~|7MU~xF-u{LLF>Ao<3^`XE0&$Jt(G!%=>c;7Hj64I9iI2V69J|Gf0y*aCX>vhXpY(}}NiOU7^0iS`UF zRwr^gynMA*^-&QmI}0Q*o`6CkhV1+!$WC^#D)rND%Lt?SU22_(Znaf$TU6Q=>pOE=heIJSp}vOw){!2=*VJhMlel(M05Cka2Fg z|MtRXrj;^(*VyT~@V_(RpUTebq3a+S~ZHIbH_~J!@1+i8o?M8ZwX}P9T)~i(?2z0hj9+ z`ZTo20SsvdLkML*v^%^-Cl{1EvV(s-`{OgZb#0IG8Qb#spGiX+O7W;(SM5EEuU=X0 zJsJt}sNVa!-t&*ZrMg~aI0&>rT*JWh`)5P1$3QWt@U!lVi|)L>e_hqiDY>B?7P&q7 zzgj#OxjkSGBKa$S@I(5F=RP3khV~aKApmAY4peC31xi6754*C*^Z4V0UfRMkQqbnS z-Ug85y#mEZHkU)yfU(1JEvPE~kKCLnR|e}JJd#RY_#~hx%{Z&bX75$ylFD2PL*fV*>qdZ9_)B-!6w^o?_DH zCMqi`&JSfo!k&=g595%o)Mr`pb|ODfbD%P1@_`~QzSqTZ%w-jGSrv_XrlZc(_#c@& zToIbPN}Q1TO{u<3p&;P9rXqhtt2MVtY`N!1_DC!)OC2uDKa#ET-_HY;=_<;2=C0kk zl`fsIy=ifMM(=%Ri`zW>j+#fATVu+rA=}m+E&>WD=oo+`k(a919b^ajadx?;Tm6HW zj8=9}Ya zb9?>@8a=&l#wzmQ5X6xGKaLykKfW6b>_1Q&tR(b*cmEI74gG(p?*EJER*{E>`QPi{ Q|App%b@V?l91QG#0rq0k1poj5 From a6f92b8ff99d6a35ba135f07e6ddda9310da5ad4 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 27 May 2024 11:28:03 +0800 Subject: [PATCH 7/7] TestFromTestgo --- cl/compile_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cl/compile_test.go b/cl/compile_test.go index 2d601ae2..48639cf5 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -28,6 +28,10 @@ func testCompile(t *testing.T, src, expected string) { cltest.TestCompileEx(t, src, "foo.go", expected) } +func TestFromTestgo(t *testing.T) { + cltest.FromDir(t, "", "./_testgo", false) +} + func TestFromTestpy(t *testing.T) { cltest.FromDir(t, "", "./_testpy", false) }