1 // Derived from Inferno utils/6c/reg.c
2 // http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6 // Portions Copyright © 1997-1999 Vita Nuova Limited
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8 // Portions Copyright © 2004,2006 Bruce Ellis
9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11 // Portions Copyright © 2009 The Go Authors. All rights reserved.
13 // Permission is hereby granted, free of charge, to any person obtaining a copy
14 // of this software and associated documentation files (the "Software"), to deal
15 // in the Software without restriction, including without limitation the rights
16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 // copies of the Software, and to permit persons to whom the Software is
18 // furnished to do so, subject to the following conditions:
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 #define NREGVAR 16 /* 8 integer + 8 floating */
37 #define REGBITS ((uint64)0xffffull)
40 REGBITS = (1<<NREGVAR) - 1,
48 rcmp(const void *a1, const void *a2)
59 return p2->varno - p1->varno;
70 // convert each bit to a variable
76 // disable all pieces of that variable
77 for(i=0; i<nvar; i++) {
79 if(v->node == node && v->name == n)
85 static char* regname[] = {
86 ".ax", ".cx", ".dx", ".bx", ".sp", ".bp", ".si", ".di",
87 ".x0", ".x1", ".x2", ".x3", ".x4", ".x5", ".x6", ".x7",
90 static Node* regnodes[NREGVAR];
92 static void walkvardef(Node *n, Reg *r, int active);
106 fmtinstall('Q', Qconv);
107 exregoffset = D_DI; // no externals
114 * control flow is more complicated in generated go code
115 * than in generated c code. define pseudo-variables for
116 * registers, so we have complete register usage information.
119 memset(var, 0, NREGVAR*sizeof var[0]);
120 for(i=0; i<NREGVAR; i++) {
122 regnodes[i] = newname(lookup(regname[i]));
123 var[i].node = regnodes[i];
126 regbits = RtoB(D_SP);
127 for(z=0; z<BITS; z++) {
138 * build aux data structure
140 * find use and set of variables
142 g = flowstart(firstp, sizeof(Reg));
144 for(i=0; i<nvar; i++)
145 var[i].node->opt = nil;
149 firstr = (Reg*)g->start;
151 for(r = firstr; r != R; r = (Reg*)r->f.link) {
153 if(p->as == AVARDEF || p->as == AVARKILL)
157 // Avoid making variables for direct-called functions.
158 if(p->as == ACALL && p->to.type == D_EXTERN)
161 r->use1.b[0] |= info.reguse | info.regindex;
162 r->set.b[0] |= info.regset;
164 bit = mkvar(r, &p->from);
166 if(info.flags & LeftAddr)
168 if(info.flags & LeftRead)
169 for(z=0; z<BITS; z++)
170 r->use1.b[z] |= bit.b[z];
171 if(info.flags & LeftWrite)
172 for(z=0; z<BITS; z++)
173 r->set.b[z] |= bit.b[z];
176 bit = mkvar(r, &p->to);
178 if(info.flags & RightAddr)
180 if(info.flags & RightRead)
181 for(z=0; z<BITS; z++)
182 r->use2.b[z] |= bit.b[z];
183 if(info.flags & RightWrite)
184 for(z=0; z<BITS; z++)
185 r->set.b[z] |= bit.b[z];
191 for(i=0; i<nvar; i++) {
195 for(z=0; z<BITS; z++)
196 addrs.b[z] |= bit.b[z];
199 if(debug['R'] && debug['v'])
200 print("bit=%2d addr=%d et=%-6E w=%-2d s=%N + %lld\n",
201 i, v->addr, v->etype, v->width, v->node, v->offset);
204 if(debug['R'] && debug['v'])
205 dumpit("pass1", &firstr->f, 1);
209 * find looping structure
213 if(debug['R'] && debug['v'])
214 dumpit("pass2", &firstr->f, 1);
218 * iterate propagating fat vardef covering forward
219 * r->act records vars with a VARDEF since the last CALL.
220 * (r->act will be reused in pass 5 for something else,
221 * but we'll be done with it by then.)
224 for(r = firstr; r != R; r = (Reg*)r->f.link) {
228 for(r = firstr; r != R; r = (Reg*)r->f.link) {
230 if(p->as == AVARDEF && isfat(p->to.node->type) && p->to.node->opt != nil) {
232 walkvardef(p->to.node, r, active);
238 * iterate propagating usage
239 * back until flow graph is complete
243 for(r = firstr; r != R; r = (Reg*)r->f.link)
245 for(r = firstr; r != R; r = (Reg*)r->f.link)
246 if(r->f.prog->as == ARET)
247 prop(r, zbits, zbits);
249 /* pick up unreachable code */
251 for(r = firstr; r != R; r = r1) {
252 r1 = (Reg*)r->f.link;
253 if(r1 && r1->f.active && !r->f.active) {
254 prop(r, zbits, zbits);
263 if(debug['R'] && debug['v'])
264 dumpit("pass3", &firstr->f, 1);
268 * iterate propagating register/variable synchrony
269 * forward until graph is complete
273 for(r = firstr; r != R; r = (Reg*)r->f.link)
275 synch(firstr, zbits);
279 if(debug['R'] && debug['v'])
280 dumpit("pass4", &firstr->f, 1);
284 * move register pseudo-variables into regu.
286 for(r = firstr; r != R; r = (Reg*)r->f.link) {
287 r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS;
289 r->set.b[0] &= ~REGBITS;
290 r->use1.b[0] &= ~REGBITS;
291 r->use2.b[0] &= ~REGBITS;
292 r->refbehind.b[0] &= ~REGBITS;
293 r->refahead.b[0] &= ~REGBITS;
294 r->calbehind.b[0] &= ~REGBITS;
295 r->calahead.b[0] &= ~REGBITS;
296 r->regdiff.b[0] &= ~REGBITS;
297 r->act.b[0] &= ~REGBITS;
303 * calculate costs (paint1)
307 for(z=0; z<BITS; z++)
308 bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
309 ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
310 if(bany(&bit) && !r->f.refset) {
311 // should never happen - all variables are preset
313 print("%L: used and not set: %Q\n", r->f.prog->lineno, bit);
317 for(r = firstr; r != R; r = (Reg*)r->f.link)
321 for(r = firstr; r != R; r = (Reg*)r->f.link) {
322 for(z=0; z<BITS; z++)
323 bit.b[z] = r->set.b[z] &
324 ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
325 if(bany(&bit) && !r->f.refset) {
327 print("%L: set and not used: %Q\n", r->f.prog->lineno, bit);
331 for(z=0; z<BITS; z++)
332 bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
344 if(nregion >= NRGN) {
345 if(debug['R'] && debug['v'])
346 print("too many regions\n");
353 qsort(region, nregion, sizeof(region[0]), rcmp);
357 * determine used registers (paint2)
358 * replace code (paint3)
361 if(debug['R'] && debug['v'])
362 print("\nregisterizing\n");
363 for(i=0; i<nregion; i++) {
364 if(debug['R'] && debug['v'])
365 print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
366 bit = blsh(rgp->varno);
367 vreg = paint2(rgp->enter, rgp->varno, 0);
368 vreg = allreg(vreg, rgp);
370 paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
375 * free aux structures. peep allocates new ones.
377 for(i=0; i<nvar; i++)
378 var[i].node->opt = nil;
382 if(debug['R'] && debug['v']) {
383 // Rebuild flow graph, since we inserted instructions
384 g = flowstart(firstp, sizeof(Reg));
385 firstr = (Reg*)g->start;
386 dumpit("pass6", &firstr->f, 1);
393 * peep-hole on basic block
395 if(!debug['R'] || debug['P'])
401 for(p=firstp; p!=P; p=p->link) {
402 while(p->link != P && p->link->as == ANOP)
403 p->link = p->link->link;
404 if(p->to.type == D_BRANCH)
405 while(p->to.u.branch != P && p->to.u.branch->as == ANOP)
406 p->to.u.branch = p->to.u.branch->link;
410 for(p=firstp; p!=P; p=p->link) {
411 if(p->from.type >= D_X0 && p->from.type <= D_X7)
412 fatal("invalid use of %R with GO386=387: %P", p->from.type, p);
413 if(p->to.type >= D_X0 && p->to.type <= D_X7)
414 fatal("invalid use of %R with GO386=387: %P", p->to.type, p);
428 print(" %4d cvtreg\n", ostats.ncvtreg);
430 print(" %4d spill\n", ostats.nspill);
432 print(" %4d reload\n", ostats.nreload);
434 print(" %4d delmov\n", ostats.ndelmov);
436 print(" %4d var\n", ostats.nvar);
438 print(" %4d addr\n", ostats.naddr);
440 memset(&ostats, 0, sizeof(ostats));
445 walkvardef(Node *n, Reg *r, int active)
451 for(r1=r; r1!=R; r1=(Reg*)r1->f.s1) {
452 if(r1->f.active == active)
454 r1->f.active = active;
455 if(r1->f.prog->as == AVARKILL && r1->f.prog->to.node == n)
457 for(v=n->opt; v!=nil; v=v->nextinnode) {
461 if(r1->f.prog->as == ACALL)
465 for(r2=r; r2!=r1; r2=(Reg*)r2->f.s1)
467 walkvardef(n, (Reg*)r2->f.s2, active);
475 addmove(Reg *r, int bn, int rn, int f)
481 p1 = mal(sizeof(*p1));
488 p1->lineno = p->lineno;
493 a->offset = v->offset;
497 a->sym = linksym(v->node->sym);
499 // need to clean this up with wptr and
500 // some of the defaults
504 fatal("unknown type %E", v->etype);
533 if(v->etype == TUINT8)
535 if(v->etype == TUINT16)
538 if(debug['R'] && debug['v'])
539 print("%P ===add=== %P\n", p, p1);
551 if(r >= D_AX && r <= D_DI)
554 if(r >= D_AL && r <= D_BL)
555 b |= RtoB(r-D_AL+D_AX);
557 if(r >= D_AH && r <= D_BH)
558 b |= RtoB(r-D_AH+D_AX);
560 if(r >= D_X0 && r <= D_X0+7)
566 overlap(int32 o1, int w1, int32 o2, int w2)
573 if(!(t1 > o2 && t2 > o1))
580 mkvar(Reg *r, Adr *a)
583 int i, t, n, et, z, w, flag, regu;
589 * mark registers used
596 r->use1.b[0] |= doregbits(a->index);
624 if(node == N || node->op != ONAME || node->orig == N)
627 if(node->orig != node)
628 fatal("%D: bad node", a);
629 if(node->sym == S || node->sym->name[0] == '.')
635 fatal("bad width %d for %D", w, a);
638 for(i=0; i<nvar; i++) {
640 if(v->node == node && v->name == n) {
646 // if they overlap, disable both
647 if(overlap(v->offset, v->width, o, w)) {
649 print("disable %s\n", node->sym->name);
663 if(debug['w'] > 1 && node != N)
664 fatal("variable not optimized: %D", a);
666 // If we're not tracking a word in a variable, mark the rest as
667 // having its address taken, so that we keep the whole thing
668 // live at all calls. otherwise we might optimize away part of
669 // a variable but not all of it.
670 for(i=0; i<nvar; i++) {
685 v->addr = flag; // funny punning
688 // node->opt is the head of a linked list
689 // of Vars within the given Node, so that
690 // we can start at a Var and find all the other
691 // Vars in the same Go variable.
692 v->nextinnode = node->opt;
696 if(n == D_EXTERN || n == D_STATIC)
697 for(z=0; z<BITS; z++)
698 externs.b[z] |= bit.b[z];
700 for(z=0; z<BITS; z++)
701 params.b[z] |= bit.b[z];
703 if(node->class == PPARAM)
704 for(z=0; z<BITS; z++)
705 ivar.b[z] |= bit.b[z];
706 if(node->class == PPARAMOUT)
707 for(z=0; z<BITS; z++)
708 ovar.b[z] |= bit.b[z];
710 // Treat values with their address taken as live at calls,
711 // because the garbage collector's liveness analysis in ../gc/plive.c does.
712 // These must be consistent or else we will elide stores and the garbage
713 // collector will see uninitialized data.
714 // The typical case where our own analysis is out of sync is when the
715 // node appears to have its address taken but that code doesn't actually
716 // get generated and therefore doesn't show up as an address being
717 // taken when we analyze the instruction stream.
718 // One instance of this case is when a closure uses the same name as
719 // an outer variable for one of its own variables declared with :=.
720 // The parser flags the outer variable as possibly shared, and therefore
721 // sets addrtaken, even though it ends up not being actually shared.
722 // If we were better about _ elision, _ = &x would suffice too.
723 // The broader := in a closure problem is mentioned in a comment in
724 // closure.c:/^typecheckclosure and dcl.c:/^oldname.
728 // Disable registerization for globals, because:
729 // (1) we might panic at any time and we want the recovery code
730 // to see the latest values (issue 1304).
731 // (2) we don't know what pointers might point at them and we want
732 // loads via those pointers to see updated values and vice versa (issue 7995).
734 // Disable registerization for results if using defer, because the deferred func
735 // might recover and return, causing the current values to be used.
736 if(node->class == PEXTERN || (hasdefer && node->class == PPARAMOUT))
740 print("bit=%2d et=%2E w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
750 prop(Reg *r, Bits ref, Bits cal)
756 for(r1 = r; r1 != R; r1 = (Reg*)r1->f.p1) {
757 for(z=0; z<BITS; z++) {
758 ref.b[z] |= r1->refahead.b[z];
759 if(ref.b[z] != r1->refahead.b[z]) {
760 r1->refahead.b[z] = ref.b[z];
763 cal.b[z] |= r1->calahead.b[z];
764 if(cal.b[z] != r1->calahead.b[z]) {
765 r1->calahead.b[z] = cal.b[z];
769 switch(r1->f.prog->as) {
771 if(noreturn(r1->f.prog))
774 // Mark all input variables (ivar) as used, because that's what the
775 // liveness bitmaps say. The liveness bitmaps say that so that a
776 // panic will not show stale values in the parameter dump.
777 // Mark variables with a recent VARDEF (r1->act) as used,
778 // so that the optimizer flushes initializations to memory,
779 // so that if a garbage collection happens during this CALL,
780 // the collector will see initialized memory. Again this is to
781 // match what the liveness bitmaps say.
782 for(z=0; z<BITS; z++) {
783 cal.b[z] |= ref.b[z] | externs.b[z] | ivar.b[z] | r1->act.b[z];
787 // cal.b is the current approximation of what's live across the call.
788 // Every bit in cal.b is a single stack word. For each such word,
789 // find all the other tracked stack words in the same Go variable
790 // (struct/slice/string/interface) and mark them live too.
791 // This is necessary because the liveness analysis for the garbage
792 // collector works at variable granularity, not at word granularity.
793 // It is fundamental for slice/string/interface: the garbage collector
794 // needs the whole value, not just some of the words, in order to
795 // interpret the other bits correctly. Specifically, slice needs a consistent
796 // ptr and cap, string needs a consistent ptr and len, and interface
797 // needs a consistent type word and data word.
798 for(z=0; z<BITS; z++) {
801 for(i=0; i<64; i++) {
802 if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
805 if(v->node->opt == nil) // v represents fixed register, not Go variable
808 // v->node->opt is the head of a linked list of Vars
809 // corresponding to tracked words from the Go variable v->node.
810 // Walk the list and set all the bits.
811 // For a large struct this could end up being quadratic:
812 // after the first setting, the outer loop (for z, i) would see a 1 bit
813 // for all of the remaining words in the struct, and for each such
814 // word would go through and turn on all the bits again.
815 // To avoid the quadratic behavior, we only turn on the bits if
816 // v is the head of the list or if the head's bit is not yet turned on.
817 // This will set the bits at most twice, keeping the overall loop linear.
820 if(v == v1 || !btest(&cal, j)) {
821 for(; v1 != nil; v1 = v1->nextinnode) {
831 for(z=0; z<BITS; z++) {
838 for(z=0; z<BITS; z++) {
839 cal.b[z] = externs.b[z] | ovar.b[z];
844 for(z=0; z<BITS; z++) {
845 ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
846 r1->use1.b[z] | r1->use2.b[z];
847 cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
848 r1->refbehind.b[z] = ref.b[z];
849 r1->calbehind.b[z] = cal.b[z];
855 for(; r != r1; r = (Reg*)r->f.p1)
856 for(r2 = (Reg*)r->f.p2; r2 != R; r2 = (Reg*)r2->f.p2link)
857 prop(r2, r->refbehind, r->calbehind);
861 synch(Reg *r, Bits dif)
866 for(r1 = r; r1 != R; r1 = (Reg*)r1->f.s1) {
867 for(z=0; z<BITS; z++) {
868 dif.b[z] = (dif.b[z] &
869 ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
870 r1->set.b[z] | r1->regdiff.b[z];
871 if(dif.b[z] != r1->regdiff.b[z]) {
872 r1->regdiff.b[z] = dif.b[z];
879 for(z=0; z<BITS; z++)
880 dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
881 if((Reg*)r1->f.s2 != R)
882 synch((Reg*)r1->f.s2, dif);
887 allreg(uint32 b, Rgn *r)
897 fatal("unknown etype %d/%E", bitno(b), v->etype);
913 if(i && r->cost > 0) {
924 if(i && r->cost > 0) {
934 paint1(Reg *r, int bn)
946 if(!(r->refbehind.b[z] & bb))
951 if(!(r1->refahead.b[z] & bb))
953 if(r1->act.b[z] & bb)
958 rbz = ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z]));
959 if(LOAD(r) & rbz & bb) {
960 change -= CLOAD * r->f.loop;
966 if(r->f.prog->as != ANOP) { // don't give credit for NOPs
967 if(r->use1.b[z] & bb) {
968 change += CREF * r->f.loop;
969 if(p->as == AFMOVL || p->as == AFMOVW)
973 if((r->use2.b[z]|r->set.b[z]) & bb) {
974 change += CREF * r->f.loop;
975 if(p->as == AFMOVL || p->as == AFMOVW)
981 if(STORE(r) & r->regdiff.b[z] & bb) {
982 change -= CLOAD * r->f.loop;
983 if(p->as == AFMOVL || p->as == AFMOVW)
988 if(r->refbehind.b[z] & bb)
989 for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
990 if(r1->refahead.b[z] & bb)
993 if(!(r->refahead.b[z] & bb))
997 if(r1->refbehind.b[z] & bb)
1002 if(r->act.b[z] & bb)
1004 if(!(r->refbehind.b[z] & bb))
1010 paint2(Reg *r, int bn, int depth)
1017 bb = 1LL << (bn%64);
1019 if(!(r->act.b[z] & bb))
1022 if(!(r->refbehind.b[z] & bb))
1027 if(!(r1->refahead.b[z] & bb))
1029 if(!(r1->act.b[z] & bb))
1034 if(debug['R'] && debug['v'])
1035 print(" paint2 %d %P\n", depth, r->f.prog);
1041 if(r->refbehind.b[z] & bb)
1042 for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
1043 if(r1->refahead.b[z] & bb)
1044 vreg |= paint2(r1, bn, depth+1);
1046 if(!(r->refahead.b[z] & bb))
1050 if(r1->refbehind.b[z] & bb)
1051 vreg |= paint2(r1, bn, depth+1);
1055 if(!(r->act.b[z] & bb))
1057 if(!(r->refbehind.b[z] & bb))
1065 paint3(Reg *r, int bn, uint32 rb, int rn)
1073 bb = 1LL << (bn%64);
1074 if(r->act.b[z] & bb)
1077 if(!(r->refbehind.b[z] & bb))
1082 if(!(r1->refahead.b[z] & bb))
1084 if(r1->act.b[z] & bb)
1089 rbz = ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z]));
1090 if(LOAD(r) & rbz & bb)
1091 addmove(r, bn, rn, 0);
1096 if(r->use1.b[z] & bb) {
1097 if(debug['R'] && debug['v'])
1099 addreg(&p->from, rn);
1100 if(debug['R'] && debug['v'])
1101 print(" ===change== %P\n", p);
1103 if((r->use2.b[z]|r->set.b[z]) & bb) {
1104 if(debug['R'] && debug['v'])
1107 if(debug['R'] && debug['v'])
1108 print(" ===change== %P\n", p);
1111 if(STORE(r) & r->regdiff.b[z] & bb)
1112 addmove(r, bn, rn, 1);
1115 if(r->refbehind.b[z] & bb)
1116 for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
1117 if(r1->refahead.b[z] & bb)
1118 paint3(r1, bn, rb, rn);
1120 if(!(r->refahead.b[z] & bb))
1124 if(r1->refbehind.b[z] & bb)
1125 paint3(r1, bn, rb, rn);
1129 if(r->act.b[z] & bb)
1131 if(!(r->refbehind.b[z] & bb))
1137 addreg(Adr *a, int rn)
1151 if(r < D_AX || r > D_DI)
1153 return 1L << (r-D_AX);
1163 return bitno(b) + D_AX;
1169 if(f < D_X0 || f > D_X7)
1171 return 1L << (f - D_X0 + 8);
1180 return bitno(b) - 8 + D_X0;
1184 dumpone(Flow *f, int isreg)
1190 print("%d:%P", f->loop, f->prog);
1193 for(z=0; z<BITS; z++)
1208 print(" s:%Q", r->set);
1210 print(" u1:%Q", r->use1);
1212 print(" u2:%Q", r->use2);
1213 if(bany(&r->refbehind))
1214 print(" rb:%Q ", r->refbehind);
1215 if(bany(&r->refahead))
1216 print(" ra:%Q ", r->refahead);
1217 if(bany(&r->calbehind))
1218 print(" cb:%Q ", r->calbehind);
1219 if(bany(&r->calahead))
1220 print(" ca:%Q ", r->calahead);
1221 if(bany(&r->regdiff))
1222 print(" d:%Q ", r->regdiff);
1224 print(" a:%Q ", r->act);
1231 dumpit(char *str, Flow *r0, int isreg)
1235 print("\n%s\n", str);
1236 for(r = r0; r != nil; r = r->link) {
1241 for(; r1 != nil; r1 = r1->p2link)
1242 print(" %.4ud", (int)r1->prog->pc);
1245 // Print successors if it's not just the next one
1246 if(r->s1 != r->link || r->s2 != nil) {
1249 print(" %.4ud", (int)r->s1->prog->pc);
1251 print(" %.4ud", (int)r->s2->prog->pc);