--- /dev/null
+pkg structs, type HostLayout struct #66408
--- /dev/null
+### New structs package
+
+
+The new [structs](/pkg/structs) package provides
+types for struct fields that modify properties of
+the containing struct type such as memory layout.
+
+In this release, the only such type is
+[`HostLayout`](/pkg/structs#HostLayout)
+which indicates that a structure with a field of that
+type has a layout that conforms to host platform
+expectations.
\ No newline at end of file
--- /dev/null
+<!-- This is a new package; covered in 6-stdlib/3-structs.md. -->
}
typs := make([]*types.Type, 0, l)
offs := make([]int64, 0, l)
- offs, _ = appendParamOffsets(offs, 0, pa.Type)
+ offs, _ = appendParamOffsets(offs, 0, pa.Type) // 0 is aligned for everything.
return appendParamTypes(typs, pa.Type), offs
}
// appendParamOffsets appends the offset(s) of type t, starting from "at",
// to input offsets, and returns the longer slice and the next unused offset.
+// at should already be aligned for t.
func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int64) {
- at = align(at, t)
w := t.Size()
if w == 0 {
return offsets, at
typ := t.Kind()
switch typ {
case types.TARRAY:
+ te := t.Elem()
for i := int64(0); i < t.NumElem(); i++ {
- offsets, at = appendParamOffsets(offsets, at, t.Elem())
+ at = align(at, te)
+ offsets, at = appendParamOffsets(offsets, at, te)
}
case types.TSTRUCT:
+ at0 := at
for i, f := range t.Fields() {
+ at = at0 + f.Offset // Fields may be over-aligned, see wasm32.
offsets, at = appendParamOffsets(offsets, at, f.Type)
if f.Type.Size() == 0 && i == t.NumFields()-1 {
at++ // last field has zero width
if len(types) != nr {
panic("internal error")
}
+ offsets, _ := appendParamOffsets([]int64{}, 0, pa.Type)
off := int64(0)
for idx, t := range types {
ts := t.Size()
off += int64(ts)
if idx < len(types)-1 {
- noff := align(off, types[idx+1])
+ noff := offsets[idx+1]
if noff != off {
padding[idx] = uint64(noff - off)
}
types.PtrSize = 8
types.RegSize = 8
types.MaxWidth = 1 << 50
- typecheck.InitUniverse()
base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
+ typecheck.InitUniverse()
}
func TestEqStructCost(t *testing.T) {
"cmd/internal/obj"
"cmd/internal/pgo"
"cmd/internal/src"
+ "cmd/internal/sys"
"testing"
)
types.PtrSize = 8
types.RegSize = 8
types.MaxWidth = 1 << 50
+ base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
typecheck.InitUniverse()
- base.Ctxt = &obj.Link{}
base.Debug.PGODebug = 3
}
package inlheur
import (
+ "cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
+ "cmd/internal/obj"
"cmd/internal/src"
+ "cmd/internal/sys"
"go/constant"
"testing"
)
types.PtrSize = 8
types.RegSize = 8
types.MaxWidth = 1 << 50
+ base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
+
typecheck.InitUniverse()
local = types.NewPkg("", "")
fsym := &types.Sym{
import (
"testing"
+ "cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/obj/s390x"
"cmd/internal/obj/x86"
"cmd/internal/src"
+ "cmd/internal/sys"
)
var CheckFunc = checkFunc
types.RegSize = 8
types.MaxWidth = 1 << 50
+ base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
typecheck.InitUniverse()
testTypes.SetTypPtrs()
}
"sort",
"strconv",
"strings",
+ "structs",
"sync",
"syscall",
"testing",
--- /dev/null
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package structs defines marker types that can be used as struct fields
+// to modify the properties of a struct.
+//
+// By convention, a marker type should be used as the type of a field
+// named "_", placed at the beginning of a struct type definition.
+package structs
--- /dev/null
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package structs
+
+// HostLayout marks a struct as using host memory layout. A struct with a
+// field of type HostLayout will be laid out in memory according to host
+// expectations, generally following the host's C ABI.
+//
+// HostLayout does not affect layout within any other struct-typed fields
+// of the containing struct, nor does it affect layout of structs
+// containing the struct marked as host layout.
+//
+// By convention, HostLayout should be used as the type of a field
+// named "_", placed at the beginning of the struct type definition.
+type HostLayout struct {
+ _ hostLayout // prevent accidental conversion with plain struct{}
+}
+
+// We use an unexported type within the exported type to give the marker
+// type itself, rather than merely its name, a recognizable identity in
+// the type system. The main consequence of this is that a user can give
+// the type a new name and it will still have the same properties, e.g.,
+//
+// type HL structs.HostLayout
+//
+// It also prevents unintentional conversion of struct{} to a named marker type.
+type hostLayout struct {
+}