1
0
mirror of https://github.com/golang/go synced 2024-11-23 07:50:05 -07:00

cmd/gc: correct liveness for func ending in panic

The registerization code needs the function to end in a RET,
even if that RET is actually unreachable.

The liveness code needs to avoid such unreachable RETs.
It had a special case for final RET after JMP, but no case
for final RET after UNDEF. Instead of expanding the special
cases, let fixjmp - which already knows what is and is not
reachable definitively - mark the unreachable RET so that
the liveness code can identify it.

TBR=iant
CC=golang-codereviews
https://golang.org/cl/63680043
This commit is contained in:
Russ Cox 2014-02-13 23:56:53 -05:00
parent 02ae91f342
commit ab9e8d068a
3 changed files with 18 additions and 6 deletions

View File

@ -519,12 +519,10 @@ newcfg(Prog *firstp)
break;
bb->last = p;
// Pattern match an unconditional branch followed by a
// dead return instruction. This avoids a creating
// Stop before an unreachable RET, to avoid creating
// unreachable control flow nodes.
if(p->link != nil && p->link->link == nil)
if (p->as == AJMP && p->link->as == ARET && p->link->opt == nil)
break;
if(p->link != nil && p->link->as == ARET && p->link->mode == -1)
break;
// Collect basic blocks with selectgo calls.
if(isselectgocall(p))

View File

@ -146,7 +146,13 @@ fixjmp(Prog *firstp)
if(p->opt == dead) {
if(p->link == P && p->as == ARET && last && last->as != ARET) {
// This is the final ARET, and the code so far doesn't have one.
// Let it stay.
// Let it stay. The register allocator assumes that all live code in
// the function can be traversed by starting at all the RET instructions
// and following predecessor links. If we remove the final RET,
// this assumption will not hold in the case of an infinite loop
// at the end of a function.
// Keep the RET but mark it dead for the liveness analysis.
p->mode = -1;
} else {
if(debug['R'] && debug['v'])
print("del %P\n", p);

View File

@ -113,3 +113,11 @@ func f9() bool {
x := i9
return x != 99
}
// liveness formerly confused by UNDEF followed by RET,
// leading to "live at entry to f10: ~r1" (unnamed result).
func f10() string {
panic(1)
}