]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types: add Type.Registers
authorMatthew Dempsky <mdempsky@google.com>
Tue, 12 Sep 2023 03:19:46 +0000 (20:19 -0700)
committerGopher Robot <gobot@golang.org>
Wed, 13 Sep 2023 18:33:58 +0000 (18:33 +0000)
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>

src/cmd/compile/internal/types/size.go
src/cmd/compile/internal/types/sizeof_test.go
src/cmd/compile/internal/types/type.go

index 9e38b8c0d106662a2c5027ef600896084d169ce9..6ba2b9153b13d3c64a8c568d27e5afa7875c3461 100644 (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++
        }
 
-       // The alignment of a struct type is the maximum alignment of its
-       // field types.
+       var intRegs, floatRegs uint64
        for _, field := range fields {
-               if align := field.Type.align; align > maxAlign {
+               typ := field.Type
+
+               // The alignment of a struct type is the maximum alignment of its
+               // field types.
+               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 {
index a06ab0d18c6cfd8170f1d8fb5b7bc8c9abeb84bf..8a6f24124a88960ec70f4cf9159df441d0601391 100644 (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},
index 49ac5d7b1c1e653109c48965fb16cc4e09dd6044..3655c5db022ea16061b5ad0e73c874510495e07b 100644 (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() {