1
0
mirror of https://github.com/golang/go synced 2024-11-18 16:24:42 -07:00

cmd/compile/internal/types: add Type.Registers

To be used by package abi in the following CL.

Change-Id: Ic2470069e65f8d9b01ec161c28e5b86dca2ec141
Reviewed-on: https://go-review.googlesource.com/c/go/+/527338
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Matthew Dempsky 2023-09-11 20:19:46 -07:00 committed by Gopher Robot
parent 65c407b405
commit c80a9f172b
3 changed files with 77 additions and 10 deletions

View File

@ -5,6 +5,7 @@
package types
import (
"math"
"sort"
"cmd/compile/internal/base"
@ -267,39 +268,58 @@ func CalcSize(t *Type) {
case TINT8, TUINT8, TBOOL:
// bool is int8
w = 1
t.intRegs = 1
case TINT16, TUINT16:
w = 2
t.intRegs = 1
case TINT32, TUINT32, TFLOAT32:
case TINT32, TUINT32:
w = 4
t.intRegs = 1
case TINT64, TUINT64, TFLOAT64:
case TINT64, TUINT64:
w = 8
t.align = uint8(RegSize)
t.intRegs = uint8(8 / RegSize)
case TFLOAT32:
w = 4
t.floatRegs = 1
case TFLOAT64:
w = 8
t.align = uint8(RegSize)
t.floatRegs = 1
case TCOMPLEX64:
w = 8
t.align = 4
t.floatRegs = 2
case TCOMPLEX128:
w = 16
t.align = uint8(RegSize)
t.floatRegs = 2
case TPTR:
w = int64(PtrSize)
t.intRegs = 1
CheckSize(t.Elem())
case TUNSAFEPTR:
w = int64(PtrSize)
t.intRegs = 1
case TINTER: // implemented as 2 pointers
w = 2 * int64(PtrSize)
t.align = uint8(PtrSize)
t.intRegs = 2
expandiface(t)
case TCHAN: // implemented as pointer
w = int64(PtrSize)
t.intRegs = 1
CheckSize(t.Elem())
@ -323,15 +343,14 @@ func CalcSize(t *Type) {
case TMAP: // implemented as pointer
w = int64(PtrSize)
t.intRegs = 1
CheckSize(t.Elem())
CheckSize(t.Key())
case TFORW: // should have been filled in
base.Fatalf("invalid recursive type %v", t)
w = 1 // anything will do
case TANY:
// not a real type; should be replaced before use.
case TANY: // not a real type; should be replaced before use.
base.Fatalf("CalcSize any")
case TSTRING:
@ -340,6 +359,7 @@ func CalcSize(t *Type) {
}
w = StringSize
t.align = uint8(PtrSize)
t.intRegs = 2
case TARRAY:
if t.Elem() == nil {
@ -357,6 +377,20 @@ func CalcSize(t *Type) {
w = t.NumElem() * t.Elem().width
t.align = t.Elem().align
// ABIInternal only allows "trivial" arrays (i.e., length 0 or 1)
// to be passed by register.
switch t.NumElem() {
case 0:
t.intRegs = 0
t.floatRegs = 0
case 1:
t.intRegs = t.Elem().intRegs
t.floatRegs = t.Elem().floatRegs
default:
t.intRegs = math.MaxUint8
t.floatRegs = math.MaxUint8
}
case TSLICE:
if t.Elem() == nil {
break
@ -364,6 +398,7 @@ func CalcSize(t *Type) {
w = SliceSize
CheckSize(t.Elem())
t.align = uint8(PtrSize)
t.intRegs = 3
case TSTRUCT:
if t.IsFuncArgStruct() {
@ -378,6 +413,7 @@ func CalcSize(t *Type) {
t1 := NewFuncArgs(t)
CheckSize(t1)
w = int64(PtrSize) // width of func type is pointer
t.intRegs = 1
// function is 3 cated structures;
// compute their widths as side-effect.
@ -411,7 +447,7 @@ func CalcSize(t *Type) {
}
// CalcStructSize calculates the size of t,
// filling in t.width and t.align,
// filling in t.width, t.align, t.intRegs, and t.floatRegs,
// even if size calculation is otherwise disabled.
func CalcStructSize(t *Type) {
var maxAlign uint8 = 1
@ -438,19 +474,34 @@ func CalcStructSize(t *Type) {
size++
}
var intRegs, floatRegs uint64
for _, field := range fields {
typ := field.Type
// The alignment of a struct type is the maximum alignment of its
// field types.
for _, field := range fields {
if align := field.Type.align; align > maxAlign {
if align := typ.align; align > maxAlign {
maxAlign = align
}
// Each field needs its own registers.
// We sum in uint64 to avoid possible overflows.
intRegs += uint64(typ.intRegs)
floatRegs += uint64(typ.floatRegs)
}
// Final size includes trailing padding.
size = RoundUp(size, int64(maxAlign))
if intRegs > math.MaxUint8 || floatRegs > math.MaxUint8 {
intRegs = math.MaxUint8
floatRegs = math.MaxUint8
}
t.width = size
t.align = maxAlign
t.intRegs = uint8(intRegs)
t.floatRegs = uint8(floatRegs)
}
func (t *Type) widthCalculated() bool {

View File

@ -21,7 +21,7 @@ func TestSizeof(t *testing.T) {
_64bit uintptr // size on 64bit platforms
}{
{Sym{}, 32, 64},
{Type{}, 52, 96},
{Type{}, 56, 96},
{Map{}, 12, 24},
{Forward{}, 20, 32},
{Func{}, 32, 56},

View File

@ -198,6 +198,8 @@ type Type struct {
kind Kind // kind of type
align uint8 // the required alignment of this type, in bytes (0 means Width and Align have not yet been computed)
intRegs, floatRegs uint8 // registers needed for ABIInternal
flags bitset8
// For defined (named) generic types, a pointer to the list of type params
@ -211,6 +213,17 @@ type Type struct {
rparams *[]*Type
}
// Registers returns the number of integer and floating-point
// registers required to represent a parameter of this type under the
// ABIInternal calling conventions.
//
// If t must be passed by memory, Registers returns (math.MaxUint8,
// math.MaxUint8).
func (t *Type) Registers() (uint8, uint8) {
CalcSize(t)
return t.intRegs, t.floatRegs
}
func (*Type) CanBeAnSSAAux() {}
const (
@ -637,6 +650,7 @@ func NewPtr(elem *Type) *Type {
t.extra = Ptr{Elem: elem}
t.width = int64(PtrSize)
t.align = uint8(PtrSize)
t.intRegs = 1
if NewPtrCacheEnabled {
elem.cache.ptr = t
}
@ -1628,6 +1642,8 @@ func (t *Type) SetUnderlying(underlying *Type) {
t.extra = underlying.extra
t.width = underlying.width
t.align = underlying.align
t.intRegs = underlying.intRegs
t.floatRegs = underlying.floatRegs
t.underlying = underlying.underlying
if underlying.NotInHeap() {