mirror of
https://github.com/golang/go
synced 2024-11-19 05:04:43 -07:00
[dev.cc] all: merge dev.power64 (f57928630b36) into dev.cc
This will be the last dev.power64 merge; we'll finish on dev.cc. TBR=austin CC=golang-codereviews https://golang.org/cl/175420043
This commit is contained in:
commit
754de8d403
@ -626,6 +626,11 @@ extern char* anames9[];
|
||||
extern char* cnames5[];
|
||||
extern char* cnames9[];
|
||||
|
||||
extern char* dnames5[];
|
||||
extern char* dnames6[];
|
||||
extern char* dnames8[];
|
||||
extern char* dnames9[];
|
||||
|
||||
extern LinkArch link386;
|
||||
extern LinkArch linkamd64;
|
||||
extern LinkArch linkamd64p32;
|
||||
|
@ -75,12 +75,18 @@ struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
@ -93,6 +99,16 @@ struct Reg
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
@ -144,7 +160,7 @@ void prop(Reg*, Bits, Bits);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpit(char *str, Flow *r0, int);
|
||||
@ -187,16 +203,16 @@ enum
|
||||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Register in middle; never written.
|
||||
// Register in middle (Prog.reg); only ever read.
|
||||
RegRead = 1<<12,
|
||||
CanRegRead = 1<<13,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<14,
|
||||
RightRead = 1<<15,
|
||||
RightWrite = 1<<16,
|
||||
|
@ -454,9 +454,13 @@ brk:
|
||||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(debug['R']) {
|
||||
if(rgp->regno >= NREG)
|
||||
@ -477,9 +481,6 @@ brk:
|
||||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
@ -488,6 +489,15 @@ brk:
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
@ -1189,7 +1199,7 @@ paint1(Reg *r, int bn)
|
||||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
@ -1213,6 +1223,9 @@ paint2(Reg *r, int bn)
|
||||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
@ -1220,14 +1233,14 @@ paint2(Reg *r, int bn)
|
||||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
@ -1344,6 +1357,8 @@ RtoB(int r)
|
||||
int
|
||||
BtoR(uint32 b)
|
||||
{
|
||||
// TODO Allow R0 and R1, but be careful with a 0 return
|
||||
// TODO Allow R9. Only R10 is reserved now (just g, not m).
|
||||
b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
|
||||
if(b == 0)
|
||||
return 0;
|
||||
@ -1442,12 +1457,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
||||
print(" (only)");
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != nil) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -338,6 +338,8 @@ enum
|
||||
D_STATIC = (D_NONE+4),
|
||||
D_AUTO = (D_NONE+5),
|
||||
D_PARAM = (D_NONE+6),
|
||||
|
||||
D_LAST = (D_NONE+26),
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -75,12 +75,18 @@ struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
@ -93,6 +99,16 @@ struct Reg
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
@ -140,7 +156,7 @@ void prop(Reg*, Bits, Bits);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
@ -165,8 +181,8 @@ typedef struct ProgInfo ProgInfo;
|
||||
struct ProgInfo
|
||||
{
|
||||
uint32 flags; // the bits below
|
||||
uint32 reguse; // required registers used by this instruction
|
||||
uint32 regset; // required registers set by this instruction
|
||||
uint32 reguse; // registers implicitly used by this instruction
|
||||
uint32 regset; // registers implicitly set by this instruction
|
||||
uint32 regindex; // registers used by addressing mode
|
||||
};
|
||||
|
||||
@ -187,12 +203,12 @@ enum
|
||||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<12,
|
||||
RightRead = 1<<13,
|
||||
RightWrite = 1<<14,
|
||||
|
@ -389,9 +389,13 @@ brk:
|
||||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(rgp->regno != 0) {
|
||||
if(debug['R'] && debug['v']) {
|
||||
@ -406,9 +410,6 @@ brk:
|
||||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
@ -417,6 +418,15 @@ brk:
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
@ -1020,7 +1030,7 @@ paint1(Reg *r, int bn)
|
||||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
@ -1044,6 +1054,9 @@ paint2(Reg *r, int bn)
|
||||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
@ -1051,14 +1064,14 @@ paint2(Reg *r, int bn)
|
||||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
@ -1259,12 +1272,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
||||
print(" %.4ud", (int)r1->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != R) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -865,6 +865,8 @@ enum
|
||||
|
||||
D_INDIR, /* additive */
|
||||
|
||||
D_LAST,
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
|
@ -75,12 +75,18 @@ struct Reg
|
||||
{
|
||||
Flow f;
|
||||
|
||||
Bits set; // variables written by this instruction.
|
||||
Bits use1; // variables read by prog->from.
|
||||
Bits use2; // variables read by prog->to.
|
||||
Bits set; // regopt variables written by this instruction.
|
||||
Bits use1; // regopt variables read by prog->from.
|
||||
Bits use2; // regopt variables read by prog->to.
|
||||
|
||||
// refahead/refbehind are the regopt variables whose current
|
||||
// value may be used in the following/preceding instructions
|
||||
// up to a CALL (or the value is clobbered).
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
// calahead/calbehind are similar, but for variables in
|
||||
// instructions that are reachable after hitting at least one
|
||||
// CALL.
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
@ -106,6 +112,16 @@ struct Reg
|
||||
|
||||
#define NRGN 600
|
||||
/*c2go enum { NRGN = 600 }; */
|
||||
|
||||
// A Rgn represents a single regopt variable over a region of code
|
||||
// where a register could potentially be dedicated to that variable.
|
||||
// The code encompassed by a Rgn is defined by the flow graph,
|
||||
// starting at enter, flood-filling forward while varno is refahead
|
||||
// and backward while varno is refbehind, and following branches. A
|
||||
// single variable may be represented by multiple disjoint Rgns and
|
||||
// each Rgn may choose a different register for that variable.
|
||||
// Registers are allocated to regions greedily in order of descending
|
||||
// cost.
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
@ -158,7 +174,7 @@ void loopit(Reg*, int32);
|
||||
void synch(Reg*, Bits);
|
||||
uint32 allreg(uint32, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
uint32 paint2(Reg*, int);
|
||||
uint32 paint2(Reg*, int, int);
|
||||
void paint3(Reg*, int, uint32, int);
|
||||
void addreg(Adr*, int);
|
||||
void dumpone(Flow*, int);
|
||||
@ -183,8 +199,8 @@ typedef struct ProgInfo ProgInfo;
|
||||
struct ProgInfo
|
||||
{
|
||||
uint32 flags; // the bits below
|
||||
uint32 reguse; // required registers used by this instruction
|
||||
uint32 regset; // required registers set by this instruction
|
||||
uint32 reguse; // registers implicitly used by this instruction
|
||||
uint32 regset; // registers implicitly set by this instruction
|
||||
uint32 regindex; // registers used by addressing mode
|
||||
};
|
||||
|
||||
@ -205,12 +221,12 @@ enum
|
||||
SizeF = 1<<7, // float aka float32
|
||||
SizeD = 1<<8, // double aka float64
|
||||
|
||||
// Left side: address taken, read, write.
|
||||
// Left side (Prog.from): address taken, read, write.
|
||||
LeftAddr = 1<<9,
|
||||
LeftRead = 1<<10,
|
||||
LeftWrite = 1<<11,
|
||||
|
||||
// Right side: address taken, read, write.
|
||||
// Right side (Prog.to): address taken, read, write.
|
||||
RightAddr = 1<<12,
|
||||
RightRead = 1<<13,
|
||||
RightWrite = 1<<14,
|
||||
|
@ -358,18 +358,19 @@ brk:
|
||||
* replace code (paint3)
|
||||
*/
|
||||
rgp = region;
|
||||
if(debug['R'] && debug['v'])
|
||||
print("\nregisterizing\n");
|
||||
for(i=0; i<nregion; i++) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
|
||||
bit = blsh(rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno);
|
||||
vreg = paint2(rgp->enter, rgp->varno, 0);
|
||||
vreg = allreg(vreg, rgp);
|
||||
if(rgp->regno != 0)
|
||||
paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
|
||||
rgp++;
|
||||
}
|
||||
|
||||
if(debug['R'] && debug['v'])
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
|
||||
/*
|
||||
* free aux structures. peep allocates new ones.
|
||||
*/
|
||||
@ -378,6 +379,15 @@ brk:
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
|
||||
if(debug['R'] && debug['v']) {
|
||||
// Rebuild flow graph, since we inserted instructions
|
||||
g = flowstart(firstp, sizeof(Reg));
|
||||
firstr = (Reg*)g->start;
|
||||
dumpit("pass6", &firstr->f, 1);
|
||||
flowend(g);
|
||||
firstr = R;
|
||||
}
|
||||
|
||||
/*
|
||||
* pass 7
|
||||
* peep-hole on basic block
|
||||
@ -997,7 +1007,7 @@ paint1(Reg *r, int bn)
|
||||
}
|
||||
|
||||
uint32
|
||||
paint2(Reg *r, int bn)
|
||||
paint2(Reg *r, int bn, int depth)
|
||||
{
|
||||
Reg *r1;
|
||||
int z;
|
||||
@ -1021,6 +1031,9 @@ paint2(Reg *r, int bn)
|
||||
r = r1;
|
||||
}
|
||||
for(;;) {
|
||||
if(debug['R'] && debug['v'])
|
||||
print(" paint2 %d %P\n", depth, r->f.prog);
|
||||
|
||||
r->act.b[z] &= ~bb;
|
||||
|
||||
vreg |= r->regu;
|
||||
@ -1028,14 +1041,14 @@ paint2(Reg *r, int bn)
|
||||
if(r->refbehind.b[z] & bb)
|
||||
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
|
||||
if(r1->refahead.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
|
||||
if(!(r->refahead.b[z] & bb))
|
||||
break;
|
||||
r1 = (Reg*)r->f.s2;
|
||||
if(r1 != R)
|
||||
if(r1->refbehind.b[z] & bb)
|
||||
vreg |= paint2(r1, bn);
|
||||
vreg |= paint2(r1, bn, depth+1);
|
||||
r = (Reg*)r->f.s1;
|
||||
if(r == R)
|
||||
break;
|
||||
@ -1229,12 +1242,14 @@ dumpit(char *str, Flow *r0, int isreg)
|
||||
print(" %.4ud", (int)r1->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
// r1 = r->s1;
|
||||
// if(r1 != nil) {
|
||||
// print(" succ:");
|
||||
// for(; r1 != R; r1 = r1->s1)
|
||||
// print(" %.4ud", (int)r1->prog->pc);
|
||||
// print("\n");
|
||||
// }
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
if(r->s2 != nil)
|
||||
print(" %.4ud", (int)r->s2->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -654,6 +654,8 @@ enum
|
||||
|
||||
D_CONST2 = D_INDIR+D_INDIR,
|
||||
|
||||
D_LAST,
|
||||
|
||||
T_TYPE = 1<<0,
|
||||
T_INDEX = 1<<1,
|
||||
T_OFFSET = 1<<2,
|
||||
|
@ -1322,7 +1322,6 @@ void
|
||||
dumpit(char *str, Flow *r0, int isreg)
|
||||
{
|
||||
Flow *r, *r1;
|
||||
int s1v, s2v;
|
||||
|
||||
print("\n%s\n", str);
|
||||
for(r = r0; r != nil; r = r->link) {
|
||||
@ -1334,10 +1333,8 @@ dumpit(char *str, Flow *r0, int isreg)
|
||||
print(" %.4ud", (int)r1->prog->pc);
|
||||
print("\n");
|
||||
}
|
||||
// If at least one successor is "interesting", print both
|
||||
s1v = (r->s1 != nil) && (r->s1->prog != r->prog->link);
|
||||
s2v = (r->s2 != nil) && (r->s2->prog != r->prog->link);
|
||||
if(s1v || s2v) {
|
||||
// Print successors if it's not just the next one
|
||||
if(r->s1 != r->link || r->s2 != nil) {
|
||||
print(" succ:");
|
||||
if(r->s1 != nil)
|
||||
print(" %.4ud", (int)r->s1->prog->pc);
|
||||
|
@ -497,6 +497,8 @@ enum
|
||||
D_DCONST,
|
||||
D_ADDR, // not used, use D_CONST with non-empty sym.
|
||||
|
||||
D_LAST,
|
||||
|
||||
/* reg names for 9g OREGISTER */
|
||||
D_R0 = 0, // type is D_REG
|
||||
D_F0 = D_R0+NREG, // type is D_FREG
|
||||
|
87
src/cmd/dist/buildgc.c
vendored
87
src/cmd/dist/buildgc.c
vendored
@ -63,22 +63,36 @@ gcopnames(char *dir, char *file)
|
||||
vfree(&fields);
|
||||
}
|
||||
|
||||
static int
|
||||
xatoi(char *s, char **end)
|
||||
{
|
||||
int val = 0;
|
||||
for(; *s && *s >= '0' && *s <= '9'; ++s)
|
||||
val = val * 10 + (*s - '0');
|
||||
*end = s;
|
||||
return val;
|
||||
}
|
||||
|
||||
// mkanames reads [5689].out.h and writes anames[5689].c
|
||||
// The format is much the same as the Go opcodes above.
|
||||
// it also writes out cnames array for C_* constants.
|
||||
// It also writes out cnames array for C_* constants and the dnames
|
||||
// array for D_* constants.
|
||||
void
|
||||
mkanames(char *dir, char *file)
|
||||
{
|
||||
int i, j, ch;
|
||||
int i, j, ch, n, unknown;
|
||||
Buf in, b, out, out2;
|
||||
Vec lines;
|
||||
char *p;
|
||||
char *p, *p2;
|
||||
Vec dnames[128];
|
||||
|
||||
binit(&b);
|
||||
binit(&in);
|
||||
binit(&out);
|
||||
binit(&out2);
|
||||
vinit(&lines);
|
||||
for(i=0; i<nelem(dnames); i++)
|
||||
vinit(&dnames[i]);
|
||||
|
||||
ch = file[xstrlen(file)-3];
|
||||
bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
|
||||
@ -87,10 +101,12 @@ mkanames(char *dir, char *file)
|
||||
|
||||
// Include link.h so that the extern declaration there is
|
||||
// checked against the non-extern declaration we are generating.
|
||||
bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
|
||||
bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch));
|
||||
bwritestr(&out, bprintf(&b, "\n"));
|
||||
|
||||
bwritestr(&out, bprintf(&b, "char* anames%c[] = {\n", ch));
|
||||
@ -127,6 +143,69 @@ mkanames(char *dir, char *file)
|
||||
if(j>0)
|
||||
bwriteb(&out, &out2);
|
||||
|
||||
j=unknown=0;
|
||||
n=-1;
|
||||
for(i=0; i<lines.len; i++) {
|
||||
if(hasprefix(lines.p[i], "\tD_")) {
|
||||
p = xstrstr(lines.p[i], ",");
|
||||
if(p)
|
||||
*p = '\0';
|
||||
p = xstrstr(lines.p[i], "\n");
|
||||
if(p)
|
||||
*p = '\0';
|
||||
|
||||
// Parse explicit value, if any
|
||||
p = xstrstr(lines.p[i], "=");
|
||||
if(p) {
|
||||
// Skip space after '='
|
||||
p2 = p + 1;
|
||||
while(*p2 == ' ' || *p2 == '\t')
|
||||
p2++;
|
||||
n = xatoi(p2, &p2);
|
||||
// We can't do anything about
|
||||
// non-numeric values or anything that
|
||||
// follows
|
||||
while(*p2 == ' ' || *p2 == '\t')
|
||||
p2++;
|
||||
if(*p2 != 0) {
|
||||
unknown = 1;
|
||||
continue;
|
||||
}
|
||||
// Truncate space before '='
|
||||
while(*(p-1) == ' ' || *(p-1) == '\t')
|
||||
p--;
|
||||
*p = '\0';
|
||||
unknown = 0;
|
||||
} else {
|
||||
n++;
|
||||
}
|
||||
|
||||
if(unknown || n >= nelem(dnames))
|
||||
continue;
|
||||
|
||||
p = lines.p[i] + 3;
|
||||
if(xstrcmp(p, "LAST") == 0)
|
||||
continue;
|
||||
vadd(&dnames[n], p);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if(j>0){
|
||||
bwritestr(&out, bprintf(&b, "char* dnames%c[D_LAST] = {\n", ch));
|
||||
for(i=0; i<nelem(dnames); i++) {
|
||||
if(dnames[i].len == 0)
|
||||
continue;
|
||||
bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0]));
|
||||
for(j=0; j<dnames[i].len; j++) {
|
||||
if(j != 0)
|
||||
bwritestr(&out, "/");
|
||||
bwritestr(&out, dnames[i].p[j]);
|
||||
}
|
||||
bwritestr(&out, "\",\n");
|
||||
}
|
||||
bwritestr(&out, "};\n");
|
||||
}
|
||||
|
||||
writefile(&out, file, 0);
|
||||
|
||||
bfree(&b);
|
||||
@ -134,4 +213,6 @@ mkanames(char *dir, char *file)
|
||||
bfree(&out);
|
||||
bfree(&out2);
|
||||
vfree(&lines);
|
||||
for(i=0; i<nelem(dnames); i++)
|
||||
vfree(&dnames[i]);
|
||||
}
|
||||
|
@ -82,6 +82,19 @@ Pconv(Fmt *fp)
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
bigP = p;
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
char *s = str;
|
||||
s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, p->as);
|
||||
if(p->from.type != D_NONE)
|
||||
s += sprint(s, " from={%#D}", &p->from);
|
||||
if(p->reg)
|
||||
s += sprint(s, " reg=%d", p->reg);
|
||||
if(p->to.type != D_NONE)
|
||||
s += sprint(s, " to={%#D}", &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
switch(p->as) {
|
||||
case ADATA:
|
||||
sprint(str, "%.5lld (%L) %A %D/%d,%D",
|
||||
@ -126,6 +139,31 @@ Dconv(Fmt *fp)
|
||||
a = va_arg(fp->args, Addr*);
|
||||
i = a->type;
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
char *s = str;
|
||||
s += sprint(s, "type=");
|
||||
if(i == D_NONE) {
|
||||
sprint(s, "NONE");
|
||||
goto brk;
|
||||
}
|
||||
if(i >= D_INDIR) {
|
||||
i -= D_INDIR;
|
||||
s += sprint(s, "INDIR+");
|
||||
}
|
||||
if(i >= 0 && i < D_LAST && dnames6[i] != nil)
|
||||
s += sprint(s, "%s ", dnames6[i]);
|
||||
else
|
||||
s += sprint(s, "%d ", i);
|
||||
s += sprint(s, "offset=%ld etype=%E width=%d", a->offset, a->etype, a->width);
|
||||
if(a->class != 0)
|
||||
s += sprint(s, " class=%s", cnames9[(int)a->class]);
|
||||
if(a->sym != nil)
|
||||
s += sprint(s, " sym=%s", a->sym->name);
|
||||
if(a->type == D_BRANCH && a->u.branch != nil)
|
||||
s += sprint(s, " branch=%.5lld", a->u.branch->pc);
|
||||
goto brk;
|
||||
}
|
||||
|
||||
if(fp->flags & FmtLong) {
|
||||
if(i == D_CONST)
|
||||
sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
|
||||
|
@ -91,6 +91,21 @@ Pconv(Fmt *fp)
|
||||
p = va_arg(fp->args, Prog*);
|
||||
bigP = p;
|
||||
a = p->as;
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
s = str;
|
||||
s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, a);
|
||||
if(p->from.type != D_NONE)
|
||||
s += sprint(s, " from={%#D}", &p->from);
|
||||
if(p->reg)
|
||||
s += sprint(s, " reg=%d", p->reg);
|
||||
if(p->from3.type != D_NONE)
|
||||
s += sprint(s, " from3={%#D}", &p->from3);
|
||||
if(p->to.type != D_NONE)
|
||||
s += sprint(s, " to={%#D}", &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
if(a == ADATA || a == AINIT || a == ADYNT)
|
||||
sprint(str, "%.5lld (%L) %A %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
|
||||
else if(a == ATEXT) {
|
||||
@ -153,6 +168,32 @@ Dconv(Fmt *fp)
|
||||
|
||||
a = va_arg(fp->args, Addr*);
|
||||
|
||||
if(fp->flags & FmtSharp) {
|
||||
char *s = str;
|
||||
if(a->type == D_NONE) {
|
||||
sprint(s, "type=NONE");
|
||||
goto ret;
|
||||
}
|
||||
if(a->type >= 0 && a->type < D_LAST && dnames9[a->type] != nil)
|
||||
s += sprint(s, "type=%s ", dnames9[a->type]);
|
||||
else
|
||||
s += sprint(s, "type=%d ", a->type);
|
||||
if(a->name >= 0 && a->name < D_LAST && dnames9[a->name] != nil)
|
||||
s += sprint(s, "name=%s ", dnames9[a->name]);
|
||||
else
|
||||
s += sprint(s, "name=%d ", a->name);
|
||||
s += sprint(s, "offset=%ld etype=%E width=%d", a->offset, a->etype, a->width);
|
||||
if(a->class != 0)
|
||||
s += sprint(s, " class=%s", cnames9[a->class]);
|
||||
if(a->reg != NREG)
|
||||
s += sprint(s, " reg=%d", a->reg);
|
||||
if(a->sym != nil)
|
||||
s += sprint(s, " sym=%s", a->sym->name);
|
||||
if(a->type == D_BRANCH && a->u.branch != nil)
|
||||
s += sprint(s, " branch=%.5lld", a->u.branch->pc);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if(fp->flags & FmtLong) {
|
||||
if(a->type == D_CONST)
|
||||
sprint(str, "$%d-%d", (int32)a->offset, (int32)(a->offset>>32));
|
||||
|
Loading…
Reference in New Issue
Block a user