diff options
| author | David Chase <drchase@google.com> | 2020-10-02 14:53:48 -0400 |
|---|---|---|
| committer | David Chase <drchase@google.com> | 2020-10-06 15:37:42 +0000 |
| commit | f8d80977b784fd4879963e61dc9fca1fc9bf2193 (patch) | |
| tree | 27a7b8f1fef2f0cd1c61cc20ab83a14eb0811003 /src | |
| parent | d2a80f3fb5b44450e0b304ac5a718f99c053d82a (diff) | |
| download | go-f8d80977b784fd4879963e61dc9fca1fc9bf2193.tar.xz | |
cmd/compile: correct leaf type when "selecting" singleton register-sized struct
Two part fix:
1) bring the type "correction" forward from a later CL in the expand calls series
2) when a leaf-selwect is rewritten in place, update the type (it might have been
changed by the type correction in 1).
Fixes #41736.
Change-Id: Id097efd10481bf0ad92aaead81a7207221c144b5
Reviewed-on: https://go-review.googlesource.com/c/go/+/259203
Trust: David Chase <drchase@google.com>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/compile/internal/ssa/config.go | 2 | ||||
| -rw-r--r-- | src/cmd/compile/internal/ssa/expand_calls.go | 41 |
2 files changed, 36 insertions, 7 deletions
diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 649b5ba820..f1a748309c 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -195,7 +195,7 @@ const ( ClassParamOut // return value ) -const go116lateCallExpansion = false +const go116lateCallExpansion = true // LateCallExpansionEnabledWithin returns true if late call expansion should be tested // within compilation of a function/method triggered by GOSSAHASH (defaults to "yes"). diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 7b1d656b64..992936b2d3 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -58,6 +58,29 @@ func expandCalls(f *Func) { return t.IsStruct() || t.IsArray() || regSize == 4 && t.Size() > 4 && t.IsInteger() } + // removeTrivialWrapperTypes unwraps layers of + // struct { singleField SomeType } and [1]SomeType + // until a non-wrapper type is reached. This is useful + // for working with assignments to/from interface data + // fields (either second operand to OpIMake or OpIData) + // where the wrapping or type conversion can be elided + // because of type conversions/assertions in source code + // that do not appear in SSA. + removeTrivialWrapperTypes := func(t *types.Type) *types.Type { + for { + if t.IsStruct() && t.NumFields() == 1 { + t = t.Field(0).Type + continue + } + if t.IsArray() && t.NumElem() == 1 { + t = t.Elem() + continue + } + break + } + return t + } + // Calls that need lowering have some number of inputs, including a memory input, // and produce a tuple of (value1, value2, ..., mem) where valueK may or may not be SSA-able. @@ -84,7 +107,7 @@ func expandCalls(f *Func) { // rewrite v as a Copy of call -- the replacement call will produce a mem. leaf.copyOf(call) } else { - leafType := leaf.Type + leafType := removeTrivialWrapperTypes(leaf.Type) pt := types.NewPtr(leafType) if canSSAType(leafType) { off := f.ConstOffPtrSP(pt, offset+aux.OffsetOfResult(which), sp) @@ -92,6 +115,7 @@ func expandCalls(f *Func) { if leaf.Block == call.Block { leaf.reset(OpLoad) leaf.SetArgs2(off, call) + leaf.Type = leafType } else { w := call.Block.NewValue2(leaf.Pos, OpLoad, leafType, off, call) leaf.copyOf(w) @@ -192,6 +216,13 @@ func expandCalls(f *Func) { case types.TARRAY: elt := t.Elem() + if src.Op == OpIData && t.NumElem() == 1 && t.Width == regSize && elt.Width == regSize { + t = removeTrivialWrapperTypes(t) + if t.Etype == types.TSTRUCT || t.Etype == types.TARRAY { + f.Fatalf("Did not expect to find IDATA-immediate with non-trivial struct/array in it") + } + break // handle the leaf type. + } for i := int64(0); i < t.NumElem(); i++ { sel := src.Block.NewValue1I(pos, OpArraySelect, elt, i, src) mem = splitStore(dst, sel, mem, v, elt, offset+i*elt.Width, firstStorePos) @@ -199,7 +230,7 @@ func expandCalls(f *Func) { } return mem case types.TSTRUCT: - if src.Op == OpIData && t.NumFields() == 1 && t.Field(0).Type.Width == t.Width && t.Width == regSize { + if src.Op == OpIData && t.NumFields() == 1 && t.Field(0).Type.Width == t.Width && t.Width == regSize { // This peculiar test deals with accesses to immediate interface data. // It works okay because everything is the same size. // Example code that triggers this can be found in go/constant/value.go, function ToComplex @@ -207,11 +238,9 @@ func expandCalls(f *Func) { // v121 (+882) = StaticLECall <floatVal,mem> {AuxCall{"".itof([intVal,0])[floatVal,8]}} [16] v119 v1 // This corresponds to the generic rewrite rule "(StructSelect [0] (IData x)) => (IData x)" // Guard against "struct{struct{*foo}}" - for t.Etype == types.TSTRUCT && t.NumFields() == 1 { - t = t.Field(0).Type - } + t = removeTrivialWrapperTypes(t) if t.Etype == types.TSTRUCT || t.Etype == types.TARRAY { - f.Fatalf("Did not expect to find IDATA-immediate with non-trivial struct in it") + f.Fatalf("Did not expect to find IDATA-immediate with non-trivial struct/array in it") } break // handle the leaf type. } |
