mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/compile: load properly constant values from itabs
While looking at the SSA of following code, i noticed that these rules do not work properly, and the types are loaded indirectly through an itab, instead of statically. type M interface{ M() } type A interface{ A() } type Impl struct{} func (*Impl) M() {} func (*Impl) A() {} func main() { var a M = &Impl{} a.(A).A() } Change-Id: Ia275993f81a2e7302102d4ff87ac28586023d13c GitHub-Last-Rev: 4bfc9019172929d0b0f1c8a1b7eb28cdbc9b87ef GitHub-Pull-Request: golang/go#71784 Reviewed-on: https://go-review.googlesource.com/c/go/+/649500 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
ba3f568988
commit
43e6525986
@ -2756,10 +2756,14 @@
|
||||
(RotateLeft(64|32|16|8) (RotateLeft(64|32|16|8) x c) d) && c.Type.Size() == 1 && d.Type.Size() == 1 => (RotateLeft(64|32|16|8) x (Add8 <c.Type> c d))
|
||||
|
||||
// Loading constant values from dictionaries and itabs.
|
||||
(Load <t> (OffPtr [off] (Addr {s} sb) ) _) && t.IsUintptr() && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <t> (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && t.IsUintptr() && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <t> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && t.IsUintptr() && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <t> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && t.IsUintptr() && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <typ.BytePtr> (OffPtr [off] (Addr {s} sb) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <typ.BytePtr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <typ.Uintptr> (OffPtr [off] (Addr {s} sb) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <typ.Uintptr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <typ.Uintptr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
(Load <typ.Uintptr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _) && isFixedSym(s, off) => (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
|
||||
// Loading constant values from runtime._type.hash.
|
||||
(Load <t> (OffPtr [off] (Addr {sym} _) ) _) && t.IsInteger() && t.Size() == 4 && isFixed32(config, sym, off) => (Const32 [fixed32(config, sym, off)])
|
||||
|
@ -13519,6 +13519,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
v_0 := v.Args[0]
|
||||
b := v.Block
|
||||
config := b.Func.Config
|
||||
typ := &b.Func.Config.Types
|
||||
// match: (Load <t1> p1 (Store {t2} p2 x _))
|
||||
// cond: isSamePtr(p1, p2) && t1.Compare(x.Type) == types.CMPeq && t1.Size() == t2.Size()
|
||||
// result: x
|
||||
@ -14103,12 +14104,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (Addr {s} sb) ) _)
|
||||
// cond: t.IsUintptr() && isFixedSym(s, off)
|
||||
// match: (Load <typ.BytePtr> (OffPtr [off] (Addr {s} sb) ) _)
|
||||
// cond: isFixedSym(s, off)
|
||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
for {
|
||||
t := v.Type
|
||||
if v_0.Op != OpOffPtr {
|
||||
if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
off := auxIntToInt64(v_0.AuxInt)
|
||||
@ -14118,7 +14118,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
}
|
||||
s := auxToSym(v_0_0.Aux)
|
||||
sb := v_0_0.Args[0]
|
||||
if !(t.IsUintptr() && isFixedSym(s, off)) {
|
||||
if !(isFixedSym(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
@ -14126,12 +14126,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
|
||||
// cond: t.IsUintptr() && isFixedSym(s, off)
|
||||
// match: (Load <typ.BytePtr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
|
||||
// cond: isFixedSym(s, off)
|
||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
for {
|
||||
t := v.Type
|
||||
if v_0.Op != OpOffPtr {
|
||||
if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
off := auxIntToInt64(v_0.AuxInt)
|
||||
@ -14145,7 +14144,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
}
|
||||
s := auxToSym(v_0_0_0.Aux)
|
||||
sb := v_0_0_0.Args[0]
|
||||
if !(t.IsUintptr() && isFixedSym(s, off)) {
|
||||
if !(isFixedSym(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
@ -14153,12 +14152,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
|
||||
// cond: t.IsUintptr() && isFixedSym(s, off)
|
||||
// match: (Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
|
||||
// cond: isFixedSym(s, off)
|
||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
for {
|
||||
t := v.Type
|
||||
if v_0.Op != OpOffPtr {
|
||||
if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
off := auxIntToInt64(v_0.AuxInt)
|
||||
@ -14176,7 +14174,7 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
}
|
||||
s := auxToSym(v_0_0_0_0.Aux)
|
||||
sb := v_0_0_0_0.Args[0]
|
||||
if !(t.IsUintptr() && isFixedSym(s, off)) {
|
||||
if !(isFixedSym(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
@ -14184,12 +14182,11 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
|
||||
// cond: t.IsUintptr() && isFixedSym(s, off)
|
||||
// match: (Load <typ.BytePtr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
|
||||
// cond: isFixedSym(s, off)
|
||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
for {
|
||||
t := v.Type
|
||||
if v_0.Op != OpOffPtr {
|
||||
if v.Type != typ.BytePtr || v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
off := auxIntToInt64(v_0.AuxInt)
|
||||
@ -14211,7 +14208,119 @@ func rewriteValuegeneric_OpLoad(v *Value) bool {
|
||||
}
|
||||
s := auxToSym(v_0_0_0_0_0.Aux)
|
||||
sb := v_0_0_0_0_0.Args[0]
|
||||
if !(t.IsUintptr() && isFixedSym(s, off)) {
|
||||
if !(isFixedSym(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, off))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.Uintptr> (OffPtr [off] (Addr {s} sb) ) _)
|
||||
// cond: isFixedSym(s, off)
|
||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
for {
|
||||
if v.Type != typ.Uintptr || v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
off := auxIntToInt64(v_0.AuxInt)
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
s := auxToSym(v_0_0.Aux)
|
||||
sb := v_0_0.Args[0]
|
||||
if !(isFixedSym(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, off))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.Uintptr> (OffPtr [off] (Convert (Addr {s} sb) _) ) _)
|
||||
// cond: isFixedSym(s, off)
|
||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
for {
|
||||
if v.Type != typ.Uintptr || v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
off := auxIntToInt64(v_0.AuxInt)
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpConvert {
|
||||
break
|
||||
}
|
||||
v_0_0_0 := v_0_0.Args[0]
|
||||
if v_0_0_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
s := auxToSym(v_0_0_0.Aux)
|
||||
sb := v_0_0_0.Args[0]
|
||||
if !(isFixedSym(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, off))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.Uintptr> (OffPtr [off] (ITab (IMake (Addr {s} sb) _))) _)
|
||||
// cond: isFixedSym(s, off)
|
||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
for {
|
||||
if v.Type != typ.Uintptr || v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
off := auxIntToInt64(v_0.AuxInt)
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpITab {
|
||||
break
|
||||
}
|
||||
v_0_0_0 := v_0_0.Args[0]
|
||||
if v_0_0_0.Op != OpIMake {
|
||||
break
|
||||
}
|
||||
v_0_0_0_0 := v_0_0_0.Args[0]
|
||||
if v_0_0_0_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
s := auxToSym(v_0_0_0_0.Aux)
|
||||
sb := v_0_0_0_0.Args[0]
|
||||
if !(isFixedSym(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
v.Aux = symToAux(fixedSym(b.Func, s, off))
|
||||
v.AddArg(sb)
|
||||
return true
|
||||
}
|
||||
// match: (Load <typ.Uintptr> (OffPtr [off] (ITab (IMake (Convert (Addr {s} sb) _) _))) _)
|
||||
// cond: isFixedSym(s, off)
|
||||
// result: (Addr {fixedSym(b.Func, s, off)} sb)
|
||||
for {
|
||||
if v.Type != typ.Uintptr || v_0.Op != OpOffPtr {
|
||||
break
|
||||
}
|
||||
off := auxIntToInt64(v_0.AuxInt)
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpITab {
|
||||
break
|
||||
}
|
||||
v_0_0_0 := v_0_0.Args[0]
|
||||
if v_0_0_0.Op != OpIMake {
|
||||
break
|
||||
}
|
||||
v_0_0_0_0 := v_0_0_0.Args[0]
|
||||
if v_0_0_0_0.Op != OpConvert {
|
||||
break
|
||||
}
|
||||
v_0_0_0_0_0 := v_0_0_0_0.Args[0]
|
||||
if v_0_0_0_0_0.Op != OpAddr {
|
||||
break
|
||||
}
|
||||
s := auxToSym(v_0_0_0_0_0.Aux)
|
||||
sb := v_0_0_0_0_0.Args[0]
|
||||
if !(isFixedSym(s, off)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAddr)
|
||||
|
24
test/codegen/load_type_from_itab.go
Normal file
24
test/codegen/load_type_from_itab.go
Normal file
@ -0,0 +1,24 @@
|
||||
// asmcheck
|
||||
|
||||
// Copyright 2025 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.
|
||||
|
||||
// This test makes sure that we statically load a type from an itab, instead
|
||||
// of doing a indirect load from thet itab.
|
||||
|
||||
package codegen
|
||||
|
||||
type M interface{ M() }
|
||||
type A interface{ A() }
|
||||
|
||||
type Impl struct{}
|
||||
|
||||
func (*Impl) M() {}
|
||||
func (*Impl) A() {}
|
||||
|
||||
func main() {
|
||||
var a M = &Impl{}
|
||||
// amd64:`LEAQ\ttype:.*Impl`
|
||||
a.(A).A()
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user