abiTypes
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
219
ssa/abitype.go
219
ssa/abitype.go
@@ -29,14 +29,16 @@ 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))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func (b Builder) abiExtern(name string) Expr {
|
func (b Builder) abiExtern(name string) Expr {
|
||||||
@@ -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,64 +227,131 @@ 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 {
|
|
||||||
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 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 {
|
||||||
params := fn.raw.Type.(*types.Signature).Params()
|
params := fn.raw.Type.(*types.Signature).Params()
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user