diff options
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | libgo/go/runtime/ffi.go | 48 |
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. |