This commit is contained in:
xushiwei
2024-05-31 07:35:22 +08:00
parent db141e1f3f
commit 3b2f01e974
6 changed files with 307 additions and 244 deletions

View File

@@ -134,6 +134,12 @@ const (
// TFlagRegularMemory means that equal and hash functions can treat // TFlagRegularMemory means that equal and hash functions can treat
// this type as a single region of t.size bytes. // this type as a single region of t.size bytes.
TFlagRegularMemory TFlag = 1 << 3 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. // 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 FuncType struct {
Type Type
InCount uint16 In []*Type
OutCount uint16 // top bit is set if last input parameter is ... Out []*Type
}
// 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))
} }
// Variadic reports whether the function type is variadic. // Variadic reports whether the function type is variadic.
func (p *FuncType) Variadic() bool { func (p *FuncType) Variadic() bool {
return p.OutCount&(1<<15) != 0 return p.TFlag&TFlagVariadic != 0
} }
type StructField struct { 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_) } 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 { func (t *Type) Common() *Type {
return t return t
} }

View File

@@ -102,56 +102,50 @@ func hdrSizeOf(kind abi.Kind) uintptr {
return typeHdrSize return typeHdrSize
} }
// Named returns a named type. // NewNamed returns an uninitialized named type.
func Named(pkgPath, name string, underlying *Type, methods, ptrMethods []Method) *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 tflag := underlying.TFlag
if tflag&abi.TFlagUncommon != 0 { if tflag&abi.TFlagUncommon != 0 {
panic("runtime: underlying type is already named") panic("runtime: underlying type is already named")
} }
kind := underlying.Kind() kind := abi.Kind(ret.Kind_)
n := len(methods) if ret.TFlag != abi.TFlagUninited || kind != underlying.Kind() {
if kind == abi.Interface { panic("initNamed: unexpected named type")
if n > 0 {
panic("runtime: interface type cannot have methods")
}
ret := *underlying.InterfaceType()
ret.PkgPath_ = pkgPath
ret.Str_ = name
return &ret.Type
} }
ret := newNamed(pkgPath, name, underlying, methods) ptr := unsafe.Pointer(ret)
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) 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) c.Memcpy(ptr, unsafe.Pointer(underlying), baseSize)
ret := (*Type)(ptr) ret.TFlag = tflag | abi.TFlagNamed | abi.TFlagUncommon
ret.TFlag = tflag | abi.TFlagNamed
ret.Str_ = name ret.Str_ = name
xcount := 0 n := len(methods)
xcount := uint16(0)
for _, m := range methods { for _, m := range methods {
if !m.Exported() { if !m.Exported() {
break break
@@ -161,54 +155,42 @@ func newNamed(pkgPath, name string, underlying *Type, methods []Method) *Type {
uncommon := (*abi.UncommonType)(c.Advance(ptr, int(baseSize))) uncommon := (*abi.UncommonType)(c.Advance(ptr, int(baseSize)))
uncommon.PkgPath_ = pkgPath uncommon.PkgPath_ = pkgPath
uncommon.Mcount = uint16(n) uncommon.Mcount = uint16(n)
uncommon.Xcount = uint16(xcount) uncommon.Xcount = xcount
uncommon.Moff = uint32(uncommonTypeHdrSize + extraSize) uncommon.Moff = uint32(uncommonTypeHdrSize)
extraOff := int(baseSize + 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)) data := (*abi.Method)(c.Advance(ptr, extraOff))
copy(unsafe.Slice(data, n), methods) copy(unsafe.Slice(data, n), methods)
println("==> Named:", pkgPath, name, ret, ret.Uncommon()) println("==> InitNamed:", pkgPath, name, ret, ret.Uncommon())
return ret
} }
// Func returns a function type. // Func returns a function type.
func Func(in, out []*Type, variadic bool) *FuncType { func Func(in, out []*Type, variadic bool) *FuncType {
n := len(in) + len(out) ret := &FuncType{
ptr := AllocU(funcTypeHdrSize + uintptr(n)*pointerSize) Type: Type{
c.Memset(ptr, 0, funcTypeHdrSize) Size_: unsafe.Sizeof(uintptr(0)),
Hash: uint32(abi.Func), // TODO(xsw): hash
ret := (*abi.FuncType)(ptr) Kind_: uint8(abi.Func),
ret.Size_ = pointerSize },
ret.Hash = uint32(abi.Func) // TODO(xsw): hash In: in,
ret.Kind_ = uint8(abi.Func) Out: out,
ret.InCount = uint16(len(in)) }
ret.OutCount = uint16(len(out)) if variadic {
if variadic { ret.TFlag |= abi.TFlagVariadic
ret.OutCount |= 1 << 15
} }
data := (**Type)(c.Advance(ptr, int(funcTypeHdrSize)))
params := unsafe.Slice(data, n)
copy(params, in)
copy(params[len(in):], out)
return ret return ret
} }
// Interface returns an interface type. // 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{ ret := &abi.InterfaceType{
Type: Type{ Type: Type{
Size_: unsafe.Sizeof(eface{}), Size_: unsafe.Sizeof(eface{}),
Hash: uint32(abi.Interface), // TODO(xsw): hash Hash: uint32(abi.Interface), // TODO(xsw): hash
Kind_: uint8(abi.Interface), Kind_: uint8(abi.Interface),
Str_: name,
}, },
PkgPath_: pkgPath, PkgPath_: pkgPath,
Methods: methods, Methods: methods,

View File

@@ -40,19 +40,43 @@ func BasicKind(t *types.Basic) abi.Kind {
return abi.Kind(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 ( const (
Invalid Kind = iota Invalid DataKind = iota
Indirect // allocate memory for the value Indirect // allocate memory for the value
Pointer // store a pointer value directly in the interface value Pointer // store a pointer value directly in the interface value
Integer // store a integer 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 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) { switch t := raw.Underlying().(type) {
case *types.Basic: case *types.Basic:
kind := t.Kind() kind := t.Kind()
@@ -76,12 +100,12 @@ func KindOf(raw types.Type, lvl int, is32Bits bool) (Kind, types.Type, int) {
return Pointer, raw, lvl return Pointer, raw, lvl
case *types.Struct: case *types.Struct:
if t.NumFields() == 1 { 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.Interface, *types.Slice:
case *types.Array: case *types.Array:
if t.Len() == 1 { if t.Len() == 1 {
return KindOf(t.Elem(), lvl+1, is32Bits) return DataKindOf(t.Elem(), lvl+1, is32Bits)
} }
default: default:
panic("unkown type") panic("unkown type")

View File

@@ -29,13 +29,15 @@ import (
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// abiBasic returns the abi type of the specified basic kind. // 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): TODO(xsw):
return b.abiExtern(abi.BasicName(t)) return b.abiExtern(abi.BasicName(t))
*/ */
return func() Expr {
kind := int(abi.BasicKind(t)) kind := int(abi.BasicKind(t))
return b.InlineCall(b.Pkg.rtFunc("Basic"), b.Prog.Val(kind)) 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) { switch t := t.(type) {
case *types.Basic: case *types.Basic:
return b.abiBasic(t) return b.abiBasic(t)
@@ -56,7 +58,7 @@ func (b Builder) abiTypeOf(t types.Type) Expr {
case *types.Named: case *types.Named:
return b.abiNamedOf(t) return b.abiNamedOf(t)
case *types.Interface: case *types.Interface:
return b.abiInterfaceOf(t) return b.abiInterfaceOf("", t)
case *types.Signature: case *types.Signature:
return b.abiFuncOf(t) return b.abiFuncOf(t)
case *types.Slice: case *types.Slice:
@@ -67,39 +69,55 @@ func (b Builder) abiTypeOf(t types.Type) Expr {
panic("todo") panic("todo")
} }
func (b Builder) abiTupleOf(t *types.Tuple) Expr { func (b Builder) abiTupleOf(t *types.Tuple) func() Expr {
n := t.Len() n := t.Len()
prog := b.Prog
tSlice := prog.Slice(prog.AbiTypePtr())
tuple := make([]Expr, n) tuple := make([]Expr, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
tuple[i] = b.abiType(t.At(i).Type()) tuple[i] = b.abiType(t.At(i).Type())
} }
return func() Expr {
prog := b.Prog
tSlice := prog.Slice(prog.AbiTypePtr())
return b.SliceLit(tSlice, tuple...) return b.SliceLit(tSlice, tuple...)
}
} }
// func Func(in, out []*Type, variadic bool) // func Func(in, out []*Type, variadic bool)
func (b Builder) abiFuncOf(sig *types.Signature) Expr { func (b Builder) abiFuncOf(sig *types.Signature) func() Expr {
params := b.abiTupleOf(sig.Params())
results := b.abiTupleOf(sig.Results())
return func() Expr {
prog := b.Prog prog := b.Prog
pkg := b.Pkg pkg := b.Pkg
fn := pkg.rtFunc("Func") fn := pkg.rtFunc("Func")
params := b.abiTupleOf(sig.Params())
results := b.abiTupleOf(sig.Results())
variadic := prog.Val(sig.Variadic()) variadic := prog.Val(sig.Variadic())
return b.Call(fn, params, results, variadic) return b.Call(fn, params(), results(), variadic)
}
} }
// Imethod{name string, typ *FuncType} // 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 prog := b.Prog
name := b.Str(m.Name()) name := b.Str(m.Name())
typ := b.abiType(m.Type())
tname, _ := b.Pkg.abi.TypeName(m.Type()) tname, _ := b.Pkg.abi.TypeName(m.Type())
log.Println("==> abiImethodOf:", m.Name(), m.Type(), tname) log.Println("==> abiImethodOf:", m.Name(), m.Type(), tname)
b.Println(b.Str("==> abiImethodOf:"), typ) b.Println(b.Str("==> abiImethodOf:"), typ)
return b.aggregateValue(prog.rtType("Imethod"), name.impl, typ.impl) 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} // Method{name string, typ *FuncType, ifn, tfn abi.Text}
func (b Builder) abiMethodOf(m *types.Func /*, bg Background = InGo */) (mthd, ptrMthd Expr) { func (b Builder) abiMethodOf(m *types.Func /*, bg Background = InGo */) (mthd, ptrMthd Expr) {
prog := b.Prog prog := b.Prog
@@ -138,33 +156,54 @@ func (b Builder) abiMthd(mPkg *types.Package, mName string, mSig *types.Signatur
return return
} }
// func Interface(pkgPath string, methods []abi.Imethod) // func Interface(pkgPath, name string, methods []abi.Imethod)
func (b Builder) abiInterfaceOf(t *types.Interface) Expr { func (b Builder) abiInterfaceOf(name string, t *types.Interface) func() Expr {
prog := b.Prog
n := t.NumMethods() n := t.NumMethods()
typs := make([]Expr, n)
for i := 0; i < n; i++ {
m := t.Method(i)
typs[i] = b.abiType(m.Type())
}
return func() Expr {
prog := b.Prog
methods := make([]Expr, n) methods := make([]Expr, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
m := t.Method(i) m := t.Method(i)
methods[i] = b.abiImethodOf(m) methods[i] = b.abiImethodOf(m, typs[i])
} }
pkg := b.Pkg pkg := b.Pkg
fn := pkg.rtFunc("Interface") fn := pkg.rtFunc("Interface")
pkgPath := pkg.Path() pkgPath := pkg.Path()
tSlice := lastParamType(prog, fn) tSlice := lastParamType(prog, fn)
methodSlice := b.SliceLit(tSlice, methods...) methodSlice := b.SliceLit(tSlice, methods...)
return b.Call(fn, b.Str(pkgPath), methodSlice) return b.Call(fn, b.Str(pkgPath), b.Str(name), methodSlice)
}
} }
// func Named(pkgPath, name string, underlying *Type, methods, ptrMethods []abi.Method) // func NewNamed(kind abi.Kind, methods, ptrMethods int)
func (b Builder) abiNamedOf(t *types.Named) Expr { 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()) under := b.abiType(t.Underlying())
return func() Expr {
pkg := b.Pkg
prog := b.Prog
path := abi.PathOf(t.Obj().Pkg()) path := abi.PathOf(t.Obj().Pkg())
name := NameOf(t) name := NameOf(t)
prog := b.Prog
pkg := b.Pkg
var fn = pkg.rtFunc("Named") var initNamed = pkg.rtFunc("InitNamed")
var tSlice = lastParamType(prog, fn) var tSlice = lastParamType(prog, initNamed)
var n = t.NumMethods() var n = t.NumMethods()
var methods, ptrMethods Expr var methods, ptrMethods Expr
if n == 0 { if n == 0 {
@@ -188,43 +227,62 @@ func (b Builder) abiNamedOf(t *types.Named) Expr {
} }
ptrMethods = b.SliceLit(tSlice, ptrMthds...) ptrMethods = b.SliceLit(tSlice, ptrMthds...)
} }
return b.Call(fn, b.Str(path), b.Str(name), under, methods, ptrMethods) return b.Call(initNamed, ret, b.Str(path), b.Str(name), under, methods, ptrMethods)
}
} }
func (b Builder) abiPointerOf(t *types.Pointer) Expr { func (b Builder) abiPointerOf(t *types.Pointer) func() Expr {
elem := b.abiType(t.Elem()) elem := b.abiType(t.Elem())
return func() Expr {
return b.Call(b.Pkg.rtFunc("PointerTo"), elem) return b.Call(b.Pkg.rtFunc("PointerTo"), elem)
}
} }
func (b Builder) abiSliceOf(t *types.Slice) Expr { func (b Builder) abiSliceOf(t *types.Slice) func() Expr {
elem := b.abiTypeOf(t.Elem()) elem := b.abiType(t.Elem())
return func() Expr {
return b.Call(b.Pkg.rtFunc("SliceOf"), elem) return b.Call(b.Pkg.rtFunc("SliceOf"), elem)
}
} }
func (b Builder) abiArrayOf(t *types.Array) Expr { func (b Builder) abiArrayOf(t *types.Array) func() Expr {
elem := b.abiTypeOf(t.Elem()) elem := b.abiType(t.Elem())
return b.Call(b.Pkg.rtFunc("ArrayOf"), b.Prog.IntVal(uint64(t.Len()), b.Prog.Uintptr()), 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 Struct(pkgPath string, size uintptr, fields []abi.StructField)
func (b Builder) abiStructOf(t *types.Struct) Expr { func (b Builder) abiStructOf(t *types.Struct) func() Expr {
n := t.NumFields()
typs := make([]Expr, n)
for i := 0; i < n; i++ {
f := t.Field(i)
typs[i] = b.abiType(f.Type())
}
return func() Expr {
pkg := b.Pkg pkg := b.Pkg
prog := b.Prog prog := b.Prog
n := t.NumFields()
flds := make([]Expr, n) flds := make([]Expr, n)
strucAbi := pkg.rtFunc("Struct") strucAbi := pkg.rtFunc("Struct")
sfAbi := pkg.rtFunc("StructField") sfAbi := pkg.rtFunc("StructField")
typ := prog.rawType(t) tStruc := prog.rawType(t)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
f := t.Field(i) f := t.Field(i)
off := uintptr(prog.OffsetOf(typ, i)) off := uintptr(prog.OffsetOf(tStruc, i))
flds[i] = b.structField(sfAbi, prog, f, off, t.Tag(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()) pkgPath := b.Str(pkg.Path())
tSlice := lastParamType(prog, strucAbi) tSlice := lastParamType(prog, strucAbi)
fldSlice := b.SliceLit(tSlice, flds...) fldSlice := b.SliceLit(tSlice, flds...)
size := prog.IntVal(prog.SizeOf(typ), prog.Uintptr()) size := prog.IntVal(prog.SizeOf(tStruc), prog.Uintptr())
return b.Call(strucAbi, pkgPath, size, fldSlice) return b.Call(strucAbi, pkgPath, size, fldSlice)
}
} }
func lastParamType(prog Program, fn Expr) Type { 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()) 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()) type abiTypes struct {
typ := b.abiType(f.Type()) iniabi unsafe.Pointer
embedded := prog.Val(f.Embedded()) }
return b.Call(sfAbi, name, typ, prog.Val(offset), b.Str(tag), embedded)
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. // abiType returns the abi type of the specified type.
func (b Builder) abiType(t types.Type) Expr { func (b Builder) abiType(t types.Type) Expr {
switch tx := t.(type) {
case *types.Basic:
return b.abiBasic(tx)
}
pkg := b.Pkg pkg := b.Pkg
name, pub := pkg.abi.TypeName(t) name, pub := pkg.abi.TypeName(t)
g := pkg.VarOf(name) g := pkg.VarOf(name)
@@ -256,24 +362,7 @@ func (b Builder) abiType(t types.Type) Expr {
if pub { if pub {
g.impl.SetLinkage(llvm.LinkOnceAnyLinkage) g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
} }
pkg.abiini = append(pkg.abiini, func(param unsafe.Pointer) { pkg.abiTypeInit(g, t, pub)
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
}
})
} }
return b.Load(g.Expr) return b.Load(g.Expr)
} }

View File

@@ -102,7 +102,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) {
prog := b.Prog prog := b.Prog
typ := x.Type typ := x.Type
tabi := b.abiType(typ.raw.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 { switch kind {
case abi.Indirect: case abi.Indirect:
vptr := b.AllocU(typ) 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 { func (b Builder) valFromData(typ Type, data llvm.Value) Expr {
prog := b.Prog 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 { switch kind {
case abi.Indirect: case abi.Indirect:
impl := b.impl impl := b.impl

View File

@@ -20,7 +20,6 @@ import (
"go/token" "go/token"
"go/types" "go/types"
"strconv" "strconv"
"unsafe"
"github.com/goplus/llgo/ssa/abi" "github.com/goplus/llgo/ssa/abi"
"github.com/goplus/llvm" "github.com/goplus/llvm"
@@ -511,14 +510,16 @@ func (p Program) Uint64() Type {
// and unspecified other things too. // and unspecified other things too.
type aPackage struct { type aPackage struct {
mod llvm.Module mod llvm.Module
abi abi.Builder
abiini []func(b unsafe.Pointer) // b Builder
vars map[string]Global vars map[string]Global
fns map[string]Function fns map[string]Function
stubs map[string]Function stubs map[string]Function
pyobjs map[string]PyObjRef pyobjs map[string]PyObjRef
pymods map[string]Global pymods map[string]Global
Prog Program Prog Program
abi abi.Builder
abiTypes
} }
type Package = *aPackage 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). // AfterInit is called after the package is initialized (init all packages that depends on).
func (p Package) AfterInit(b Builder, ret BasicBlock) { func (p Package) AfterInit(b Builder, ret BasicBlock) {
doAbiInit := len(p.abiini) > 0 doAbiInit := p.hasAbiInit()
doPyLoadModSyms := p.pyHasModSyms() doPyLoadModSyms := p.pyHasModSyms()
if doAbiInit || doPyLoadModSyms { if doAbiInit || doPyLoadModSyms {
b.SetBlockEx(ret, afterInit, false) b.SetBlockEx(ret, afterInit, false)
if doAbiInit { if doAbiInit {
sigAbiInit := types.NewSignatureType(nil, nil, nil, nil, nil, false) p.abiInit(b)
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)
}
} }
if doPyLoadModSyms { if doPyLoadModSyms {
p.pyLoadModSyms(b) 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 type CodeGenFileType = llvm.CodeGenFileType