Skip to content

Commit

Permalink
[dev.regabi] cmd/compile: add ir.TailCallStmt
Browse files Browse the repository at this point in the history
This CL splits out ORETJMP as a new TailCallStmt node, separate from
the other BranchStmt nodes. In doing so, this allows us to change it
from identifying a function by *types.Sym to identifying one by
directly pointing to the *ir.Func.

While here, also rename the operation to OTAILCALL.

Passes toolstash -cmp.

Change-Id: I273e6ea5d92bf3005ae02fb59b3240a190a6cf1b
Reviewed-on: https://go-review.googlesource.com/c/go/+/284227
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
  • Loading branch information
mdempsky committed Jan 17, 2021
1 parent e3027c6 commit 87845d1
Show file tree
Hide file tree
Showing 14 changed files with 63 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/deadcode/deadcode.go
Expand Up @@ -75,7 +75,7 @@ func stmts(nn *ir.Nodes) {
// might be the target of a goto. See issue 28616.
if body := body; len(body) != 0 {
switch body[(len(body) - 1)].Op() {
case ir.ORETURN, ir.ORETJMP, ir.OPANIC:
case ir.ORETURN, ir.OTAILCALL, ir.OPANIC:
if i > lastLabel {
cut = true
}
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/escape/escape.go
Expand Up @@ -534,8 +534,8 @@ func (e *escape) stmt(n ir.Node) {
e.stmts(n.Call.Init())
e.call(nil, n.Call, n)

case ir.ORETJMP:
// TODO(mdempsky): What do? esc.go just ignores it.
case ir.OTAILCALL:
// TODO(mdempsky): Treat like a normal call? esc.go used to just ignore it.
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/inline/inl.go
Expand Up @@ -359,7 +359,7 @@ func (v *hairyVisitor) doNode(n ir.Node) error {
ir.OGO,
ir.ODEFER,
ir.ODCLTYPE, // can't print yet
ir.ORETJMP:
ir.OTAILCALL:
return errors.New("unhandled op " + n.Op().String())

case ir.OAPPEND:
Expand Down
6 changes: 3 additions & 3 deletions src/cmd/compile/internal/ir/fmt.go
Expand Up @@ -378,9 +378,9 @@ func stmtFmt(n Node, s fmt.State) {
n := n.(*ReturnStmt)
fmt.Fprintf(s, "return %.v", n.Results)

case ORETJMP:
n := n.(*BranchStmt)
fmt.Fprintf(s, "retjmp %v", n.Label)
case OTAILCALL:
n := n.(*TailCallStmt)
fmt.Fprintf(s, "tailcall %v", n.Target)

case OINLMARK:
n := n.(*InlineMarkStmt)
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/ir/node.go
Expand Up @@ -306,8 +306,8 @@ const (
OLINKSYMOFFSET // offset within a name

// arch-specific opcodes
ORETJMP // return to other function
OGETG // runtime.getg() (read g pointer)
OTAILCALL // tail call to another function
OGETG // runtime.getg() (read g pointer)

OEND
)
Expand Down
22 changes: 22 additions & 0 deletions src/cmd/compile/internal/ir/node_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/cmd/compile/internal/ir/op_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 18 additions & 4 deletions src/cmd/compile/internal/ir/stmt.go
Expand Up @@ -144,17 +144,14 @@ func NewBlockStmt(pos src.XPos, list []Node) *BlockStmt {
}

// A BranchStmt is a break, continue, fallthrough, or goto statement.
//
// For back-end code generation, Op may also be RETJMP (return+jump),
// in which case the label names another function entirely.
type BranchStmt struct {
miniStmt
Label *types.Sym // label if present
}

func NewBranchStmt(pos src.XPos, op Op, label *types.Sym) *BranchStmt {
switch op {
case OBREAK, OCONTINUE, OFALL, OGOTO, ORETJMP:
case OBREAK, OCONTINUE, OFALL, OGOTO:
// ok
default:
panic("NewBranch " + op.String())
Expand Down Expand Up @@ -384,6 +381,23 @@ func NewSwitchStmt(pos src.XPos, tag Node, cases []*CaseClause) *SwitchStmt {
return n
}

// A TailCallStmt is a tail call statement, which is used for back-end
// code generation to jump directly to another function entirely.
type TailCallStmt struct {
miniStmt
Target *Name
}

func NewTailCallStmt(pos src.XPos, target *Name) *TailCallStmt {
if target.Op() != ONAME || target.Class != PFUNC {
base.FatalfAt(pos, "tail call to non-func %v", target)
}
n := &TailCallStmt{Target: target}
n.pos = pos
n.op = OTAILCALL
return n
}

// A TypeSwitchGuard is the [Name :=] X.(type) in a type switch.
type TypeSwitchGuard struct {
miniNode
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/reflectdata/reflect.go
Expand Up @@ -1794,7 +1794,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field) *obj.LSym {
}
as := ir.NewAssignStmt(base.Pos, nthis, typecheck.ConvNop(left, rcvr))
fn.Body.Append(as)
fn.Body.Append(ir.NewBranchStmt(base.Pos, ir.ORETJMP, ir.MethodSym(methodrcvr, method.Sym)))
fn.Body.Append(ir.NewTailCallStmt(base.Pos, method.Nname.(*ir.Name)))
} else {
fn.SetWrapper(true) // ignore frame for panic+recover matching
call := ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/ssagen/abi.go
Expand Up @@ -303,7 +303,7 @@ func makeABIWrapper(f *ir.Func, wrapperABI obj.ABI) {
var tail ir.Node
if tfn.Type().NumResults() == 0 && tfn.Type().NumParams() == 0 && tfn.Type().NumRecvs() == 0 && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) {

tail = ir.NewBranchStmt(base.Pos, ir.ORETJMP, f.Nname.Sym())
tail = ir.NewTailCallStmt(base.Pos, f.Nname)
} else {
call := ir.NewCallExpr(base.Pos, ir.OCALL, f.Nname, nil)
call.Args = ir.ParamNames(tfn.Type())
Expand Down
6 changes: 3 additions & 3 deletions src/cmd/compile/internal/ssagen/ssa.go
Expand Up @@ -1580,11 +1580,11 @@ func (s *state) stmt(n ir.Node) {
b := s.exit()
b.Pos = s.lastPos.WithIsStmt()

case ir.ORETJMP:
n := n.(*ir.BranchStmt)
case ir.OTAILCALL:
n := n.(*ir.TailCallStmt)
b := s.exit()
b.Kind = ssa.BlockRetJmp // override BlockRet
b.Aux = callTargetLSym(n.Label, s.curfn.LSym)
b.Aux = callTargetLSym(n.Target.Sym(), s.curfn.LSym)

case ir.OCONTINUE, ir.OBREAK:
n := n.(*ir.BranchStmt)
Expand Down
6 changes: 3 additions & 3 deletions src/cmd/compile/internal/typecheck/typecheck.go
Expand Up @@ -857,8 +857,8 @@ func typecheck1(n ir.Node, top int) ir.Node {
n := n.(*ir.ReturnStmt)
return tcReturn(n)

case ir.ORETJMP:
n := n.(*ir.BranchStmt)
case ir.OTAILCALL:
n := n.(*ir.TailCallStmt)
return n

case ir.OSELECT:
Expand Down Expand Up @@ -2023,7 +2023,7 @@ func isTermNode(n ir.Node) bool {
n := n.(*ir.BlockStmt)
return isTermNodes(n.List)

case ir.OGOTO, ir.ORETURN, ir.ORETJMP, ir.OPANIC, ir.OFALL:
case ir.OGOTO, ir.ORETURN, ir.OTAILCALL, ir.OPANIC, ir.OFALL:
return true

case ir.OFOR, ir.OFORUNTIL:
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/walk/order.go
Expand Up @@ -692,7 +692,7 @@ func (o *orderState) stmt(n ir.Node) {
ir.OFALL,
ir.OGOTO,
ir.OLABEL,
ir.ORETJMP:
ir.OTAILCALL:
o.out = append(o.out, n)

// Special: handle call arguments.
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/walk/stmt.go
Expand Up @@ -136,8 +136,8 @@ func walkStmt(n ir.Node) ir.Node {
n := n.(*ir.ReturnStmt)
return walkReturn(n)

case ir.ORETJMP:
n := n.(*ir.BranchStmt)
case ir.OTAILCALL:
n := n.(*ir.TailCallStmt)
return n

case ir.OINLMARK:
Expand Down

0 comments on commit 87845d1

Please sign in to comment.