]> Cypherpunks repositories - gostls13.git/commitdiff
Revert "cmd/compile: allow multi-field structs to be stored directly in interfaces"
authorKeith Randall <khr@golang.org>
Tue, 12 Aug 2025 00:32:05 +0000 (17:32 -0700)
committerGopher Robot <gobot@golang.org>
Tue, 12 Aug 2025 05:59:52 +0000 (22:59 -0700)
This reverts commit cd55f86b8dcfc139ee5c17d32530ac9e758c8bc0 (CL 681937)

Reason for revert: still causing compiler failures on Google test code

Change-Id: I5cd482fd607fd060a523257082d48821b5f965d6
Reviewed-on: https://go-review.googlesource.com/c/go/+/695016
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
src/cmd/compile/internal/ssa/_gen/generic.rules
src/cmd/compile/internal/ssa/expand_calls.go
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewritegeneric.go
src/cmd/compile/internal/types/type.go
src/internal/abi/type.go
src/reflect/type.go

index 8f354e977f9af2968c64e0b7cc9a1d71c2b8f1d8..7ac36c3b3cd3911ad07cf9a21d3737b562ae655f 100644 (file)
   @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
 
 // Putting struct{*byte} and similar into direct interfaces.
-(IMake _typ (StructMake val)) => imakeOfStructMake(v)
-(StructSelect [_] (IData x)) => (IData x)
+(IMake _typ (StructMake val)) => (IMake _typ val)
+(StructSelect [0] (IData x)) => (IData x)
 
 // un-SSAable values use mem->mem copies
 (Store {t} dst (Load src mem) mem) && !CanSSA(t) =>
index 1730dbf53deacfb1a1a9392bca2080bc041b5799..f6bb863c001798d97497ef5a12fd75db90c97795 100644 (file)
@@ -423,14 +423,7 @@ func (x *expandState) decomposeAsNecessary(pos src.XPos, b *Block, a, m0 *Value,
                if a.Op == OpIMake {
                        data := a.Args[1]
                        for data.Op == OpStructMake || data.Op == OpArrayMake1 {
-                               // A struct make might have a few zero-sized fields.
-                               // Use the pointer-y one we know is there.
-                               for _, a := range data.Args {
-                                       if a.Type.Size() > 0 {
-                                               data = a
-                                               break
-                                       }
-                               }
+                               data = data.Args[0]
                        }
                        return x.decomposeAsNecessary(pos, b, data, mem, rc.next(data.Type))
                }
index 03b1e39b741ebc55bd44f72c8f658ffb76c14d9a..22399275212381439eef6fe3a8ed68b26ae73574 100644 (file)
@@ -2621,17 +2621,3 @@ func panicBoundsCToAux(p PanicBoundsC) Aux {
 func panicBoundsCCToAux(p PanicBoundsCC) Aux {
        return p
 }
-
-// When v is (IMake typ (StructMake ...)), convert to
-// (IMake typ arg) where arg is the pointer-y argument to
-// the StructMake (there must be exactly one).
-func imakeOfStructMake(v *Value) *Value {
-       var arg *Value
-       for _, a := range v.Args[1].Args {
-               if a.Type.Size() > 0 {
-                       arg = a
-                       break
-               }
-       }
-       return v.Block.NewValue2(v.Pos, OpIMake, v.Type, v.Args[0], arg)
-}
index 83be129a7bc49b66ca025d3ce95a95a9d4706e34..3af7f40e684f912f5a74a12173add3c5209a7f82 100644 (file)
@@ -11201,12 +11201,15 @@ func rewriteValuegeneric_OpIMake(v *Value) bool {
        v_1 := v.Args[1]
        v_0 := v.Args[0]
        // match: (IMake _typ (StructMake val))
-       // result: imakeOfStructMake(v)
+       // result: (IMake _typ val)
        for {
+               _typ := v_0
                if v_1.Op != OpStructMake || len(v_1.Args) != 1 {
                        break
                }
-               v.copyOf(imakeOfStructMake(v))
+               val := v_1.Args[0]
+               v.reset(OpIMake)
+               v.AddArg2(_typ, val)
                return true
        }
        // match: (IMake _typ (ArrayMake1 val))
@@ -32042,10 +32045,10 @@ func rewriteValuegeneric_OpStructSelect(v *Value) bool {
                v0.AddArg2(v1, mem)
                return true
        }
-       // match: (StructSelect [_] (IData x))
+       // match: (StructSelect [0] (IData x))
        // result: (IData x)
        for {
-               if v_0.Op != OpIData {
+               if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpIData {
                        break
                }
                x := v_0.Args[0]
index f28490fc446d3ee0d09ad8855c30396e74bc4472..6a3e9b512e72d54fbf280bf8caf1488b2d7f2be5 100644 (file)
@@ -1822,7 +1822,26 @@ func IsReflexive(t *Type) bool {
 // Can this type be stored directly in an interface word?
 // Yes, if the representation is a single pointer.
 func IsDirectIface(t *Type) bool {
-       return t.Size() == int64(PtrSize) && PtrDataSize(t) == int64(PtrSize)
+       switch t.Kind() {
+       case TPTR:
+               // Pointers to notinheap types must be stored indirectly. See issue 42076.
+               return !t.Elem().NotInHeap()
+       case TCHAN,
+               TMAP,
+               TFUNC,
+               TUNSAFEPTR:
+               return true
+
+       case TARRAY:
+               // Array of 1 direct iface type can be direct.
+               return t.NumElem() == 1 && IsDirectIface(t.Elem())
+
+       case TSTRUCT:
+               // Struct with 1 field of direct iface type can be direct.
+               return t.NumFields() == 1 && IsDirectIface(t.Field(0).Type)
+       }
+
+       return false
 }
 
 // IsInterfaceMethod reports whether (field) m is
index 9f783a34c13346cce4e91b383af528d994834237..1920a8a37fb25530f64d63a8923d524b8d713689 100644 (file)
@@ -121,8 +121,8 @@ const (
        TFlagGCMaskOnDemand TFlag = 1 << 4
 
        // TFlagDirectIface means that a value of this type is stored directly
-       // in the data field of an interface, instead of indirectly.
-       // This flag is just a cached computation of Size_ == PtrBytes == goarch.PtrSize.
+       // in the data field of an interface, instead of indirectly. Normally
+       // this means the type is pointer-ish.
        TFlagDirectIface TFlag = 1 << 5
 
        // Leaving this breadcrumb behind for dlv. It should not be used, and no
index 19a28abfcfef1694cc9df49c2eaa1efa9b8f12a6..cec8662c01a28d687e304c09736bb3faab53821e 100644 (file)
@@ -2524,7 +2524,8 @@ func StructOf(fields []StructField) Type {
        }
 
        switch {
-       case typ.Size_ == goarch.PtrSize && typ.PtrBytes == goarch.PtrSize:
+       case len(fs) == 1 && fs[0].Typ.IsDirectIface():
+               // structs of 1 direct iface type can be direct
                typ.TFlag |= abi.TFlagDirectIface
        default:
                typ.TFlag &^= abi.TFlagDirectIface
@@ -2693,7 +2694,8 @@ func ArrayOf(length int, elem Type) Type {
        }
 
        switch {
-       case array.Size_ == goarch.PtrSize && array.PtrBytes == goarch.PtrSize:
+       case length == 1 && typ.IsDirectIface():
+               // array of 1 direct iface type can be direct
                array.TFlag |= abi.TFlagDirectIface
        default:
                array.TFlag &^= abi.TFlagDirectIface