aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-07-13 20:39:02 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-07-13 20:39:02 +0000
commit867b003fd74a1f77c9835a8c64e1dcf88f639aff (patch)
tree56301120971100639a4f923361812cb8d0b79362
parent7264261f64fab95545cd1e5bae429fad5f2b44d7 (diff)
downloadgcc-867b003fd74a1f77c9835a8c64e1dcf88f639aff.zip
gcc-867b003fd74a1f77c9835a8c64e1dcf88f639aff.tar.gz
gcc-867b003fd74a1f77c9835a8c64e1dcf88f639aff.tar.bz2
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
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--libgo/go/runtime/ffi.go48
2 files changed, 46 insertions, 4 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 8aaa045..3e0b655 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -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.
diff --git a/libgo/go/runtime/ffi.go b/libgo/go/runtime/ffi.go
index 164e177..00858f1 100644
--- a/libgo/go/runtime/ffi.go
+++ b/libgo/go/runtime/ffi.go
@@ -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.