Skip to content

Commit 8fe372c

Browse files
committed
cmd/compile: allowing inlining of functions with OCALLPART
OCALLPART is exported in its original form, which is as an OXDOT. The body of the method value wrapper created in makepartialcall() was not being typechecked, and that was causing a problem during escape analysis, so I added code to typecheck the body. The go executable got slightly bigger with this change (13598111 -> 13598905), because of extra exported methods with OCALLPART (I believe), while the text size got slightly smaller (9686964 -> 9686643). This is mainly part of the work to make sure all function bodies can be exported (for purposes of generics), but might as well fix the OCALLPART inlining bug as well. Fixes #18493 Change-Id: If7aa055ff78ed7a6330c6a1e22f836ec567d04fd Reviewed-on: https://go-review.googlesource.com/c/go/+/263620 Run-TryBot: Dan Scales <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]>
1 parent 2754d91 commit 8fe372c

File tree

5 files changed

+35
-5
lines changed

5 files changed

+35
-5
lines changed

src/cmd/compile/internal/gc/closure.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,8 @@ func typecheckpartialcall(fn *Node, sym *types.Sym) {
434434
fn.Type = xfunc.Type
435435
}
436436

437+
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
438+
// for partial calls.
437439
func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
438440
rcvrtype := fn.Left.Type
439441
sym := methodSymSuffix(rcvrtype, meth, "-fm")
@@ -500,6 +502,10 @@ func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
500502
funcbody()
501503

502504
xfunc = typecheck(xfunc, ctxStmt)
505+
// Need to typecheck the body of the just-generated wrapper.
506+
// typecheckslice() requires that Curfn is set when processing an ORETURN.
507+
Curfn = xfunc
508+
typecheckslice(xfunc.Nbody.Slice(), ctxStmt)
503509
sym.Def = asTypesNode(xfunc)
504510
xtop = append(xtop, xfunc)
505511
Curfn = savecurfn

src/cmd/compile/internal/gc/iexport.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,8 +1266,13 @@ func (w *exportWriter) expr(n *Node) {
12661266
// case OSTRUCTKEY:
12671267
// unreachable - handled in case OSTRUCTLIT by elemList
12681268

1269-
// case OCALLPART:
1270-
// unimplemented - handled by default case
1269+
case OCALLPART:
1270+
// An OCALLPART is an OXDOT before type checking.
1271+
w.op(OXDOT)
1272+
w.pos(n.Pos)
1273+
w.expr(n.Left)
1274+
// Right node should be ONAME
1275+
w.selector(n.Right.Sym)
12711276

12721277
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
12731278
w.op(OXDOT)

src/cmd/compile/internal/gc/iimport.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,7 @@ func (r *importReader) node() *Node {
866866
// unreachable - handled in case OSTRUCTLIT by elemList
867867

868868
// case OCALLPART:
869-
// unimplemented
869+
// unreachable - mapped to case OXDOT below by exporter
870870

871871
// case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
872872
// unreachable - mapped to case OXDOT below by exporter

src/cmd/compile/internal/gc/inl.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,10 @@ func (v *hairyVisitor) visit(n *Node) bool {
374374
v.reason = "call to recover"
375375
return true
376376

377+
case OCALLPART:
378+
// OCALLPART is inlineable, but no extra cost to the budget
379+
377380
case OCLOSURE,
378-
OCALLPART,
379381
ORANGE,
380382
OSELECT,
381383
OTYPESW,
@@ -454,7 +456,7 @@ func inlcopy(n *Node) *Node {
454456
}
455457

456458
m := n.copy()
457-
if m.Func != nil {
459+
if n.Op != OCALLPART && m.Func != nil {
458460
Fatalf("unexpected Func: %v", m)
459461
}
460462
m.Left = inlcopy(n.Left)

test/inline.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,20 @@ Loop:
229229
}
230230
}
231231
}
232+
233+
// Issue #18493 - make sure we can do inlining of functions with a method value
234+
type T1 struct{}
235+
236+
func (a T1) meth(val int) int { // ERROR "can inline T1.meth" "inlining call to T1.meth"
237+
return val + 5
238+
}
239+
240+
func getMeth(t1 T1) func(int) int { // ERROR "can inline getMeth"
241+
return t1.meth // ERROR "t1.meth escapes to heap"
242+
}
243+
244+
func ii() { // ERROR "can inline ii"
245+
var t1 T1
246+
f := getMeth(t1) // ERROR "inlining call to getMeth" "t1.meth does not escape"
247+
_ = f(3)
248+
}

0 commit comments

Comments
 (0)