abiTypes
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
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")
|
||||
|
||||
217
ssa/abitype.go
217
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))
|
||||
*/
|
||||
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 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 {
|
||||
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
|
||||
pkg := b.Pkg
|
||||
fn := pkg.rtFunc("Func")
|
||||
params := b.abiTupleOf(sig.Params())
|
||||
results := b.abiTupleOf(sig.Results())
|
||||
variadic := prog.Val(sig.Variadic())
|
||||
return b.Call(fn, params, results, variadic)
|
||||
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,33 +156,54 @@ 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()
|
||||
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)
|
||||
for i := 0; i < n; i++ {
|
||||
m := t.Method(i)
|
||||
methods[i] = b.abiImethodOf(m)
|
||||
methods[i] = b.abiImethodOf(m, typs[i])
|
||||
}
|
||||
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)
|
||||
return b.Call(fn, b.Str(pkgPath), b.Str(name), methodSlice)
|
||||
}
|
||||
}
|
||||
|
||||
// func Named(pkgPath, name string, underlying *Type, methods, ptrMethods []abi.Method)
|
||||
func (b Builder) abiNamedOf(t *types.Named) 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)
|
||||
prog := b.Prog
|
||||
pkg := b.Pkg
|
||||
|
||||
var fn = pkg.rtFunc("Named")
|
||||
var tSlice = lastParamType(prog, fn)
|
||||
var initNamed = pkg.rtFunc("InitNamed")
|
||||
var tSlice = lastParamType(prog, initNamed)
|
||||
var n = t.NumMethods()
|
||||
var methods, ptrMethods Expr
|
||||
if n == 0 {
|
||||
@@ -188,43 +227,62 @@ func (b Builder) abiNamedOf(t *types.Named) Expr {
|
||||
}
|
||||
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())
|
||||
return func() Expr {
|
||||
return b.Call(b.Pkg.rtFunc("PointerTo"), elem)
|
||||
}
|
||||
}
|
||||
|
||||
func (b Builder) abiSliceOf(t *types.Slice) Expr {
|
||||
elem := b.abiTypeOf(t.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 {
|
||||
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
|
||||
prog := b.Prog
|
||||
n := t.NumFields()
|
||||
flds := make([]Expr, n)
|
||||
strucAbi := pkg.rtFunc("Struct")
|
||||
sfAbi := pkg.rtFunc("StructField")
|
||||
typ := prog.rawType(t)
|
||||
tStruc := prog.rawType(t)
|
||||
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))
|
||||
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(typ), prog.Uintptr())
|
||||
size := prog.IntVal(prog.SizeOf(tStruc), 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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/goplus/llgo/ssa/abi"
|
||||
"github.com/goplus/llvm"
|
||||
@@ -511,14 +510,16 @@ func (p Program) Uint64() Type {
|
||||
// and unspecified other things too.
|
||||
type aPackage struct {
|
||||
mod llvm.Module
|
||||
abi abi.Builder
|
||||
abiini []func(b unsafe.Pointer) // b Builder
|
||||
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user