Skip to content

Commit

Permalink
cmd/compile: add structs.HostLayout
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dr2chase authored and gopherbot committed May 20, 2024
1 parent ecad164 commit 22344e1
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 6 deletions.
1 change: 1 addition & 0 deletions api/next/66408.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pkg structs, type HostLayout struct #66408
12 changes: 12 additions & 0 deletions doc/next/6-stdlib/3-structs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### 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.
1 change: 1 addition & 0 deletions doc/next/6-stdlib/99-minor/structs/66408.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- This is a new package; covered in 6-stdlib/3-structs.md. -->
13 changes: 9 additions & 4 deletions src/cmd/compile/internal/abi/abiutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (pa *ABIParamAssignment) RegisterTypesAndOffsets() ([]*types.Type, []int64)
}
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
}

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

// 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
Expand All @@ -210,11 +210,15 @@ func appendParamOffsets(offsets []int64, at int64, t *types.Type) ([]int64, int6
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
Expand Down Expand Up @@ -668,12 +672,13 @@ func (pa *ABIParamAssignment) ComputePadding(storage []uint64) []uint64 {
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)
}
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/compare/compare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func init() {
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) {
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/compile/internal/devirtualize/pgo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"cmd/internal/obj"
"cmd/internal/pgo"
"cmd/internal/src"
"cmd/internal/sys"
"testing"
)

Expand All @@ -23,8 +24,8 @@ func init() {
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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
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"
)
Expand All @@ -21,6 +24,8 @@ func init() {
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{
Expand Down
3 changes: 3 additions & 0 deletions src/cmd/compile/internal/ssa/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package ssa
import (
"testing"

"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
Expand All @@ -15,6 +16,7 @@ import (
"cmd/internal/obj/s390x"
"cmd/internal/obj/x86"
"cmd/internal/src"
"cmd/internal/sys"
)

var CheckFunc = checkFunc
Expand Down Expand Up @@ -115,6 +117,7 @@ func init() {
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()
}
1 change: 1 addition & 0 deletions src/go/doc/comment/std.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/structs/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// 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
30 changes: 30 additions & 0 deletions src/structs/hostlayout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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 {
}

0 comments on commit 22344e1

Please sign in to comment.