diff --git a/cl/_testgo/errors/out.ll b/cl/_testgo/errors/out.ll index 930efb98..40e32fde 100644 --- a/cl/_testgo/errors/out.ll +++ b/cl/_testgo/errors/out.ll @@ -15,18 +15,19 @@ source_filename = "main" @__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 [9 x i8] c"Imethod:\00", align 1 @_llgo_main.errorString = global ptr null -@1 = private unnamed_addr constant [6 x i8] c"Error\00", align 1 +@2 = private unnamed_addr constant [6 x i8] c"Error\00", align 1 @"_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to" = linkonce global ptr null -@2 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@3 = private unnamed_addr constant [5 x i8] c"main\00", align 1 @"main.struct$QTufDJA9wEDzuzgkA-ZSrLqW-B6lWN8O25mTSglAoLQ" = global ptr null -@3 = private unnamed_addr constant [6 x i8] c"Error\00", align 1 +@4 = private unnamed_addr constant [6 x i8] c"Error\00", align 1 @"_llgo_func$8LHAAczeMU-_MsqDJ4-62jHfhzpiOiRnFkBoaL3mfxg" = linkonce global ptr null -@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 [2 x i8] c"s\00", align 1 -@7 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 -@8 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@5 = private unnamed_addr constant [5 x i8] c"main\00", align 1 +@6 = private unnamed_addr constant [17 x i8] c"main.errorString\00", align 1 +@7 = private unnamed_addr constant [2 x i8] c"s\00", align 1 +@8 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 +@9 = 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: @@ -91,10 +92,27 @@ _llgo_0: %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.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %17) + %15 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %16 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %15, i32 0, i32 0 + store ptr @1, ptr %16, align 8 + %17 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %15, i32 0, i32 1 + store i64 8, ptr %17, align 4 + %18 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %15, align 8 + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %18) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintPointer"(ptr %7) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + %19 = extractvalue { ptr, ptr } %14, 0 + call void @"github.com/goplus/llgo/internal/runtime.PrintPointer"(ptr %19) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 10) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 0) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %20 = extractvalue { ptr, ptr } %14, 1 + %21 = extractvalue { ptr, ptr } %14, 0 + %22 = call %"github.com/goplus/llgo/internal/runtime.String" %21(ptr %20) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %22) call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) ret i32 0 } @@ -111,6 +129,10 @@ 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") +declare void @"github.com/goplus/llgo/internal/runtime.PrintPointer"(ptr) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64) + define void @"main.init$abi"() { _llgo_0: call void @"main.init$abi2"() @@ -124,7 +146,7 @@ _llgo_0: _llgo_1: ; preds = %_llgo_0 %4 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 0 - store ptr @1, ptr %5, align 8 + store ptr @2, ptr %5, align 8 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %4, i32 0, i32 1 store i64 5, ptr %6, align 4 %7 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %4, align 8 @@ -148,7 +170,7 @@ _llgo_1: ; preds = %_llgo_0 %19 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %15, align 8 %20 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %21 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %20, i32 0, i32 0 - store ptr @2, ptr %21, align 8 + store ptr @3, ptr %21, align 8 %22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %20, i32 0, i32 1 store i64 4, ptr %22, align 4 %23 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %20, align 8 @@ -172,7 +194,7 @@ _llgo_0: %0 = load ptr, ptr @"main.struct$QTufDJA9wEDzuzgkA-ZSrLqW-B6lWN8O25mTSglAoLQ", align 8 %1 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %1, i32 0, i32 0 - store ptr @3, ptr %2, align 8 + store ptr @4, ptr %2, align 8 %3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %1, i32 0, i32 1 store i64 5, ptr %3, align 4 %4 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %1, align 8 @@ -200,17 +222,17 @@ _llgo_0: %18 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %14, align 8 %19 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %20 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %19, i32 0, i32 0 - store ptr @4, ptr %20, align 8 + store ptr @5, ptr %20, align 8 %21 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %19, i32 0, i32 1 store i64 4, ptr %21, align 4 %22 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %19, align 8 %23 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %24 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %23, i32 0, i32 0 - store ptr @5, ptr %24, align 8 + store ptr @6, ptr %24, align 8 %25 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %23, i32 0, i32 1 store i64 16, ptr %25, align 4 %26 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %23, align 8 - %27 = call ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String" %22, %"github.com/goplus/llgo/internal/runtime.String" %26, ptr %0, %"github.com/goplus/llgo/internal/runtime.Slice" %18) + %27 = call ptr @"github.com/goplus/llgo/internal/runtime.Named"(%"github.com/goplus/llgo/internal/runtime.String" %22, %"github.com/goplus/llgo/internal/runtime.String" %26, ptr %0, { ptr, i64, i64 } zeroinitializer, %"github.com/goplus/llgo/internal/runtime.Slice" %18) store ptr %27, ptr @_llgo_main.errorString, align 8 %28 = load ptr, ptr @"_llgo_func$zNDVRsWTIpUPKouNUS805RGX--IV9qVK8B31IZbg5to", align 8 %29 = icmp eq ptr %28, null @@ -246,7 +268,7 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 ret void } -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.Named"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String", ptr, %"github.com/goplus/llgo/internal/runtime.Slice", %"github.com/goplus/llgo/internal/runtime.Slice") declare ptr @"github.com/goplus/llgo/internal/runtime.Func"(%"github.com/goplus/llgo/internal/runtime.Slice", %"github.com/goplus/llgo/internal/runtime.Slice", i1) @@ -256,21 +278,21 @@ define void @"main.init$abi3"() { _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 @6, ptr %1, align 8 + store ptr @7, 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 @7, ptr %6, align 8 + store ptr @8, 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 @8, ptr %11, align 8 + store ptr @9, 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 diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index d723b748..d7e201b3 100644 Binary files a/internal/runtime/llgo_autogen.lla and b/internal/runtime/llgo_autogen.lla differ diff --git a/internal/runtime/z_face.go b/internal/runtime/z_face.go index eccb2039..4d1e374c 100644 --- a/internal/runtime/z_face.go +++ b/internal/runtime/z_face.go @@ -103,7 +103,7 @@ func hdrSizeOf(kind abi.Kind) uintptr { } // Named returns a named type. -func Named(pkgPath, name string, underlying *Type, methods []Method) *Type { +func Named(pkgPath, name string, underlying *Type, methods, ptrMethods []Method) *Type { tflag := underlying.TFlag if tflag&abi.TFlagUncommon != 0 { panic("runtime: underlying type is already named") @@ -121,6 +121,16 @@ func Named(pkgPath, name string, underlying *Type, methods []Method) *Type { return &ret.Type } + ret := newNamed(pkgPath, name, underlying, methods) + ret.PtrToThis_ = newNamed(pkgPath, "*"+name, newPointer(ret), ptrMethods) + return ret +} + +func newNamed(pkgPath, name string, underlying *Type, methods []Method) *Type { + tflag := underlying.TFlag + kind := underlying.Kind() + n := len(methods) + baseSize := hdrSizeOf(kind) extraSize := uintptr(0) if kind == abi.Func { @@ -164,6 +174,8 @@ func Named(pkgPath, name string, underlying *Type, methods []Method) *Type { data := (*abi.Method)(c.Advance(ptr, extraOff)) copy(unsafe.Slice(data, n), methods) + + println("==> Named:", pkgPath, name, ret, ret.Uncommon()) return ret } @@ -216,6 +228,7 @@ func NewItab(inter *InterfaceType, typ *Type) *Itab { ret.hash = typ.Hash u := typ.Uncommon() + println("==> NewItab Uncommon:", typ, u) if u == nil { ret.fun[0] = 0 } else { @@ -228,6 +241,7 @@ func NewItab(inter *InterfaceType, typ *Type) *Itab { break } *c.Advance(data, i) = uintptr(fn) + println("==> NewItab:", ret, i, fn) } } return ret @@ -238,6 +252,7 @@ func findMethod(mthds []abi.Method, im abi.Imethod) abi.Text { for _, m := range mthds { mName := m.Name_ if mName >= imName { + println("==> findMethod:", mName, imName, m.Mtyp_, im.Typ_, m.Ifn_) if mName == imName && m.Mtyp_ == im.Typ_ { println("==> findMethod", mName, m.Ifn_) return m.Ifn_ diff --git a/internal/runtime/z_type.go b/internal/runtime/z_type.go index 08c11b03..8d6f8261 100644 --- a/internal/runtime/z_type.go +++ b/internal/runtime/z_type.go @@ -116,20 +116,25 @@ func Struct(pkgPath string, size uintptr, fields ...abi.StructField) *Type { 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 + ret = newPointer(elem) elem.PtrToThis_ = ret } return ret } +func newPointer(elem *Type) *Type { + ptr := &abi.PtrType{ + Type: Type{ + Size_: unsafe.Sizeof(uintptr(0)), + Hash: uint32(abi.Pointer), // TODO(xsw): hash + Kind_: uint8(abi.Pointer), + }, + Elem: elem, + } + return &ptr.Type +} + +// SliceOf returns the slice type with element elem. func SliceOf(elem *Type) *Type { ret := &abi.SliceType{ Type: Type{ @@ -142,6 +147,7 @@ func SliceOf(elem *Type) *Type { return &ret.Type } +// ArrayOf returns the array type with element elem and length. func ArrayOf(length uintptr, elem *Type) *Type { ret := &abi.ArrayType{ Type: Type{ diff --git a/ssa/interface.go b/ssa/interface.go index f89a3edc..95c2f385 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -94,22 +94,48 @@ func (b Builder) abiImethodOf(m *types.Func) Expr { prog := b.Prog name := b.Str(m.Name()) typ := b.abiType(m.Type()) + tname, _ := b.Pkg.abi.TypeName(m.Type()) + log.Println("==> abiImethodOf:", m.Name(), m.Type(), tname) + b.Println(b.Str("==> abiImethodOf:"), typ) return b.aggregateValue(prog.rtType("Imethod"), name.impl, typ.impl) } // Method{name string, typ *FuncType, ifn, tfn abi.Text} -func (b Builder) abiMethodOf(m *types.Func) Expr { +func (b Builder) abiMethodOf(m *types.Func /*, bg Background = InGo */) (mthd, ptrMthd Expr) { prog := b.Prog - mName := m.Name() + mPkg, mName := m.Pkg(), m.Name() mSig := m.Type().(*types.Signature) - fullName := FuncName(m.Pkg(), mName, mSig.Recv()) - name := b.Str(mName) - fn := b.Pkg.NewFunc(fullName, mSig, InGo) - sig := fn.raw.Type.(*types.Signature) - sig = types.NewSignatureType(nil, nil, nil, sig.Params(), sig.Results(), sig.Variadic()) - typ := b.abiType(sig) - // TODO(xsw): ifn, tfn - return b.aggregateValue(prog.rtType("Method"), name.impl, typ.impl, fn.impl, fn.impl) + + name := b.Str(mName).impl + abiSigGo := types.NewSignatureType(nil, nil, nil, mSig.Params(), mSig.Results(), mSig.Variadic()) + abiSig := prog.FuncDecl(abiSigGo, InGo).raw.Type + abiTyp := b.abiType(abiSig) + tname, _ := b.Pkg.abi.TypeName(abiSig) + log.Println("==> abiMethodOf:", mName, abiSigGo, tname) + b.Println(b.Str("==> abiMethodOf:"), abiTyp) + abiTypImpl := abiTyp.impl + + recv := mSig.Recv() + recvType := recv.Type() + if _, ok := recvType.(*types.Pointer); ok { + ptrMthd, _ = b.abiMthd(mPkg, mName, mSig, name, abiTypImpl, llvm.Value{}) + return + } + ptrRecv := types.NewVar(0, nil, "", types.NewPointer(recvType)) + ptrSig := types.NewSignatureType(ptrRecv, nil, nil, mSig.Params(), mSig.Results(), mSig.Variadic()) + ptrMthd, ifn := b.abiMthd(mPkg, mName, ptrSig, name, abiTypImpl, llvm.Value{}) + mthd, _ = b.abiMthd(mPkg, mName, mSig, name, abiTypImpl, ifn) + return +} + +func (b Builder) abiMthd(mPkg *types.Package, mName string, mSig *types.Signature, name, abiTyp, ifn llvm.Value) (ret Expr, tfn llvm.Value) { + fullName := FuncName(mPkg, mName, mSig.Recv()) + tfn = b.Pkg.NewFunc(fullName, mSig, InGo).impl // TODO(xsw): use rawType to speed up + if ifn.IsNil() { + ifn = tfn + } + ret = b.aggregateValue(b.Prog.rtType("Method"), name, abiTyp, ifn, tfn) + return } // func Interface(pkgPath string, methods []abi.Imethod) @@ -129,10 +155,9 @@ func (b Builder) abiInterfaceOf(t *types.Interface) Expr { return b.Call(fn, b.Str(pkgPath), methodSlice) } -// func Named(pkgPath, name string, underlying *Type, methods []abi.Method) +// func Named(pkgPath, name string, underlying *Type, methods, ptrMethods []abi.Method) func (b Builder) abiNamedOf(t *types.Named) Expr { - tunder := t.Underlying() - under := b.abiType(tunder) + under := b.abiType(t.Underlying()) path := abi.PathOf(t.Obj().Pkg()) name := NameOf(t) prog := b.Prog @@ -140,19 +165,30 @@ func (b Builder) abiNamedOf(t *types.Named) Expr { var fn = pkg.rtFunc("Named") var tSlice = lastParamType(prog, fn) - var methods Expr - if _, ok := tunder.(*types.Interface); ok { + var n = t.NumMethods() + var methods, ptrMethods Expr + if n == 0 { methods = prog.Zero(tSlice) + ptrMethods = methods } else { - n := t.NumMethods() - mths := make([]Expr, n) + var mthds []Expr + var ptrMthds = make([]Expr, 0, n) for i := 0; i < n; i++ { m := t.Method(i) - mths[i] = b.abiMethodOf(m) + mthd, ptrMthd := b.abiMethodOf(m) + if !mthd.IsNil() { + mthds = append(mthds, mthd) + } + ptrMthds = append(ptrMthds, ptrMthd) } - methods = b.SliceLit(tSlice, mths...) + if len(mthds) > 0 { + methods = b.SliceLit(tSlice, mthds...) + } else { + methods = prog.Zero(tSlice) + } + ptrMethods = b.SliceLit(tSlice, ptrMthds...) } - return b.Call(fn, b.Str(path), b.Str(name), under, methods) + return b.Call(fn, b.Str(path), b.Str(name), under, methods, ptrMethods) } func (b Builder) abiPointerOf(t *types.Pointer) Expr { @@ -288,7 +324,9 @@ func (b Builder) Imethod(intf Expr, method *types.Func) Expr { itab := Expr{b.faceItab(impl), prog.VoidPtrPtr()} pfn := b.Advance(itab, prog.IntVal(uint64(i+3), prog.Int())) fn := b.Load(pfn) - return b.aggregateValue(tclosure, fn.impl, b.faceData(impl)) + ret := b.aggregateValue(tclosure, fn.impl, b.faceData(impl)) + b.Println(b.Str("Imethod:"), itab, ret, prog.Val(ret.kind), prog.Val(i)) + return ret } // -----------------------------------------------------------------------------