]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.cc] all: merge dev.power64 (f57928630b36) into dev.cc
authorRuss Cox <rsc@golang.org>
Thu, 20 Nov 2014 16:30:43 +0000 (11:30 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 20 Nov 2014 16:30:43 +0000 (11:30 -0500)
This will be the last dev.power64 merge; we'll finish on dev.cc.

TBR=austin
CC=golang-codereviews
https://golang.org/cl/175420043

15 files changed:
include/link.h
src/cmd/5g/opt.h
src/cmd/5g/reg.c
src/cmd/5l/5.out.h
src/cmd/6g/opt.h
src/cmd/6g/reg.c
src/cmd/6l/6.out.h
src/cmd/8g/opt.h
src/cmd/8g/reg.c
src/cmd/8l/8.out.h
src/cmd/9g/reg.c
src/cmd/9l/9.out.h
src/cmd/dist/buildgc.c
src/liblink/list6.c
src/liblink/list9.c

index 06f3ebb489408ebd26038c693b89c16e1163c30c..225c6f95dfc942eb55501aa8117d13100e901a42 100644 (file)
@@ -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;
index 5016d1cc83b7e11f49c8bf7f03a3bb71a7432163..a606f1d3105e969afc034d7cafe42f2fa09653c0 100644 (file)
@@ -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,
index 4417928731d3c67a97ec8b7d5f4aecad27f23ca3..56ea7826e2deefcd01c565a1bb7cc022a6ae19a0 100644 (file)
@@ -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");
+               }
        }
 }
index 7b16ac4468f87e2f9ee414a403626340610d78fe..38a33db6429dd7f3503d7b07fb65ba614bbdc48c 100644 (file)
@@ -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),
 };
 
 /*
index 4c9bb89fc86e4cb3de41ce5865c2802ade814cb7..493171ef82db80ff7b6ba1bb8a9662ee06dce717 100644 (file)
@@ -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,
index 4ce2f4db00177805e29122315712494f6e109112..75f9573b2e5d5572c18fd3799a70abee94dcdfcd 100644 (file)
@@ -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");
+               }
        }
 }
index af72784e84a13d19447b01ae5ecfe7cbeea33084..c09ac282424d543ca59dcaf91464dc189877e271 100644 (file)
@@ -865,6 +865,8 @@ enum
 
        D_INDIR,        /* additive */
 
+       D_LAST,
+
        T_TYPE          = 1<<0,
        T_INDEX         = 1<<1,
        T_OFFSET        = 1<<2,
index 0e2d165b17eb5e5f5264666143682af448f5da00..5445f91275e792fa8c76534a57e743e017053ded 100644 (file)
@@ -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,
index aa39dbd43f50aa73231a7772be3a5b69d566ab7c..13beaf94144a9af2977d0865c0c99f747a202657 100644 (file)
@@ -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");
+               }
        }
 }
index ed54f6744abfa35121b12671dd877d4837214953..596c5f61a8f9a32f15911d4c7b387eefa4d8be7a 100644 (file)
@@ -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,
index b911a23998364ebc75d46834f268cdde0748ebe2..2e546a95bb19dd605ccdd06958c4e38490e778e5 100644 (file)
@@ -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);
index 08a339318de8ce54369b00c93aa4b90fa3fce773..87917f88ac6ac7e6676aa6ba83b892fad5ed0b1b 100644 (file)
@@ -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
index 1c3329758733a18ab591233b1d739d5b9b32fc25..64434d51e16852112ee26aa63a503a0b3fa7bdaf 100644 (file)
@@ -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]);
 }
index 0635fdf1feb55d45c65cabd6f8a639c7e7417225..54cce4aa4b0573cdc7bb96f54abfbfadea4cb941 100644 (file)
@@ -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);
index 512ed5a1199125239c9971d7b1c4e56fe7ed936a..5436e36ac7f0ba4b29932c92fc0b7d121742a263 100644 (file)
@@ -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));