mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: initialize ACArgs and ACResults AuxCall fields for static and interface calls.
Extend use of AuxCall Change-Id: I68b6d9bad09506532e1415fd70d44cf6c15b4b93 Reviewed-on: https://go-review.googlesource.com/c/go/+/239081 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>
This commit is contained in:
parent
3c85e995ef
commit
acde81e0a9
7 changed files with 102 additions and 29 deletions
|
|
@ -4280,16 +4280,20 @@ func (s *state) openDeferExit() {
|
||||||
argStart := Ctxt.FixedFrameSize()
|
argStart := Ctxt.FixedFrameSize()
|
||||||
fn := r.n.Left
|
fn := r.n.Left
|
||||||
stksize := fn.Type.ArgWidth()
|
stksize := fn.Type.ArgWidth()
|
||||||
|
var ACArgs []ssa.Param
|
||||||
|
var ACResults []ssa.Param
|
||||||
if r.rcvr != nil {
|
if r.rcvr != nil {
|
||||||
// rcvr in case of OCALLINTER
|
// rcvr in case of OCALLINTER
|
||||||
v := s.load(r.rcvr.Type.Elem(), r.rcvr)
|
v := s.load(r.rcvr.Type.Elem(), r.rcvr)
|
||||||
addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart)
|
addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart)
|
||||||
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart)})
|
||||||
s.store(types.Types[TUINTPTR], addr, v)
|
s.store(types.Types[TUINTPTR], addr, v)
|
||||||
}
|
}
|
||||||
for j, argAddrVal := range r.argVals {
|
for j, argAddrVal := range r.argVals {
|
||||||
f := getParam(r.n, j)
|
f := getParam(r.n, j)
|
||||||
pt := types.NewPtr(f.Type)
|
pt := types.NewPtr(f.Type)
|
||||||
addr := s.constOffPtrSP(pt, argStart+f.Offset)
|
addr := s.constOffPtrSP(pt, argStart+f.Offset)
|
||||||
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart + f.Offset)})
|
||||||
if !canSSAType(f.Type) {
|
if !canSSAType(f.Type) {
|
||||||
s.move(f.Type, addr, argAddrVal)
|
s.move(f.Type, addr, argAddrVal)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -4305,7 +4309,7 @@ func (s *state) openDeferExit() {
|
||||||
call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, v, s.mem())
|
call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, v, s.mem())
|
||||||
} else {
|
} else {
|
||||||
// Do a static call if the original call was a static function or method
|
// Do a static call if the original call was a static function or method
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn.Sym.Linksym()), s.mem())
|
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn.Sym.Linksym(), ACArgs, ACResults), s.mem())
|
||||||
}
|
}
|
||||||
call.AuxInt = stksize
|
call.AuxInt = stksize
|
||||||
s.vars[&memVar] = call
|
s.vars[&memVar] = call
|
||||||
|
|
@ -4340,6 +4344,17 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||||
var codeptr *ssa.Value // ptr to target code (if dynamic)
|
var codeptr *ssa.Value // ptr to target code (if dynamic)
|
||||||
var rcvr *ssa.Value // receiver to set
|
var rcvr *ssa.Value // receiver to set
|
||||||
fn := n.Left
|
fn := n.Left
|
||||||
|
var ACArgs []ssa.Param
|
||||||
|
var ACResults []ssa.Param
|
||||||
|
res := n.Left.Type.Results()
|
||||||
|
if k == callNormal {
|
||||||
|
nf := res.NumFields()
|
||||||
|
for i := 0; i < nf; i++ {
|
||||||
|
fp := res.Field(i)
|
||||||
|
ACResults = append(ACResults, ssa.Param{Type: fp.Type, Offset: int32(fp.Offset + Ctxt.FixedFrameSize())})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OCALLFUNC:
|
case OCALLFUNC:
|
||||||
if k == callNormal && fn.Op == ONAME && fn.Class() == PFUNC {
|
if k == callNormal && fn.Op == ONAME && fn.Class() == PFUNC {
|
||||||
|
|
@ -4437,10 +4452,12 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||||
// Call runtime.deferprocStack with pointer to _defer record.
|
// Call runtime.deferprocStack with pointer to _defer record.
|
||||||
arg0 := s.constOffPtrSP(types.Types[TUINTPTR], Ctxt.FixedFrameSize())
|
arg0 := s.constOffPtrSP(types.Types[TUINTPTR], Ctxt.FixedFrameSize())
|
||||||
s.store(types.Types[TUINTPTR], arg0, addr)
|
s.store(types.Types[TUINTPTR], arg0, addr)
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferprocStack), s.mem())
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(Ctxt.FixedFrameSize())})
|
||||||
|
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferprocStack, ACArgs, ACResults), s.mem())
|
||||||
if stksize < int64(Widthptr) {
|
if stksize < int64(Widthptr) {
|
||||||
// We need room for both the call to deferprocStack and the call to
|
// We need room for both the call to deferprocStack and the call to
|
||||||
// the deferred function.
|
// the deferred function.
|
||||||
|
// TODO Revisit this if/when we pass args in registers.
|
||||||
stksize = int64(Widthptr)
|
stksize = int64(Widthptr)
|
||||||
}
|
}
|
||||||
call.AuxInt = stksize
|
call.AuxInt = stksize
|
||||||
|
|
@ -4453,8 +4470,10 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||||
// Write argsize and closure (args to newproc/deferproc).
|
// Write argsize and closure (args to newproc/deferproc).
|
||||||
argsize := s.constInt32(types.Types[TUINT32], int32(stksize))
|
argsize := s.constInt32(types.Types[TUINT32], int32(stksize))
|
||||||
addr := s.constOffPtrSP(s.f.Config.Types.UInt32Ptr, argStart)
|
addr := s.constOffPtrSP(s.f.Config.Types.UInt32Ptr, argStart)
|
||||||
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINT32], Offset: int32(argStart)})
|
||||||
s.store(types.Types[TUINT32], addr, argsize)
|
s.store(types.Types[TUINT32], addr, argsize)
|
||||||
addr = s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart+int64(Widthptr))
|
addr = s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart+int64(Widthptr))
|
||||||
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart) + int32(Widthptr)})
|
||||||
s.store(types.Types[TUINTPTR], addr, closure)
|
s.store(types.Types[TUINTPTR], addr, closure)
|
||||||
stksize += 2 * int64(Widthptr)
|
stksize += 2 * int64(Widthptr)
|
||||||
argStart += 2 * int64(Widthptr)
|
argStart += 2 * int64(Widthptr)
|
||||||
|
|
@ -4463,6 +4482,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||||
// Set receiver (for interface calls).
|
// Set receiver (for interface calls).
|
||||||
if rcvr != nil {
|
if rcvr != nil {
|
||||||
addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart)
|
addr := s.constOffPtrSP(s.f.Config.Types.UintptrPtr, argStart)
|
||||||
|
ACArgs = append(ACArgs, ssa.Param{Type: types.Types[TUINTPTR], Offset: int32(argStart)})
|
||||||
s.store(types.Types[TUINTPTR], addr, rcvr)
|
s.store(types.Types[TUINTPTR], addr, rcvr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4471,20 +4491,20 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||||
args := n.Rlist.Slice()
|
args := n.Rlist.Slice()
|
||||||
if n.Op == OCALLMETH {
|
if n.Op == OCALLMETH {
|
||||||
f := t.Recv()
|
f := t.Recv()
|
||||||
s.storeArg(args[0], f.Type, argStart+f.Offset)
|
ACArgs = append(ACArgs, s.storeArg(args[0], f.Type, argStart+f.Offset))
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
}
|
}
|
||||||
for i, n := range args {
|
for i, n := range args {
|
||||||
f := t.Params().Field(i)
|
f := t.Params().Field(i)
|
||||||
s.storeArg(n, f.Type, argStart+f.Offset)
|
ACArgs = append(ACArgs, s.storeArg(n, f.Type, argStart+f.Offset))
|
||||||
}
|
}
|
||||||
|
|
||||||
// call target
|
// call target
|
||||||
switch {
|
switch {
|
||||||
case k == callDefer:
|
case k == callDefer:
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferproc), s.mem())
|
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(deferproc, ACArgs, ACResults), s.mem())
|
||||||
case k == callGo:
|
case k == callGo:
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(newproc), s.mem())
|
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(newproc, ACArgs, ACResults), s.mem())
|
||||||
case closure != nil:
|
case closure != nil:
|
||||||
// rawLoad because loading the code pointer from a
|
// rawLoad because loading the code pointer from a
|
||||||
// closure is always safe, but IsSanitizerSafeAddr
|
// closure is always safe, but IsSanitizerSafeAddr
|
||||||
|
|
@ -4494,9 +4514,9 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||||
codeptr = s.rawLoad(types.Types[TUINTPTR], closure)
|
codeptr = s.rawLoad(types.Types[TUINTPTR], closure)
|
||||||
call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, closure, s.mem())
|
call = s.newValue3A(ssa.OpClosureCall, types.TypeMem, ssa.ClosureAuxCall(), codeptr, closure, s.mem())
|
||||||
case codeptr != nil:
|
case codeptr != nil:
|
||||||
call = s.newValue2A(ssa.OpInterCall, types.TypeMem, ssa.InterfaceAuxCall(), codeptr, s.mem())
|
call = s.newValue2A(ssa.OpInterCall, types.TypeMem, ssa.InterfaceAuxCall(ACArgs, ACResults), codeptr, s.mem())
|
||||||
case sym != nil:
|
case sym != nil:
|
||||||
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(sym.Linksym()), s.mem())
|
call = s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(sym.Linksym(), ACArgs, ACResults), s.mem())
|
||||||
default:
|
default:
|
||||||
s.Fatalf("bad call type %v %v", n.Op, n)
|
s.Fatalf("bad call type %v %v", n.Op, n)
|
||||||
}
|
}
|
||||||
|
|
@ -4522,7 +4542,6 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||||
s.startBlock(bNext)
|
s.startBlock(bNext)
|
||||||
}
|
}
|
||||||
|
|
||||||
res := n.Left.Type.Results()
|
|
||||||
if res.NumFields() == 0 || k != callNormal {
|
if res.NumFields() == 0 || k != callNormal {
|
||||||
// call has no return value. Continue with the next statement.
|
// call has no return value. Continue with the next statement.
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -4918,18 +4937,29 @@ func (s *state) intDivide(n *Node, a, b *ssa.Value) *ssa.Value {
|
||||||
func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args ...*ssa.Value) []*ssa.Value {
|
func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args ...*ssa.Value) []*ssa.Value {
|
||||||
// Write args to the stack
|
// Write args to the stack
|
||||||
off := Ctxt.FixedFrameSize()
|
off := Ctxt.FixedFrameSize()
|
||||||
|
var ACArgs []ssa.Param
|
||||||
|
var ACResults []ssa.Param
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
t := arg.Type
|
t := arg.Type
|
||||||
off = Rnd(off, t.Alignment())
|
off = Rnd(off, t.Alignment())
|
||||||
ptr := s.constOffPtrSP(t.PtrTo(), off)
|
ptr := s.constOffPtrSP(t.PtrTo(), off)
|
||||||
size := t.Size()
|
size := t.Size()
|
||||||
|
ACArgs = append(ACArgs, ssa.Param{Type: t, Offset: int32(off)})
|
||||||
s.store(t, ptr, arg)
|
s.store(t, ptr, arg)
|
||||||
off += size
|
off += size
|
||||||
}
|
}
|
||||||
off = Rnd(off, int64(Widthreg))
|
off = Rnd(off, int64(Widthreg))
|
||||||
|
|
||||||
|
// Accumulate results types and offsets
|
||||||
|
offR := off
|
||||||
|
for _, t := range results {
|
||||||
|
offR = Rnd(offR, t.Alignment())
|
||||||
|
ACResults = append(ACResults, ssa.Param{Type: t, Offset: int32(offR)})
|
||||||
|
offR += t.Size()
|
||||||
|
}
|
||||||
|
|
||||||
// Issue call
|
// Issue call
|
||||||
call := s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn), s.mem())
|
call := s.newValue1A(ssa.OpStaticCall, types.TypeMem, ssa.StaticAuxCall(fn, ACArgs, ACResults), s.mem())
|
||||||
s.vars[&memVar] = call
|
s.vars[&memVar] = call
|
||||||
|
|
||||||
if !returns {
|
if !returns {
|
||||||
|
|
@ -5064,8 +5094,9 @@ func (s *state) storeTypePtrs(t *types.Type, left, right *ssa.Value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *state) storeArg(n *Node, t *types.Type, off int64) {
|
func (s *state) storeArg(n *Node, t *types.Type, off int64) ssa.Param {
|
||||||
s.storeArgWithBase(n, t, s.sp, off)
|
s.storeArgWithBase(n, t, s.sp, off)
|
||||||
|
return ssa.Param{Type: t, Offset: int32(off)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *state) storeArgWithBase(n *Node, t *types.Type, base *ssa.Value, off int64) {
|
func (s *state) storeArgWithBase(n *Node, t *types.Type, base *ssa.Value, off int64) {
|
||||||
|
|
|
||||||
|
|
@ -2021,8 +2021,8 @@
|
||||||
// Note that (ITab (IMake)) doesn't get
|
// Note that (ITab (IMake)) doesn't get
|
||||||
// rewritten until after the first opt pass,
|
// rewritten until after the first opt pass,
|
||||||
// so this rule should trigger reliably.
|
// so this rule should trigger reliably.
|
||||||
(InterCall [argsize] (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem) && devirt(v, itab, off) != nil =>
|
(InterCall [argsize] {auxCall} (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem) && devirt(v, auxCall, itab, off) != nil =>
|
||||||
(StaticCall [int32(argsize)] {devirt(v, itab, off)} mem)
|
(StaticCall [int32(argsize)] {devirt(v, auxCall, itab, off)} mem)
|
||||||
|
|
||||||
// Move and Zero optimizations.
|
// Move and Zero optimizations.
|
||||||
// Move source and destination may overlap.
|
// Move source and destination may overlap.
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,7 @@ func insertLoopReschedChecks(f *Func) {
|
||||||
// mem1 := call resched (mem0)
|
// mem1 := call resched (mem0)
|
||||||
// goto header
|
// goto header
|
||||||
resched := f.fe.Syslook("goschedguarded")
|
resched := f.fe.Syslook("goschedguarded")
|
||||||
mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, StaticAuxCall(resched), mem0)
|
mem1 := sched.NewValue1A(bb.Pos, OpStaticCall, types.TypeMem, StaticAuxCall(resched, nil, nil), mem0)
|
||||||
sched.AddEdgeTo(h)
|
sched.AddEdgeTo(h)
|
||||||
headerMemPhi.AddArg(mem1)
|
headerMemPhi.AddArg(mem1)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package ssa
|
package ssa
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
@ -67,25 +68,60 @@ type regInfo struct {
|
||||||
|
|
||||||
type auxType int8
|
type auxType int8
|
||||||
|
|
||||||
|
type Param struct {
|
||||||
|
Type *types.Type
|
||||||
|
Offset int32 // TODO someday this will be a register
|
||||||
|
}
|
||||||
|
|
||||||
type AuxCall struct {
|
type AuxCall struct {
|
||||||
Fn *obj.LSym
|
Fn *obj.LSym
|
||||||
|
args []Param // Includes receiver for method calls. Does NOT include hidden closure pointer.
|
||||||
|
results []Param
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AuxCall) String() string {
|
func (a *AuxCall) String() string {
|
||||||
|
var fn string
|
||||||
if a.Fn == nil {
|
if a.Fn == nil {
|
||||||
return "AuxCall(nil)"
|
fn = "AuxCall{nil" // could be interface/closure etc.
|
||||||
|
} else {
|
||||||
|
fn = fmt.Sprintf("AuxCall{%v", a.Fn)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("AuxCall(%v)", a.Fn)
|
|
||||||
|
if len(a.args) == 0 {
|
||||||
|
fn += "()"
|
||||||
|
} else {
|
||||||
|
s := "("
|
||||||
|
for _, arg := range a.args {
|
||||||
|
fn += fmt.Sprintf("%s[%v,%v]", s, arg.Type, arg.Offset)
|
||||||
|
s = ","
|
||||||
|
}
|
||||||
|
fn += ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(a.results) > 0 { // usual is zero or one; only some RT calls have more than one.
|
||||||
|
if len(a.results) == 1 {
|
||||||
|
fn += fmt.Sprintf("[%v,%v]", a.results[0].Type, a.results[0].Offset)
|
||||||
|
} else {
|
||||||
|
s := "("
|
||||||
|
for _, result := range a.results {
|
||||||
|
fn += fmt.Sprintf("%s[%v,%v]", s, result.Type, result.Offset)
|
||||||
|
s = ","
|
||||||
|
}
|
||||||
|
fn += ")"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn + "}"
|
||||||
}
|
}
|
||||||
|
|
||||||
// StaticAuxCall returns an AuxCall for a static call.
|
// StaticAuxCall returns an AuxCall for a static call.
|
||||||
func StaticAuxCall(sym *obj.LSym) *AuxCall {
|
func StaticAuxCall(sym *obj.LSym, args []Param, results []Param) *AuxCall {
|
||||||
return &AuxCall{Fn: sym}
|
return &AuxCall{Fn: sym, args: args, results: results}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InterfaceAuxCall returns an AuxCall for an interface call.
|
// InterfaceAuxCall returns an AuxCall for an interface call.
|
||||||
func InterfaceAuxCall() *AuxCall {
|
func InterfaceAuxCall(args []Param, results []Param) *AuxCall {
|
||||||
return &AuxCall{}
|
return &AuxCall{Fn: nil, args: args, results: results}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClosureAuxCall returns an AuxCall for a closure call.
|
// ClosureAuxCall returns an AuxCall for a closure call.
|
||||||
|
|
|
||||||
|
|
@ -743,7 +743,7 @@ func uaddOvf(a, b int64) bool {
|
||||||
|
|
||||||
// de-virtualize an InterCall
|
// de-virtualize an InterCall
|
||||||
// 'sym' is the symbol for the itab
|
// 'sym' is the symbol for the itab
|
||||||
func devirt(v *Value, sym Sym, offset int64) *AuxCall {
|
func devirt(v *Value, aux interface{}, sym Sym, offset int64) *AuxCall {
|
||||||
f := v.Block.Func
|
f := v.Block.Func
|
||||||
n, ok := sym.(*obj.LSym)
|
n, ok := sym.(*obj.LSym)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -760,7 +760,8 @@ func devirt(v *Value, sym Sym, offset int64) *AuxCall {
|
||||||
if lsym == nil {
|
if lsym == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return StaticAuxCall(lsym)
|
va := aux.(*AuxCall)
|
||||||
|
return StaticAuxCall(lsym, va.args, va.results)
|
||||||
}
|
}
|
||||||
|
|
||||||
// isSamePtr reports whether p1 and p2 point to the same address.
|
// isSamePtr reports whether p1 and p2 point to the same address.
|
||||||
|
|
|
||||||
|
|
@ -8479,11 +8479,12 @@ func rewriteValuegeneric_OpIMake(v *Value) bool {
|
||||||
func rewriteValuegeneric_OpInterCall(v *Value) bool {
|
func rewriteValuegeneric_OpInterCall(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (InterCall [argsize] (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem)
|
// match: (InterCall [argsize] {auxCall} (Load (OffPtr [off] (ITab (IMake (Addr {itab} (SB)) _))) _) mem)
|
||||||
// cond: devirt(v, itab, off) != nil
|
// cond: devirt(v, auxCall, itab, off) != nil
|
||||||
// result: (StaticCall [int32(argsize)] {devirt(v, itab, off)} mem)
|
// result: (StaticCall [int32(argsize)] {devirt(v, auxCall, itab, off)} mem)
|
||||||
for {
|
for {
|
||||||
argsize := auxIntToInt32(v.AuxInt)
|
argsize := auxIntToInt32(v.AuxInt)
|
||||||
|
auxCall := auxToCall(v.Aux)
|
||||||
if v_0.Op != OpLoad {
|
if v_0.Op != OpLoad {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -8510,12 +8511,12 @@ func rewriteValuegeneric_OpInterCall(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
mem := v_1
|
mem := v_1
|
||||||
if !(devirt(v, itab, off) != nil) {
|
if !(devirt(v, auxCall, itab, off) != nil) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpStaticCall)
|
v.reset(OpStaticCall)
|
||||||
v.AuxInt = int32ToAuxInt(int32(argsize))
|
v.AuxInt = int32ToAuxInt(int32(argsize))
|
||||||
v.Aux = callToAux(devirt(v, itab, off))
|
v.Aux = callToAux(devirt(v, auxCall, itab, off))
|
||||||
v.AddArg(mem)
|
v.AddArg(mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -501,29 +501,33 @@ func wbcall(pos src.XPos, b *Block, fn, typ *obj.LSym, ptr, val, mem, sp, sb *Va
|
||||||
// put arguments on stack
|
// put arguments on stack
|
||||||
off := config.ctxt.FixedFrameSize()
|
off := config.ctxt.FixedFrameSize()
|
||||||
|
|
||||||
|
var ACArgs []Param
|
||||||
if typ != nil { // for typedmemmove
|
if typ != nil { // for typedmemmove
|
||||||
taddr := b.NewValue1A(pos, OpAddr, b.Func.Config.Types.Uintptr, typ, sb)
|
taddr := b.NewValue1A(pos, OpAddr, b.Func.Config.Types.Uintptr, typ, sb)
|
||||||
off = round(off, taddr.Type.Alignment())
|
off = round(off, taddr.Type.Alignment())
|
||||||
arg := b.NewValue1I(pos, OpOffPtr, taddr.Type.PtrTo(), off, sp)
|
arg := b.NewValue1I(pos, OpOffPtr, taddr.Type.PtrTo(), off, sp)
|
||||||
mem = b.NewValue3A(pos, OpStore, types.TypeMem, ptr.Type, arg, taddr, mem)
|
mem = b.NewValue3A(pos, OpStore, types.TypeMem, ptr.Type, arg, taddr, mem)
|
||||||
|
ACArgs = append(ACArgs, Param{Type: b.Func.Config.Types.Uintptr, Offset: int32(off)})
|
||||||
off += taddr.Type.Size()
|
off += taddr.Type.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
off = round(off, ptr.Type.Alignment())
|
off = round(off, ptr.Type.Alignment())
|
||||||
arg := b.NewValue1I(pos, OpOffPtr, ptr.Type.PtrTo(), off, sp)
|
arg := b.NewValue1I(pos, OpOffPtr, ptr.Type.PtrTo(), off, sp)
|
||||||
mem = b.NewValue3A(pos, OpStore, types.TypeMem, ptr.Type, arg, ptr, mem)
|
mem = b.NewValue3A(pos, OpStore, types.TypeMem, ptr.Type, arg, ptr, mem)
|
||||||
|
ACArgs = append(ACArgs, Param{Type: ptr.Type, Offset: int32(off)})
|
||||||
off += ptr.Type.Size()
|
off += ptr.Type.Size()
|
||||||
|
|
||||||
if val != nil {
|
if val != nil {
|
||||||
off = round(off, val.Type.Alignment())
|
off = round(off, val.Type.Alignment())
|
||||||
arg = b.NewValue1I(pos, OpOffPtr, val.Type.PtrTo(), off, sp)
|
arg = b.NewValue1I(pos, OpOffPtr, val.Type.PtrTo(), off, sp)
|
||||||
mem = b.NewValue3A(pos, OpStore, types.TypeMem, val.Type, arg, val, mem)
|
mem = b.NewValue3A(pos, OpStore, types.TypeMem, val.Type, arg, val, mem)
|
||||||
|
ACArgs = append(ACArgs, Param{Type: val.Type, Offset: int32(off)})
|
||||||
off += val.Type.Size()
|
off += val.Type.Size()
|
||||||
}
|
}
|
||||||
off = round(off, config.PtrSize)
|
off = round(off, config.PtrSize)
|
||||||
|
|
||||||
// issue call
|
// issue call
|
||||||
mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, StaticAuxCall(fn), mem)
|
mem = b.NewValue1A(pos, OpStaticCall, types.TypeMem, StaticAuxCall(fn, ACArgs, nil), mem)
|
||||||
mem.AuxInt = off - config.ctxt.FixedFrameSize()
|
mem.AuxInt = off - config.ctxt.FixedFrameSize()
|
||||||
return mem
|
return mem
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue