diff --git a/internal/abi/type.go b/internal/abi/type.go index dc1d8257..2c866238 100644 --- a/internal/abi/type.go +++ b/internal/abi/type.go @@ -134,6 +134,12 @@ const ( // TFlagRegularMemory means that equal and hash functions can treat // this type as a single region of t.size bytes. TFlagRegularMemory TFlag = 1 << 3 + + // TFlagVariadic means a funcType with variadic parameters + TFlagVariadic TFlag = 1 << 4 + + // TFlagUninited means this type is not fully initialized. + TFlagUninited TFlag = 1 << 7 ) // ----------------------------------------------------------------------------- @@ -186,35 +192,15 @@ type ChanType struct { } // funcType represents a function type. -// -// A *Type for each in and out parameter is stored in an array that -// directly follows the funcType (and possibly its uncommonType). So -// a function type with one method, one input, and one output is: -// -// struct { -// funcType -// uncommonType -// [2]*rtype // [0] is in, [1] is out -// } type FuncType struct { Type - InCount uint16 - OutCount uint16 // top bit is set if last input parameter is ... -} - -// In returns the number of input parameters of a function type. -func (p *FuncType) In() int { - return int(p.InCount) -} - -// Out returns the number of output results of a function type. -func (p *FuncType) Out() int { - return int(p.OutCount &^ (1 << 15)) + In []*Type + Out []*Type } // Variadic reports whether the function type is variadic. func (p *FuncType) Variadic() bool { - return p.OutCount&(1<<15) != 0 + return p.TFlag&TFlagVariadic != 0 } type StructField struct { @@ -304,6 +290,14 @@ func (t *Type) Align() int { return int(t.Align_) } func (t *Type) FieldAlign() int { return int(t.FieldAlign_) } +// Name returns the name of type t. +func (t *Type) Name() string { + if t.TFlag&TFlagExtraStar != 0 { + return "*" + t.Str_ + } + return t.Str_ +} + func (t *Type) Common() *Type { return t } diff --git a/internal/runtime/z_face.go b/internal/runtime/z_face.go index 4d1e374c..ededb30b 100644 --- a/internal/runtime/z_face.go +++ b/internal/runtime/z_face.go @@ -102,56 +102,50 @@ func hdrSizeOf(kind abi.Kind) uintptr { return typeHdrSize } -// Named returns a named type. -func Named(pkgPath, name string, underlying *Type, methods, ptrMethods []Method) *Type { +// NewNamed returns an uninitialized named type. +func NewNamed(kind abi.Kind, methods, ptrMethods int) *Type { + ret := newUninitedNamed(kind, methods) + ret.PtrToThis_ = newUninitedNamed(abi.Pointer, ptrMethods) + return ret +} + +// InitNamed initializes an uninitialized named type. +func InitNamed(ret *Type, pkgPath, name string, underlying *Type, methods, ptrMethods []Method) { + ptr := ret.PtrToThis_ + doInitNamed(ret, pkgPath, name, underlying, methods) + doInitNamed(ptr, pkgPath, name, newPointer(ret), ptrMethods) + ret.PtrToThis_ = ptr + ptr.TFlag |= abi.TFlagExtraStar +} + +func newUninitedNamed(kind abi.Kind, methods int) *Type { + size := hdrSizeOf(kind) + uncommonTypeHdrSize + uintptr(methods)*methodSize + ret := (*Type)(AllocU(size)) + ret.Kind_ = uint8(kind) + ret.TFlag = abi.TFlagUninited + return ret +} + +func doInitNamed(ret *Type, pkgPath, name string, underlying *Type, methods []Method) { 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 + kind := abi.Kind(ret.Kind_) + if ret.TFlag != abi.TFlagUninited || kind != underlying.Kind() { + panic("initNamed: unexpected named 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) - + ptr := unsafe.Pointer(ret) 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.TFlag = tflag | abi.TFlagNamed | abi.TFlagUncommon ret.Str_ = name - xcount := 0 + n := len(methods) + xcount := uint16(0) for _, m := range methods { if !m.Exported() { break @@ -161,54 +155,42 @@ func newNamed(pkgPath, name string, underlying *Type, methods []Method) *Type { uncommon := (*abi.UncommonType)(c.Advance(ptr, int(baseSize))) uncommon.PkgPath_ = pkgPath uncommon.Mcount = uint16(n) - uncommon.Xcount = uint16(xcount) - uncommon.Moff = uint32(uncommonTypeHdrSize + extraSize) + uncommon.Xcount = xcount + uncommon.Moff = uint32(uncommonTypeHdrSize) 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) - println("==> Named:", pkgPath, name, ret, ret.Uncommon()) - return ret + println("==> InitNamed:", pkgPath, name, ret, ret.Uncommon()) } // Func returns a function type. func Func(in, out []*Type, variadic bool) *FuncType { - n := len(in) + len(out) - ptr := AllocU(funcTypeHdrSize + uintptr(n)*pointerSize) - c.Memset(ptr, 0, funcTypeHdrSize) - - ret := (*abi.FuncType)(ptr) - ret.Size_ = pointerSize - ret.Hash = uint32(abi.Func) // TODO(xsw): hash - ret.Kind_ = uint8(abi.Func) - ret.InCount = uint16(len(in)) - ret.OutCount = uint16(len(out)) - if variadic { - ret.OutCount |= 1 << 15 + ret := &FuncType{ + Type: Type{ + Size_: unsafe.Sizeof(uintptr(0)), + Hash: uint32(abi.Func), // TODO(xsw): hash + Kind_: uint8(abi.Func), + }, + In: in, + Out: out, + } + if variadic { + ret.TFlag |= abi.TFlagVariadic } - - data := (**Type)(c.Advance(ptr, int(funcTypeHdrSize))) - params := unsafe.Slice(data, n) - copy(params, in) - copy(params[len(in):], out) return ret } // Interface returns an interface type. -func Interface(pkgPath string, methods []Imethod) *InterfaceType { +// Don't call NewNamed for named interface type. +func Interface(pkgPath, name string, methods []Imethod) *InterfaceType { ret := &abi.InterfaceType{ Type: Type{ Size_: unsafe.Sizeof(eface{}), Hash: uint32(abi.Interface), // TODO(xsw): hash Kind_: uint8(abi.Interface), + Str_: name, }, PkgPath_: pkgPath, Methods: methods, diff --git a/ssa/abi/abi.go b/ssa/abi/abi.go index 6d6fd74f..4289d6bd 100644 --- a/ssa/abi/abi.go +++ b/ssa/abi/abi.go @@ -40,19 +40,43 @@ func BasicKind(t *types.Basic) abi.Kind { return abi.Kind(kind) } +func UnderlyingKind(t types.Type) abi.Kind { + switch t := t.(type) { + case *types.Basic: + return BasicKind(t) + case *types.Pointer: + return abi.Pointer + case *types.Slice: + return abi.Slice + case *types.Signature: + return abi.Func + case *types.Interface: + return abi.Interface + case *types.Struct: + return abi.Struct + case *types.Map: + return abi.Map + case *types.Array: + return abi.Array + case *types.Chan: + return abi.Chan + } + panic("todo") +} + // ----------------------------------------------------------------------------- -type Kind int +type DataKind int const ( - Invalid Kind = iota - Indirect // allocate memory for the value - Pointer // store a pointer value directly in the interface value - Integer // store a integer value directly in the interface value - BitCast // store other value (need bitcast) directly in the interface value + Invalid DataKind = iota + Indirect // allocate memory for the value + Pointer // store a pointer value directly in the interface value + Integer // store a integer value directly in the interface value + BitCast // store other value (need bitcast) directly in the interface value ) -func KindOf(raw types.Type, lvl int, is32Bits bool) (Kind, types.Type, int) { +func DataKindOf(raw types.Type, lvl int, is32Bits bool) (DataKind, types.Type, int) { switch t := raw.Underlying().(type) { case *types.Basic: kind := t.Kind() @@ -76,12 +100,12 @@ func KindOf(raw types.Type, lvl int, is32Bits bool) (Kind, types.Type, int) { return Pointer, raw, lvl case *types.Struct: if t.NumFields() == 1 { - return KindOf(t.Field(0).Type(), lvl+1, is32Bits) + return DataKindOf(t.Field(0).Type(), lvl+1, is32Bits) } case *types.Interface, *types.Slice: case *types.Array: if t.Len() == 1 { - return KindOf(t.Elem(), lvl+1, is32Bits) + return DataKindOf(t.Elem(), lvl+1, is32Bits) } default: panic("unkown type") diff --git a/ssa/abitype.go b/ssa/abitype.go index a2254b18..ab52e6d9 100644 --- a/ssa/abitype.go +++ b/ssa/abitype.go @@ -29,13 +29,15 @@ import ( // ----------------------------------------------------------------------------- // abiBasic returns the abi type of the specified basic kind. -func (b Builder) abiBasic(t *types.Basic) Expr { +func (b Builder) abiBasic(t *types.Basic) func() Expr { /* TODO(xsw): return b.abiExtern(abi.BasicName(t)) */ - kind := int(abi.BasicKind(t)) - return b.InlineCall(b.Pkg.rtFunc("Basic"), b.Prog.Val(kind)) + return func() Expr { + kind := int(abi.BasicKind(t)) + return b.InlineCall(b.Pkg.rtFunc("Basic"), b.Prog.Val(kind)) + } } /* @@ -45,7 +47,7 @@ func (b Builder) abiExtern(name string) Expr { } */ -func (b Builder) abiTypeOf(t types.Type) Expr { +func (b Builder) abiTypeOf(t types.Type) func() Expr { switch t := t.(type) { case *types.Basic: return b.abiBasic(t) @@ -56,7 +58,7 @@ func (b Builder) abiTypeOf(t types.Type) Expr { case *types.Named: return b.abiNamedOf(t) case *types.Interface: - return b.abiInterfaceOf(t) + return b.abiInterfaceOf("", t) case *types.Signature: return b.abiFuncOf(t) case *types.Slice: @@ -67,39 +69,55 @@ func (b Builder) abiTypeOf(t types.Type) Expr { panic("todo") } -func (b Builder) abiTupleOf(t *types.Tuple) Expr { +func (b Builder) abiTupleOf(t *types.Tuple) func() 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...) + return func() Expr { + prog := b.Prog + tSlice := prog.Slice(prog.AbiTypePtr()) + 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") +func (b Builder) abiFuncOf(sig *types.Signature) func() Expr { params := b.abiTupleOf(sig.Params()) results := b.abiTupleOf(sig.Results()) - variadic := prog.Val(sig.Variadic()) - return b.Call(fn, params, results, variadic) + return func() Expr { + prog := b.Prog + pkg := b.Pkg + fn := pkg.rtFunc("Func") + 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 { +func (b Builder) abiImethodOf(m *types.Func, typ Expr) 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) } +func (b Builder) abiMethods(t *types.Named) (ret int) { + n := t.NumMethods() + for i := 0; i < n; i++ { + m := t.Method(i) + mSig := m.Type().(*types.Signature) + recvType := mSig.Recv().Type() + if _, ok := recvType.(*types.Pointer); !ok { + ret++ + } + } + return +} + // Method{name string, typ *FuncType, ifn, tfn abi.Text} func (b Builder) abiMethodOf(m *types.Func /*, bg Background = InGo */) (mthd, ptrMthd Expr) { prog := b.Prog @@ -138,93 +156,133 @@ func (b Builder) abiMthd(mPkg *types.Package, mName string, mSig *types.Signatur return } -// func Interface(pkgPath string, methods []abi.Imethod) -func (b Builder) abiInterfaceOf(t *types.Interface) Expr { - prog := b.Prog +// func Interface(pkgPath, name string, methods []abi.Imethod) +func (b Builder) abiInterfaceOf(name string, t *types.Interface) func() Expr { n := t.NumMethods() - methods := make([]Expr, n) + typs := make([]Expr, n) for i := 0; i < n; i++ { m := t.Method(i) - methods[i] = b.abiImethodOf(m) + typs[i] = b.abiType(m.Type()) } - 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, ptrMethods []abi.Method) -func (b Builder) abiNamedOf(t *types.Named) Expr { - under := b.abiType(t.Underlying()) - path := abi.PathOf(t.Obj().Pkg()) - name := NameOf(t) - prog := b.Prog - pkg := b.Pkg - - var fn = pkg.rtFunc("Named") - var tSlice = lastParamType(prog, fn) - var n = t.NumMethods() - var methods, ptrMethods Expr - if n == 0 { - methods = prog.Zero(tSlice) - ptrMethods = methods - } else { - var mthds []Expr - var ptrMthds = make([]Expr, 0, n) + return func() Expr { + prog := b.Prog + methods := make([]Expr, n) for i := 0; i < n; i++ { m := t.Method(i) - mthd, ptrMthd := b.abiMethodOf(m) - if !mthd.IsNil() { - mthds = append(mthds, mthd) - } - ptrMthds = append(ptrMthds, ptrMthd) + methods[i] = b.abiImethodOf(m, typs[i]) } - if len(mthds) > 0 { - methods = b.SliceLit(tSlice, mthds...) - } else { - methods = prog.Zero(tSlice) - } - ptrMethods = b.SliceLit(tSlice, ptrMthds...) + 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), b.Str(name), methodSlice) } - return b.Call(fn, b.Str(path), b.Str(name), under, methods, ptrMethods) } -func (b Builder) abiPointerOf(t *types.Pointer) Expr { +// func NewNamed(kind abi.Kind, methods, ptrMethods int) +func (b Builder) abiNamedOf(t *types.Named) func() Expr { + return func() Expr { + pkg := b.Pkg + tunder := t.Underlying() + kind := int(abi.UnderlyingKind(tunder)) + numMethods := b.abiMethods(t) + numPtrMethods := t.NumMethods() + newNamed := pkg.rtFunc("NewNamed") + return b.Call(newNamed, b.Prog.Val(kind), b.Prog.Val(numMethods), b.Prog.Val(numPtrMethods)) + } +} + +// func InitNamed(ret *Type, pkgPath, name string, underlying *Type, methods, ptrMethods []Method) +func (b Builder) abiInitNamed(ret Expr, t *types.Named) func() Expr { + under := b.abiType(t.Underlying()) + return func() Expr { + pkg := b.Pkg + prog := b.Prog + path := abi.PathOf(t.Obj().Pkg()) + name := NameOf(t) + + var initNamed = pkg.rtFunc("InitNamed") + var tSlice = lastParamType(prog, initNamed) + var n = t.NumMethods() + var methods, ptrMethods Expr + if n == 0 { + methods = prog.Zero(tSlice) + ptrMethods = methods + } else { + var mthds []Expr + var ptrMthds = make([]Expr, 0, n) + for i := 0; i < n; i++ { + m := t.Method(i) + mthd, ptrMthd := b.abiMethodOf(m) + if !mthd.IsNil() { + mthds = append(mthds, mthd) + } + ptrMthds = append(ptrMthds, ptrMthd) + } + if len(mthds) > 0 { + methods = b.SliceLit(tSlice, mthds...) + } else { + methods = prog.Zero(tSlice) + } + ptrMethods = b.SliceLit(tSlice, ptrMthds...) + } + return b.Call(initNamed, ret, b.Str(path), b.Str(name), under, methods, ptrMethods) + } +} + +func (b Builder) abiPointerOf(t *types.Pointer) func() Expr { elem := b.abiType(t.Elem()) - return b.Call(b.Pkg.rtFunc("PointerTo"), elem) + return func() Expr { + return b.Call(b.Pkg.rtFunc("PointerTo"), elem) + } } -func (b Builder) abiSliceOf(t *types.Slice) Expr { - elem := b.abiTypeOf(t.Elem()) - return b.Call(b.Pkg.rtFunc("SliceOf"), elem) +func (b Builder) abiSliceOf(t *types.Slice) func() Expr { + elem := b.abiType(t.Elem()) + return func() Expr { + return b.Call(b.Pkg.rtFunc("SliceOf"), elem) + } } -func (b Builder) abiArrayOf(t *types.Array) Expr { - elem := b.abiTypeOf(t.Elem()) - return b.Call(b.Pkg.rtFunc("ArrayOf"), b.Prog.IntVal(uint64(t.Len()), b.Prog.Uintptr()), elem) +func (b Builder) abiArrayOf(t *types.Array) func() Expr { + elem := b.abiType(t.Elem()) + return func() Expr { + n := b.Prog.IntVal(uint64(t.Len()), b.Prog.Uintptr()) + return b.Call(b.Pkg.rtFunc("ArrayOf"), n, elem) + } } +// func StructField(name string, typ *abi.Type, off uintptr, tag string, embedded bool) // func Struct(pkgPath string, size uintptr, fields []abi.StructField) -func (b Builder) abiStructOf(t *types.Struct) Expr { - pkg := b.Pkg - prog := b.Prog +func (b Builder) abiStructOf(t *types.Struct) func() Expr { n := t.NumFields() - flds := make([]Expr, n) - strucAbi := pkg.rtFunc("Struct") - sfAbi := pkg.rtFunc("StructField") - typ := prog.rawType(t) + typs := make([]Expr, n) for i := 0; i < n; i++ { f := t.Field(i) - off := uintptr(prog.OffsetOf(typ, i)) - flds[i] = b.structField(sfAbi, prog, f, off, t.Tag(i)) + typs[i] = b.abiType(f.Type()) + } + return func() Expr { + pkg := b.Pkg + prog := b.Prog + flds := make([]Expr, n) + strucAbi := pkg.rtFunc("Struct") + sfAbi := pkg.rtFunc("StructField") + tStruc := prog.rawType(t) + for i := 0; i < n; i++ { + f := t.Field(i) + off := uintptr(prog.OffsetOf(tStruc, i)) + name := b.Str(f.Name()) + tag := b.Str(t.Tag(i)) + embedded := prog.Val(f.Embedded()) + flds[i] = b.Call(sfAbi, name, typs[i], prog.Val(off), tag, embedded) + } + pkgPath := b.Str(pkg.Path()) + tSlice := lastParamType(prog, strucAbi) + fldSlice := b.SliceLit(tSlice, flds...) + size := prog.IntVal(prog.SizeOf(tStruc), prog.Uintptr()) + return b.Call(strucAbi, pkgPath, size, fldSlice) } - pkgPath := b.Str(pkg.Path()) - tSlice := lastParamType(prog, strucAbi) - fldSlice := b.SliceLit(tSlice, flds...) - size := prog.IntVal(prog.SizeOf(typ), prog.Uintptr()) - return b.Call(strucAbi, pkgPath, size, fldSlice) } func lastParamType(prog Program, fn Expr) Type { @@ -232,20 +290,68 @@ func lastParamType(prog Program, fn Expr) Type { return prog.rawType(params.At(params.Len() - 1).Type()) } -// func StructField(name string, typ *abi.Type, off uintptr, tag string, embedded bool) abi.StructField -func (b Builder) structField(sfAbi Expr, prog Program, f *types.Var, offset uintptr, tag string) Expr { - name := b.Str(f.Name()) - typ := b.abiType(f.Type()) - embedded := prog.Val(f.Embedded()) - return b.Call(sfAbi, name, typ, prog.Val(offset), b.Str(tag), embedded) +// ----------------------------------------------------------------------------- + +type abiTypes struct { + iniabi unsafe.Pointer +} + +func (p Package) hasAbiInit() bool { + return p.iniabi != nil +} + +func (p Package) abiInit(b Builder) { + inib := Builder(p.iniabi) + inib.Return() + b.Call(inib.Func.Expr) +} + +func (p Package) abiBuilder() Builder { + if p.iniabi == nil { + sigAbiInit := types.NewSignatureType(nil, nil, nil, nil, nil, false) + fn := p.NewFunc(p.Path()+".init$abi", sigAbiInit, InC) + fnb := fn.MakeBody(1) + p.iniabi = unsafe.Pointer(fnb) + } + return Builder(p.iniabi) +} + +func (p Package) abiTypeInit(g Global, t types.Type, pub bool) { + b := p.abiBuilder() + tabi := b.abiTypeOf(t) + expr := g.Expr + var eq Expr + var blks []BasicBlock + if pub { + eq = b.BinOp(token.EQL, b.Load(expr), b.Prog.Null(expr.Type)) + blks = b.Func.MakeBlocks(2) + b.If(eq, blks[0], blks[1]) + b.SetBlockEx(blks[0], AtEnd, false) + } + b.Store(expr, tabi()) + if pub { + b.Jump(blks[1]) + b.SetBlockEx(blks[1], AtEnd, false) + b.blk.last = blks[1].last + } + if t, ok := t.(*types.Named); ok { + tabi = b.abiInitNamed(expr, t) + if pub { + blks = b.Func.MakeBlocks(2) + b.If(eq, blks[0], blks[1]) + b.SetBlockEx(blks[0], AtEnd, false) + } + tabi() + if pub { + b.Jump(blks[1]) + b.SetBlockEx(blks[1], AtEnd, false) + b.blk.last = blks[1].last + } + } } // abiType returns the abi type of the specified type. func (b Builder) abiType(t types.Type) Expr { - switch tx := t.(type) { - case *types.Basic: - return b.abiBasic(tx) - } pkg := b.Pkg name, pub := pkg.abi.TypeName(t) g := pkg.VarOf(name) @@ -256,24 +362,7 @@ func (b Builder) abiType(t types.Type) Expr { if pub { g.impl.SetLinkage(llvm.LinkOnceAnyLinkage) } - pkg.abiini = append(pkg.abiini, func(param unsafe.Pointer) { - b := Builder(param) - expr := g.Expr - var blks []BasicBlock - if pub { - eq := b.BinOp(token.EQL, b.Load(expr), b.Prog.Null(expr.Type)) - blks = b.Func.MakeBlocks(2) - b.If(eq, blks[0], blks[1]) - b.SetBlockEx(blks[0], AtEnd, false) - } - tabi := b.abiTypeOf(t) - b.Store(expr, tabi) - if pub { - b.Jump(blks[1]) - b.SetBlockEx(blks[1], AtEnd, false) - b.blk.last = blks[1].last - } - }) + pkg.abiTypeInit(g, t, pub) } return b.Load(g.Expr) } diff --git a/ssa/interface.go b/ssa/interface.go index f1ca724f..5b97c78f 100644 --- a/ssa/interface.go +++ b/ssa/interface.go @@ -102,7 +102,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) { prog := b.Prog typ := x.Type tabi := b.abiType(typ.raw.Type) - kind, _, lvl := abi.KindOf(typ.raw.Type, 0, prog.is32Bits) + kind, _, lvl := abi.DataKindOf(typ.raw.Type, 0, prog.is32Bits) switch kind { case abi.Indirect: vptr := b.AllocU(typ) @@ -132,7 +132,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) { func (b Builder) valFromData(typ Type, data llvm.Value) Expr { prog := b.Prog - kind, real, lvl := abi.KindOf(typ.raw.Type, 0, prog.is32Bits) + kind, real, lvl := abi.DataKindOf(typ.raw.Type, 0, prog.is32Bits) switch kind { case abi.Indirect: impl := b.impl diff --git a/ssa/package.go b/ssa/package.go index 2beb25c2..cac873e6 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -20,7 +20,6 @@ import ( "go/token" "go/types" "strconv" - "unsafe" "github.com/goplus/llgo/ssa/abi" "github.com/goplus/llvm" @@ -510,15 +509,17 @@ func (p Program) Uint64() Type { // initializer) and "init#%d", the nth declared init function, // and unspecified other things too. type aPackage struct { - mod llvm.Module - abi abi.Builder - abiini []func(b unsafe.Pointer) // b Builder + mod llvm.Module + vars map[string]Global fns map[string]Function stubs map[string]Function pyobjs map[string]PyObjRef pymods map[string]Global Prog Program + + abi abi.Builder + abiTypes } type Package = *aPackage @@ -582,31 +583,12 @@ func (p Package) String() string { // AfterInit is called after the package is initialized (init all packages that depends on). func (p Package) AfterInit(b Builder, ret BasicBlock) { - doAbiInit := len(p.abiini) > 0 + doAbiInit := p.hasAbiInit() doPyLoadModSyms := p.pyHasModSyms() if doAbiInit || doPyLoadModSyms { b.SetBlockEx(ret, afterInit, false) if doAbiInit { - sigAbiInit := types.NewSignatureType(nil, nil, nil, nil, nil, false) - baseName := p.Path() + ".init$abi" - name := baseName - idx := 1 - fn := p.NewFunc(name, sigAbiInit, InC) - b.Call(fn.Expr) - for { - fnb := fn.MakeBody(1) - first := fnb.blk - p.callAbiInit(fnb) - fnb.Return() - if len(p.abiini) == 0 { - break - } - idx++ - name = baseName + strconv.Itoa(idx) - fn = p.NewFunc(name, sigAbiInit, InC) - fnb.SetBlockEx(first, AtStart, false) - fnb.Call(fn.Expr) - } + p.abiInit(b) } if doPyLoadModSyms { p.pyLoadModSyms(b) @@ -614,14 +596,6 @@ func (p Package) AfterInit(b Builder, ret BasicBlock) { } } -func (p Package) callAbiInit(fnb Builder) { - abiini := p.abiini - p.abiini = nil - for _, abiInit := range abiini { - abiInit(unsafe.Pointer(fnb)) - } -} - /* type CodeGenFileType = llvm.CodeGenFileType