Skip to content

Commit 22344e1

Browse files
dr2chasegopherbot
authored andcommitted
cmd/compile: add structs.HostLayout
This is for the proposal, plus a few bug fixes that would/will be necessary when this is put into actual use. Fixes #66408. Updates #63131. Change-Id: I3a66e09d707dd579c59f155e7f53367f41214c30 Reviewed-on: https://go-review.googlesource.com/c/go/+/578355 Reviewed-by: Austin Clements <austin@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: David Chase <drchase@google.com>
1 parent ecad164 commit 22344e1

File tree

11 files changed

+75
-6
lines changed

11 files changed

+75
-6
lines changed

api/next/66408.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg structs, type HostLayout struct #66408

doc/next/6-stdlib/3-structs.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
### New structs package
2+
3+
4+
The new [structs](/pkg/structs) package provides
5+
types for struct fields that modify properties of
6+
the containing struct type such as memory layout.
7+
8+
In this release, the only such type is
9+
[`HostLayout`](/pkg/structs#HostLayout)
10+
which indicates that a structure with a field of that
11+
type has a layout that conforms to host platform
12+
expectations.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!-- This is a new package; covered in 6-stdlib/3-structs.md. -->

src/cmd/compile/internal/abi/abiutils.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (pa *ABIParamAssignment) RegisterTypesAndOffsets() ([]*types.Type, []int64)
141141
}
142142
typs := make([]*types.Type, 0, l)
143143
offs := make([]int64, 0, l)
144-
offs, _ = appendParamOffsets(offs, 0, pa.Type)
144+
offs, _ = appendParamOffsets(offs, 0, pa.Type) // 0 is aligned for everything.
145145
return appendParamTypes(typs, pa.Type), offs
146146
}
147147

@@ -193,8 +193,8 @@ func appendParamTypes(rts []*types.Type, t *types.Type) []*types.Type {
193193

194194
// appendParamOffsets appends the offset(s) of type t, starting from "at",
195195
// to input offsets, and returns the longer slice and the next unused offset.
196+
// at should already be aligned for t.
196197
func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int64) {
197-
at = align(at, t)
198198
w := t.Size()
199199
if w == 0 {
200200
return offsets, at
@@ -210,11 +210,15 @@ func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int6
210210
typ := t.Kind()
211211
switch typ {
212212
case types.TARRAY:
213+
te := t.Elem()
213214
for i := int64(0); i < t.NumElem(); i++ {
214-
offsets, at = appendParamOffsets(offsets, at, t.Elem())
215+
at = align(at, te)
216+
offsets, at = appendParamOffsets(offsets, at, te)
215217
}
216218
case types.TSTRUCT:
219+
at0 := at
217220
for i, f := range t.Fields() {
221+
at = at0 + f.Offset // Fields may be over-aligned, see wasm32.
218222
offsets, at = appendParamOffsets(offsets, at, f.Type)
219223
if f.Type.Size() == 0 && i == t.NumFields()-1 {
220224
at++ // last field has zero width
@@ -668,12 +672,13 @@ func (pa *ABIParamAssignment) ComputePadding(storage []uint64) []uint64 {
668672
if len(types) != nr {
669673
panic("internal error")
670674
}
675+
offsets, _ := appendParamOffsets([]int64{}, 0, pa.Type)
671676
off := int64(0)
672677
for idx, t := range types {
673678
ts := t.Size()
674679
off += int64(ts)
675680
if idx < len(types)-1 {
676-
noff := align(off, types[idx+1])
681+
noff := offsets[idx+1]
677682
if noff != off {
678683
padding[idx] = uint64(noff - off)
679684
}

src/cmd/compile/internal/compare/compare_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ func init() {
2323
types.PtrSize = 8
2424
types.RegSize = 8
2525
types.MaxWidth = 1 << 50
26-
typecheck.InitUniverse()
2726
base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
27+
typecheck.InitUniverse()
2828
}
2929

3030
func TestEqStructCost(t *testing.T) {

src/cmd/compile/internal/devirtualize/pgo_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"cmd/internal/obj"
1414
"cmd/internal/pgo"
1515
"cmd/internal/src"
16+
"cmd/internal/sys"
1617
"testing"
1718
)
1819

@@ -23,8 +24,8 @@ func init() {
2324
types.PtrSize = 8
2425
types.RegSize = 8
2526
types.MaxWidth = 1 << 50
27+
base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
2628
typecheck.InitUniverse()
27-
base.Ctxt = &obj.Link{}
2829
base.Debug.PGODebug = 3
2930
}
3031

src/cmd/compile/internal/inline/inlheur/texpr_classify_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
package inlheur
66

77
import (
8+
"cmd/compile/internal/base"
89
"cmd/compile/internal/ir"
910
"cmd/compile/internal/typecheck"
1011
"cmd/compile/internal/types"
12+
"cmd/internal/obj"
1113
"cmd/internal/src"
14+
"cmd/internal/sys"
1215
"go/constant"
1316
"testing"
1417
)
@@ -21,6 +24,8 @@ func init() {
2124
types.PtrSize = 8
2225
types.RegSize = 8
2326
types.MaxWidth = 1 << 50
27+
base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
28+
2429
typecheck.InitUniverse()
2530
local = types.NewPkg("", "")
2631
fsym := &types.Sym{

src/cmd/compile/internal/ssa/export_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package ssa
77
import (
88
"testing"
99

10+
"cmd/compile/internal/base"
1011
"cmd/compile/internal/ir"
1112
"cmd/compile/internal/typecheck"
1213
"cmd/compile/internal/types"
@@ -15,6 +16,7 @@ import (
1516
"cmd/internal/obj/s390x"
1617
"cmd/internal/obj/x86"
1718
"cmd/internal/src"
19+
"cmd/internal/sys"
1820
)
1921

2022
var CheckFunc = checkFunc
@@ -115,6 +117,7 @@ func init() {
115117
types.RegSize = 8
116118
types.MaxWidth = 1 << 50
117119

120+
base.Ctxt = &obj.Link{Arch: &obj.LinkArch{Arch: &sys.Arch{Alignment: 1, CanMergeLoads: true}}}
118121
typecheck.InitUniverse()
119122
testTypes.SetTypPtrs()
120123
}

src/go/doc/comment/std.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/structs/doc.go

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package structs defines marker types that can be used as struct fields
6+
// to modify the properties of a struct.
7+
//
8+
// By convention, a marker type should be used as the type of a field
9+
// named "_", placed at the beginning of a struct type definition.
10+
package structs

src/structs/hostlayout.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package structs
6+
7+
// HostLayout marks a struct as using host memory layout. A struct with a
8+
// field of type HostLayout will be laid out in memory according to host
9+
// expectations, generally following the host's C ABI.
10+
//
11+
// HostLayout does not affect layout within any other struct-typed fields
12+
// of the containing struct, nor does it affect layout of structs
13+
// containing the struct marked as host layout.
14+
//
15+
// By convention, HostLayout should be used as the type of a field
16+
// named "_", placed at the beginning of the struct type definition.
17+
type HostLayout struct {
18+
_ hostLayout // prevent accidental conversion with plain struct{}
19+
}
20+
21+
// We use an unexported type within the exported type to give the marker
22+
// type itself, rather than merely its name, a recognizable identity in
23+
// the type system. The main consequence of this is that a user can give
24+
// the type a new name and it will still have the same properties, e.g.,
25+
//
26+
// type HL structs.HostLayout
27+
//
28+
// It also prevents unintentional conversion of struct{} to a named marker type.
29+
type hostLayout struct {
30+
}

0 commit comments

Comments
 (0)