From 0140cca9bc0fad1108c7ed369376ac71cc4bfecf Mon Sep 17 00:00:00 2001 From: melonedo Date: Mon, 19 Sep 2022 16:01:04 +0800 Subject: [PATCH] runtime: synchronize empty struct field handling In GCCGO and gollvm, the logic for allocating one byte for the last field is: 1. the last field has zero size 2. the struct itself does not have zero size 3. the last field is not blank this commit adds the last two conditions to runtime.structToFFI. For golang/go#55146 Change-Id: Iabc3ee09e7f14fab037fd197a9658b099c419904 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/431735 Reviewed-by: Ian Lance Taylor Reviewed-by: Cherry Mui --- libgo/go/runtime/ffi.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libgo/go/runtime/ffi.go b/libgo/go/runtime/ffi.go index cd8479ef..86ce5b85 100644 --- a/libgo/go/runtime/ffi.go +++ b/libgo/go/runtime/ffi.go @@ -4,6 +4,7 @@ // Only build this file if libffi is supported. +//go:build libffi // +build libffi package runtime @@ -221,9 +222,6 @@ func stringToFFI() *__ffi_type { // structToFFI returns an ffi_type for a Go struct type. func structToFFI(typ *structtype) *__ffi_type { c := len(typ.fields) - if c == 0 { - return emptyStructToFFI() - } if typ.typ.kind&kindDirectIface != 0 { return ffi_type_pointer() } @@ -231,6 +229,7 @@ func structToFFI(typ *structtype) *__ffi_type { fields := make([]*__ffi_type, 0, c+1) checkPad := false lastzero := false + sawnonzero := false for i, v := range typ.fields { // Skip zero-sized fields; they confuse libffi, // and there is no value to pass in any case. @@ -239,10 +238,13 @@ func structToFFI(typ *structtype) *__ffi_type { // next field. if v.typ.size == 0 { checkPad = true - lastzero = true + if v.name == nil || *v.name != "_" { + lastzero = true + } continue } lastzero = false + sawnonzero = true if checkPad { off := uintptr(0) @@ -263,6 +265,10 @@ func structToFFI(typ *structtype) *__ffi_type { fields = append(fields, typeToFFI(v.typ)) } + if !sawnonzero { + return emptyStructToFFI() + } + if lastzero { // The compiler adds one byte padding to non-empty struct ending // with a zero-sized field (types.cc:get_backend_struct_fields).