runtime: skip zero-sized fields in structs when converting to FFI
The libffi library doesn't understand zero-sized objects. When we see a zero-sized field in a struct, just skip it when converting to the FFI data structures. There is no value to pass in any case, so not telling libffi about the field doesn't affect anything. The test case for this is https://golang.org/cl/123316. Fixes golang/go#26335 Reviewed-on: https://go-review.googlesource.com/123335 From-SVN: r262651
This commit is contained in:
parent
7264261f64
commit
867b003fd7
@ -1,4 +1,4 @@
|
||||
3f7e72eca3f9221e67c055841d42851aa6a66aff
|
||||
db991403fc97854201b3f40492f4f6b9d471cabc
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -225,11 +225,40 @@ func structToFFI(typ *structtype) *__ffi_type {
|
||||
return emptyStructToFFI()
|
||||
}
|
||||
|
||||
fields := make([]*__ffi_type, c+1)
|
||||
fields := make([]*__ffi_type, 0, c+1)
|
||||
checkPad := false
|
||||
for i, v := range typ.fields {
|
||||
fields[i] = typeToFFI(v.typ)
|
||||
// Skip zero-sized fields; they confuse libffi,
|
||||
// and there is no value to pass in any case.
|
||||
// We do have to check whether the alignment of the
|
||||
// zero-sized field introduces any padding for the
|
||||
// next field.
|
||||
if v.typ.size == 0 {
|
||||
checkPad = true
|
||||
continue
|
||||
}
|
||||
|
||||
if checkPad {
|
||||
off := uintptr(0)
|
||||
for j := i - 1; j >= 0; j-- {
|
||||
if typ.fields[j].typ.size > 0 {
|
||||
off = typ.fields[j].offset() + typ.fields[j].typ.size
|
||||
break
|
||||
}
|
||||
}
|
||||
off += uintptr(v.typ.align) - 1
|
||||
off &^= uintptr(v.typ.align) - 1
|
||||
if off != v.offset() {
|
||||
fields = append(fields, padFFI(v.offset()-off))
|
||||
}
|
||||
checkPad = false
|
||||
}
|
||||
|
||||
fields = append(fields, typeToFFI(v.typ))
|
||||
}
|
||||
fields[c] = nil
|
||||
|
||||
fields = append(fields, nil)
|
||||
|
||||
return &__ffi_type{
|
||||
_type: _FFI_TYPE_STRUCT,
|
||||
elements: &fields[0],
|
||||
@ -305,6 +334,19 @@ func emptyStructToFFI() *__ffi_type {
|
||||
}
|
||||
}
|
||||
|
||||
// padFFI returns a padding field of the given size
|
||||
func padFFI(size uintptr) *__ffi_type {
|
||||
elements := make([]*__ffi_type, size+1)
|
||||
for i := uintptr(0); i < size; i++ {
|
||||
elements[i] = ffi_type_uint8()
|
||||
}
|
||||
elements[size] = nil
|
||||
return &__ffi_type{
|
||||
_type: _FFI_TYPE_STRUCT,
|
||||
elements: &elements[0],
|
||||
}
|
||||
}
|
||||
|
||||
//go:linkname makeCIF reflect.makeCIF
|
||||
|
||||
// makeCIF is used by the reflect package to allocate a CIF.
|
||||
|
Loading…
Reference in New Issue
Block a user