diff options
Diffstat (limited to 'src/cmd')
46 files changed, 709 insertions, 463 deletions
diff --git a/src/cmd/5a/lex.c b/src/cmd/5a/lex.c index b36094a78..e762f5646 100644 --- a/src/cmd/5a/lex.c +++ b/src/cmd/5a/lex.c @@ -187,7 +187,7 @@ assemble(char *file) pass = 1; pinit(file); - Bprint(&obuf, "%s\n", thestring); + Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c index 43eb73c94..d45aabc5e 100644 --- a/src/cmd/5c/swt.c +++ b/src/cmd/5c/swt.c @@ -373,7 +373,7 @@ outcode(void) } } - Bprint(&outbuf, "%s\n", thestring); + Bprint(&outbuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); if(ndynimp > 0 || ndynexp > 0) { int i; diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c index 78f2f4aeb..4da8db2ae 100644 --- a/src/cmd/5g/cgen64.c +++ b/src/cmd/5g/cgen64.c @@ -64,17 +64,21 @@ cgen64(Node *n, Node *res) return; case OCOM: + regalloc(&t1, lo1.type, N); + gmove(ncon(-1), &t1); + split64(res, &lo2, &hi2); regalloc(&n1, lo1.type, N); gins(AMOVW, &lo1, &n1); - gins(AMVN, &n1, &n1); + gins(AEOR, &t1, &n1); gins(AMOVW, &n1, &lo2); gins(AMOVW, &hi1, &n1); - gins(AMVN, &n1, &n1); + gins(AEOR, &t1, &n1); gins(AMOVW, &n1, &hi2); + regfree(&t1); regfree(&n1); splitclean(); splitclean(); @@ -204,14 +208,17 @@ cgen64(Node *n, Node *res) // here and below (verify it optimizes to EOR) gins(AEOR, &al, &al); gins(AEOR, &ah, &ah); - } else if(v > 32) { + } else + if(v > 32) { gins(AEOR, &al, &al); // MOVW bl<<(v-32), ah gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah); - } else if(v == 32) { + } else + if(v == 32) { gins(AEOR, &al, &al); gins(AMOVW, &bl, &ah); - } else if(v > 0) { + } else + if(v > 0) { // MOVW bl<<v, al gshift(AMOVW, &bl, SHIFT_LL, v, &al); @@ -341,7 +348,8 @@ olsh_break: gins(AEOR, &al, &al); gins(AEOR, &ah, &ah); } - } else if(v > 32) { + } else + if(v > 32) { if(bh.type->etype == TINT32) { // MOVW bh->(v-32), al gshift(AMOVW, &bh, SHIFT_AR, v-32, &al); @@ -353,7 +361,8 @@ olsh_break: gshift(AMOVW, &bh, SHIFT_LR, v-32, &al); gins(AEOR, &ah, &ah); } - } else if(v == 32) { + } else + if(v == 32) { gins(AMOVW, &bh, &al); if(bh.type->etype == TINT32) { // MOVW bh->31, ah @@ -361,7 +370,8 @@ olsh_break: } else { gins(AEOR, &ah, &ah); } - } else if( v > 0) { + } else + if( v > 0) { // MOVW bl>>v, al gshift(AMOVW, &bl, SHIFT_LR, v, &al); @@ -384,11 +394,16 @@ olsh_break: regalloc(&s, types[TUINT32], N); regalloc(&creg, types[TUINT32], N); - if (is64(r->type)) { + if(is64(r->type)) { // shift is >= 1<<32 split64(r, &cl, &ch); gmove(&ch, &s); - p1 = gins(ATST, &s, N); + gins(ATST, &s, N); + if(bh.type->etype == TINT32) + p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); + else + p1 = gins(AEOR, &ah, &ah); + p1->scond = C_SCOND_NE; p6 = gbranch(ABNE, T); gmove(&cl, &s); splitclean(); @@ -441,7 +456,6 @@ olsh_break: p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); else p1 = gins(AEOR, &ah, &ah); - p1->scond = C_SCOND_EQ; p4 = gbranch(ABEQ, T); // check if shift is < 64 @@ -461,33 +475,23 @@ olsh_break: // MOVW bh->(s-32), al p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al); p1->scond = C_SCOND_LO; - - // MOVW bh->31, ah - p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); - p1->scond = C_SCOND_LO; } else { // MOVW bh>>(v-32), al p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al); p1->scond = C_SCOND_LO; - - p1 = gins(AEOR, &ah, &ah); - p1->scond = C_SCOND_LO; } // BLO end p5 = gbranch(ABLO, T); // s >= 64 - if (p6 != P) patch(p6, pc); + if(p6 != P) + patch(p6, pc); if(bh.type->etype == TINT32) { // MOVW bh->31, al gshift(AMOVW, &bh, SHIFT_AR, 31, &al); - - // MOVW bh->31, ah - gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); } else { gins(AEOR, &al, &al); - gins(AEOR, &ah, &ah); } patch(p2, pc); diff --git a/src/cmd/5g/list.c b/src/cmd/5g/list.c index ce74d6478..0c6dbbf71 100644 --- a/src/cmd/5g/list.c +++ b/src/cmd/5g/list.c @@ -87,6 +87,10 @@ Dconv(Fmt *fp) int32 v; a = va_arg(fp->args, Addr*); + if(a == A) { + sprint(str, "<nil>"); + goto conv; + } i = a->type; switch(i) { @@ -183,7 +187,7 @@ Dconv(Fmt *fp) // a->type = D_ADDR; // goto conv; } -//conv: +conv: return fmtstrcpy(fp, str); } diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c index f619a6206..ca12d70f2 100644 --- a/src/cmd/5g/peep.c +++ b/src/cmd/5g/peep.c @@ -48,7 +48,6 @@ peep(void) /* * complete R structure */ - t = 0; for(r=firstr; r!=R; r=r1) { r1 = r->link; if(r1 == R) @@ -68,7 +67,6 @@ peep(void) r1->p1 = r2; r = r2; - t++; case ADATA: case AGLOBL: @@ -77,8 +75,10 @@ peep(void) p = p->link; } } +//dumpit("begin", firstr); loop1: + t = 0; for(r=firstr; r!=R; r=r->link) { p = r->prog; @@ -99,71 +99,75 @@ loop1: case AMOVW: case AMOVF: case AMOVD: - if(!regtyp(&p->to)) - break; -// if(isdconst(&p->from)) { -// constprop(&p->from, &p->to, r->s1); -// break; -// } - if(!regtyp(&p->from)) - break; - if(p->from.type != p->to.type) - break; - if(copyprop(r)) { - excise(r); - t++; - break; + if(regtyp(&p->from)) + if(p->from.type == p->to.type) + if(p->scond == C_SCOND_NONE) { + if(copyprop(r)) { + excise(r); + t++; + break; + } + if(subprop(r) && copyprop(r)) { + excise(r); + t++; + break; + } } - if(subprop(r) && copyprop(r)) { - excise(r); - t++; - break; + break; + + if(p->scond == C_SCOND_NONE) + if(regtyp(&p->to)) + if(isdconst(&p->from)) { + constprop(&p->from, &p->to, r->s1); } + break; } } if(t) goto loop1; - /* - * look for MOVB x,R; MOVB R,R - */ + +return; + for(r=firstr; r!=R; r=r->link) { p = r->prog; switch(p->as) { - default: - continue; - case AEOR: - /* - * EOR -1,x,y => MVN x,y - */ - if(isdconst(&p->from) && p->from.offset == -1) { - p->as = AMVN; - p->from.type = D_REG; - if(p->reg != NREG) - p->from.reg = p->reg; - else - p->from.reg = p->to.reg; - p->reg = NREG; - } - continue; +// case AEOR: +// /* +// * EOR -1,x,y => MVN x,y +// */ +// if(isdconst(&p->from) && p->from.offset == -1) { +// p->as = AMVN; +// p->from.type = D_REG; +// if(p->reg != NREG) +// p->from.reg = p->reg; +// else +// p->from.reg = p->to.reg; +// p->reg = NREG; +// } +// break; + case AMOVH: case AMOVHU: case AMOVB: case AMOVBU: + /* + * look for MOVB x,R; MOVB R,R + */ if(p->to.type != D_REG) - continue; + break; + if(r1 == R) + break; + p1 = r1->prog; + if(p1->as != p->as) + break; + if(p1->from.type != D_REG || p1->from.reg != p->to.reg) + break; + if(p1->to.type != D_REG || p1->to.reg != p->to.reg) + break; + excise(r1); break; } r1 = r->link; - if(r1 == R) - continue; - p1 = r1->prog; - if(p1->as != p->as) - continue; - if(p1->from.type != D_REG || p1->from.reg != p->to.reg) - continue; - if(p1->to.type != D_REG || p1->to.reg != p->to.reg) - continue; - excise(r1); } // for(r=firstr; r!=R; r=r->link) { @@ -335,6 +339,8 @@ subprop(Reg *r0) case AMULLU: case AMULA: + case AMVN: + return 0; case ACMN: case AADD: @@ -347,7 +353,6 @@ subprop(Reg *r0) case AORR: case AAND: case AEOR: - case AMVN: case AMUL: case AMULU: case ADIV: @@ -364,7 +369,8 @@ subprop(Reg *r0) case ADIVD: case ADIVF: if(p->to.type == v1->type) - if(p->to.reg == v1->reg) { + if(p->to.reg == v1->reg) + if(p->scond == C_SCOND_NONE) { if(p->reg == NREG) p->reg = p->to.reg; goto gotit; @@ -376,6 +382,7 @@ subprop(Reg *r0) case AMOVW: if(p->to.type == v1->type) if(p->to.reg == v1->reg) + if(p->scond == C_SCOND_NONE) goto gotit; break; @@ -662,7 +669,7 @@ shiftprop(Reg *r) FAIL("can't swap"); if(p1->reg == NREG && p1->to.reg == n) FAIL("shift result used twice"); - case AMVN: +// case AMVN: if(p1->from.type == D_SHIFT) FAIL("shift result used in shift"); if(p1->from.type != D_REG || p1->from.reg != n) @@ -971,7 +978,7 @@ copyu(Prog *p, Adr *v, Adr *s) } return 0; - case ANOP: /* read, write */ + case ANOP: /* read,, write */ case AMOVW: case AMOVF: case AMOVD: @@ -979,6 +986,8 @@ copyu(Prog *p, Adr *v, Adr *s) case AMOVHU: case AMOVB: case AMOVBU: + case AMOVFW: + case AMOVWF: case AMOVDW: case AMOVWD: case AMOVFD: @@ -1014,6 +1023,7 @@ copyu(Prog *p, Adr *v, Adr *s) case AMULLU: /* read, read, write, write */ case AMULA: + case AMVN: return 2; case AADD: /* read, read, write */ @@ -1027,7 +1037,6 @@ copyu(Prog *p, Adr *v, Adr *s) case AORR: case AAND: case AEOR: - case AMVN: case AMUL: case AMULU: case ADIV: @@ -1043,12 +1052,12 @@ copyu(Prog *p, Adr *v, Adr *s) case ADIVF: case ADIVD: - case ACMPF: + case ACMPF: /* read, read, */ case ACMPD: - case ATST: case ACMP: case ACMN: case ACASE: + case ATST: /* read,, */ if(s != A) { if(copysub(&p->from, v, s, 1)) return 1; @@ -1150,53 +1159,6 @@ copyu(Prog *p, Adr *v, Adr *s) return 0; } -int -a2type(Prog *p) -{ - - switch(p->as) { - - case ATST: - case ACMP: - case ACMN: - - case AMULLU: - case AMULA: - - case AADD: - case ASUB: - case ARSB: - case ASLL: - case ASRL: - case ASRA: - case AORR: - case AAND: - case AEOR: - case AMVN: - case AMUL: - case AMULU: - case ADIV: - case ADIVU: - case AMOD: - case AMODU: - return D_REG; - - case ACMPF: - case ACMPD: - - case AADDF: - case AADDD: - case ASUBF: - case ASUBD: - case AMULF: - case AMULD: - case ADIVF: - case ADIVD: - return D_FREG; - } - return D_NONE; -} - /* * direct reference, * could be set/use depending on @@ -1233,15 +1195,15 @@ copyau(Adr *a, Adr *v) return 1; if(v->type == D_REG) { if(a->type == D_CONST && a->reg != NREG) { - if(v->reg == a->reg) + if(a->reg == v->reg) return 1; } else if(a->type == D_OREG) { - if(v->reg == a->reg) + if(a->reg == v->reg) return 1; } else if(a->type == D_REGREG) { - if(v->reg == a->reg) + if(a->reg == v->reg) return 1; if(a->offset == v->reg) return 1; @@ -1256,17 +1218,33 @@ copyau(Adr *a, Adr *v) return 0; } +/* + * compare v to the center + * register in p (p->reg) + * the trick is that this + * register might be D_REG + * D_FREG. there are basically + * two cases, + * ADD r,r,r + * CMP r,r, + */ int copyau1(Prog *p, Adr *v) { - if(regtyp(v)) { - if(a2type(p) == v->type) - if(p->reg == v->reg) { - if(a2type(p) != v->type) - print("botch a2type %P\n", p); - return 1; + if(regtyp(v)) + if(p->reg == v->reg) { + if(p->to.type != D_NONE) { + if(v->type == p->to.type) + return 1; + return 0; + } + if(p->from.type != D_NONE) { + if(v->type == p->from.type) + return 1; + return 0; } + print("copyau1: cant tell %P\n", p); } return 0; } @@ -1479,24 +1457,24 @@ applypred(Reg *rstart, Joininfo *j, int cond, int branch) pred = predinfo[rstart->prog->as - ABEQ].notscond; for(r = j->start;; r = successor(r)) { - if (r->prog->as == AB) { - if (r != j->last || branch == Delbranch) + if(r->prog->as == AB) { + if(r != j->last || branch == Delbranch) excise(r); else { - if (cond == Truecond) + if(cond == Truecond) r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode; else r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode; } } else - if (predicable(r->prog)) + if(predicable(r->prog)) r->prog->scond = (r->prog->scond&~C_SCOND)|pred; - if (r->s1 != r->link) { + if(r->s1 != r->link) { r->s1 = r->link; r->link->p1 = r; } - if (r == j->last) + if(r == j->last) break; } } diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index eaf02b237..f31f70535 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -140,8 +140,8 @@ regopt(Prog *firstp) if(first == 0) { fmtinstall('Q', Qconv); } - first++; + first++; if(debug['K']) { if(first != 13) return; @@ -491,7 +491,7 @@ brk: * peep-hole on basic block */ if(!debug['R'] || debug['P']) { -// peep(); + peep(); } /* @@ -1375,3 +1375,71 @@ noreturn(Prog *p) return 1; return 0; } + +void +dumpone(Reg *r) +{ + int z; + Bits bit; + + print("%d:%P", r->loop, r->prog); + for(z=0; z<BITS; z++) + bit.b[z] = + r->set.b[z] | + r->use1.b[z] | + r->use2.b[z] | + r->refbehind.b[z] | + r->refahead.b[z] | + r->calbehind.b[z] | + r->calahead.b[z] | + r->regdiff.b[z] | + r->act.b[z] | + 0; +// if(bany(&bit)) { +// print("\t"); +// if(bany(&r->set)) +// print(" s:%Q", r->set); +// if(bany(&r->use1)) +// print(" u1:%Q", r->use1); +// if(bany(&r->use2)) +// print(" u2:%Q", r->use2); +// if(bany(&r->refbehind)) +// print(" rb:%Q ", r->refbehind); +// if(bany(&r->refahead)) +// print(" ra:%Q ", r->refahead); +// if(bany(&r->calbehind)) +// print("cb:%Q ", r->calbehind); +// if(bany(&r->calahead)) +// print(" ca:%Q ", r->calahead); +// if(bany(&r->regdiff)) +// print(" d:%Q ", r->regdiff); +// if(bany(&r->act)) +// print(" a:%Q ", r->act); +// } + print("\n"); +} + +void +dumpit(char *str, Reg *r0) +{ + Reg *r, *r1; + + print("\n%s\n", str); + for(r = r0; r != R; r = r->link) { + dumpone(r); + r1 = r->p2; + if(r1 != R) { + print(" pred:"); + for(; r1 != R; r1 = r1->p2link) + print(" %.4ud", r1->prog->loc); + print("\n"); + } +// r1 = r->s1; +// if(r1 != R) { +// print(" succ:"); +// for(; r1 != R; r1 = r1->s1) +// print(" %.4ud", r1->prog->loc); +// print("\n"); +// } + } +} diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index 34565629f..7163997c0 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -637,13 +637,6 @@ wput(int32 l) cflush(); } -void -wputl(ushort w) -{ - cput(w); - cput(w>>8); -} - void hput(int32 l) @@ -672,20 +665,6 @@ lput(int32 l) } void -lputl(int32 l) -{ - - cbp[3] = l>>24; - cbp[2] = l>>16; - cbp[1] = l>>8; - cbp[0] = l; - cbp += 4; - cbc -= 4; - if(cbc <= 0) - cflush(); -} - -void cflush(void) { int n; @@ -1491,15 +1470,24 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o1 |= (p->scond & C_SCOND) << 28; break; case 80: /* fmov zfcon,freg */ - if((p->scond & C_SCOND) != C_SCOND_NONE) - diag("floating point cannot be conditional"); // cant happen - o1 = 0xf3000110; // EOR 64 - - // always clears the double float register + if(p->as == AMOVD) { + o1 = 0xeeb00b00; // VMOV imm 64 + o2 = oprrr(ASUBD, p->scond); + } else { + o1 = 0x0eb00a00; // VMOV imm 32 + o2 = oprrr(ASUBF, p->scond); + } + v = 0x70; // 1.0 r = p->to.reg; - o1 |= r << 0; + + // movf $1.0, r + o1 |= (p->scond & C_SCOND) << 28; o1 |= r << 12; - o1 |= r << 16; + o1 |= (v&0xf) << 0; + o1 |= (v&0xf0) << 12; + + // subf r,r,r + o2 |= r | (r<<16) | (r<<12); break; case 81: /* fmov sfcon,freg */ o1 = 0x0eb00a00; // VMOV imm 32 diff --git a/src/cmd/5l/l.h b/src/cmd/5l/l.h index c31028416..e42be4e98 100644 --- a/src/cmd/5l/l.h +++ b/src/cmd/5l/l.h @@ -410,6 +410,7 @@ Sym* lookup(char*, int); void cput(int); void hput(int32); void lput(int32); +void lputb(int32); void lputl(int32); void* mysbrk(uint32); void names(void); diff --git a/src/cmd/5l/optab.c b/src/cmd/5l/optab.c index 9ad0193ac..8b3135e06 100644 --- a/src/cmd/5l/optab.c +++ b/src/cmd/5l/optab.c @@ -236,7 +236,7 @@ Optab optab[] = { ALDREX, C_SOREG,C_NONE, C_REG, 77, 4, 0 }, { ASTREX, C_SOREG,C_REG, C_REG, 78, 4, 0 }, - { AMOVF, C_ZFCON,C_NONE, C_FREG, 80, 4, 0 }, + { AMOVF, C_ZFCON,C_NONE, C_FREG, 80, 8, 0 }, { AMOVF, C_SFCON,C_NONE, C_FREG, 81, 4, 0 }, { ACMPF, C_FREG, C_REG, C_NONE, 82, 8, 0 }, diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c index 1b8bb6344..37144c888 100644 --- a/src/cmd/6a/lex.c +++ b/src/cmd/6a/lex.c @@ -189,7 +189,7 @@ assemble(char *file) pass = 1; pinit(file); - Bprint(&obuf, "%s\n", thestring); + Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c index 47975a0c8..6d886f459 100644 --- a/src/cmd/6c/swt.c +++ b/src/cmd/6c/swt.c @@ -231,7 +231,7 @@ outcode(void) } Binit(&b, f, OWRITE); - Bprint(&b, "%s\n", thestring); + Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); if(ndynimp > 0 || ndynexp > 0) { int i; diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index d6ffa4ff9..d179e77b1 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -63,52 +63,6 @@ entryvalue(void) return s->value; } -void -wputl(uint16 w) -{ - cput(w); - cput(w>>8); -} - -void -wputb(uint16 w) -{ - cput(w>>8); - cput(w); -} - -void -lputb(int32 l) -{ - cput(l>>24); - cput(l>>16); - cput(l>>8); - cput(l); -} - -void -vputb(uint64 v) -{ - lputb(v>>32); - lputb(v); -} - -void -lputl(int32 l) -{ - cput(l); - cput(l>>8); - cput(l>>16); - cput(l>>24); -} - -void -vputl(uint64 v) -{ - lputl(v); - lputl(v>>32); -} - vlong datoff(vlong addr) { diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index 7f22493e0..70473ecd2 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -429,6 +429,7 @@ vlong rnd(vlong, vlong); void span(void); void undef(void); vlong symaddr(Sym*); +void vputb(uint64); void vputl(uint64); void wputb(uint16); void wputl(uint16); diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c index bf298b266..d5fa959aa 100644 --- a/src/cmd/8a/lex.c +++ b/src/cmd/8a/lex.c @@ -189,7 +189,7 @@ assemble(char *file) pass = 1; pinit(file); - Bprint(&obuf, "%s\n", thestring); + Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); for(i=0; i<nDlist; i++) dodefine(Dlist[i]); diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c index be48885f8..d07a5439c 100644 --- a/src/cmd/8c/swt.c +++ b/src/cmd/8c/swt.c @@ -230,7 +230,7 @@ outcode(void) } Binit(&b, f, OWRITE); - Bprint(&b, "%s\n", thestring); + Bprint(&b, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); if(ndynimp > 0 || ndynexp > 0) { int i; diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index 6e83d8dea..d90eab7e7 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -59,45 +59,6 @@ entryvalue(void) return s->value; } -void -wputl(ushort w) -{ - cput(w); - cput(w>>8); -} - -void -wput(ushort w) -{ - cput(w>>8); - cput(w); -} - -void -lput(int32 l) -{ - cput(l>>24); - cput(l>>16); - cput(l>>8); - cput(l); -} - -void -lputl(int32 l) -{ - cput(l); - cput(l>>8); - cput(l>>16); - cput(l>>24); -} - -void -vputl(uvlong l) -{ - lputl(l >> 32); - lputl(l); -} - vlong datoff(vlong addr) { @@ -688,6 +649,8 @@ asmb(void) ElfPhdr *ph, *pph; ElfShdr *sh; Section *sect; + Sym *sym; + int i; if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); @@ -741,7 +704,7 @@ asmb(void) seek(cout, rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen, 0); break; case 2: - seek(cout, HEADR+segtext.filelen+segdata.filelen, 0); + symo = HEADR+segtext.filelen+segdata.filelen; break; case 3: case 4: @@ -761,11 +724,27 @@ asmb(void) symo = rnd(symo, PEFILEALIGN); break; } - if(HEADTYPE != 10 && !debug['s']) { + if(!debug['s']) { seek(cout, symo, 0); - if(debug['v']) - Bprint(&bso, "%5.2f dwarf\n", cputime()); - dwarfemitdebugsections(); + + if(HEADTYPE == 2) { + asmplan9sym(); + cflush(); + + sym = lookup("pclntab", 0); + if(sym != nil) { + lcsize = sym->np; + for(i=0; i < lcsize; i++) + cput(sym->p[i]); + + cflush(); + } + + } else if(HEADTYPE != 10) { + if(debug['v']) + Bprint(&bso, "%5.2f dwarf\n", cputime()); + dwarfemitdebugsections(); + } } } if(debug['v']) @@ -777,25 +756,25 @@ asmb(void) if(iself) goto Elfput; case 0: /* garbage */ - lput(0x160L<<16); /* magic and sections */ - lput(0L); /* time and date */ - lput(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen); - lput(symsize); /* nsyms */ - lput((0x38L<<16)|7L); /* size of optional hdr and flags */ - lput((0413<<16)|0437L); /* magic and version */ - lput(rnd(HEADR+segtext.filelen, 4096)); /* sizes */ - lput(segdata.filelen); - lput(segdata.len - segdata.filelen); - lput(entryvalue()); /* va of entry */ - lput(INITTEXT-HEADR); /* va of base of text */ - lput(segdata.vaddr); /* va of base of data */ - lput(segdata.vaddr+segdata.filelen); /* va of base of bss */ - lput(~0L); /* gp reg mask */ - lput(0L); - lput(0L); - lput(0L); - lput(0L); - lput(~0L); /* gp value ?? */ + lputb(0x160L<<16); /* magic and sections */ + lputb(0L); /* time and date */ + lputb(rnd(HEADR+segtext.filelen, 4096)+segdata.filelen); + lputb(symsize); /* nsyms */ + lputb((0x38L<<16)|7L); /* size of optional hdr and flags */ + lputb((0413<<16)|0437L); /* magic and version */ + lputb(rnd(HEADR+segtext.filelen, 4096)); /* sizes */ + lputb(segdata.filelen); + lputb(segdata.len - segdata.filelen); + lputb(entryvalue()); /* va of entry */ + lputb(INITTEXT-HEADR); /* va of base of text */ + lputb(segdata.vaddr); /* va of base of data */ + lputb(segdata.vaddr+segdata.filelen); /* va of base of bss */ + lputb(~0L); /* gp reg mask */ + lputb(0L); + lputb(0L); + lputb(0L); + lputb(0L); + lputb(~0L); /* gp value ?? */ break; lputl(0); /* x */ case 1: /* unix coff */ @@ -814,7 +793,7 @@ asmb(void) lputl(rnd(segtext.filelen, INITRND)); /* text sizes */ lputl(segdata.filelen); /* data sizes */ lputl(segdata.len - segdata.filelen); /* bss sizes */ - lput(entryvalue()); /* va of entry */ + lputb(entryvalue()); /* va of entry */ lputl(INITTEXT); /* text start */ lputl(segdata.vaddr); /* data start */ /* @@ -868,14 +847,14 @@ asmb(void) break; case 2: /* plan9 */ magic = 4*11*11+7; - lput(magic); /* magic */ - lput(segtext.filelen); /* sizes */ - lput(segdata.filelen); - lput(segdata.len - segdata.filelen); - lput(symsize); /* nsyms */ - lput(entryvalue()); /* va of entry */ - lput(spsize); /* sp offsets */ - lput(lcsize); /* line offsets */ + lputb(magic); /* magic */ + lputb(segtext.filelen); /* sizes */ + lputb(segdata.filelen); + lputb(segdata.len - segdata.filelen); + lputb(symsize); /* nsyms */ + lputb(entryvalue()); /* va of entry */ + lputb(spsize); /* sp offsets */ + lputb(lcsize); /* line offsets */ break; case 3: /* MS-DOS .COM */ diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h index e0746fc75..f2546cf20 100644 --- a/src/cmd/8l/l.h +++ b/src/cmd/8l/l.h @@ -363,9 +363,9 @@ void follow(void); void instinit(void); void listinit(void); Sym* lookup(char*, int); -void lput(int32); +void lputb(int32); void lputl(int32); -void vputl(uvlong); +void vputl(uint64); void strnput(char*, int); void main(int, char*[]); void* mal(uint32); diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index fefb6d8b0..9c687f2fc 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -188,6 +188,7 @@ main(int argc, char *argv[]) INITRND = 0; break; case 2: /* plan 9 */ + tlsoffset = -8; HEADR = 32L; if(INITTEXT == -1) INITTEXT = 4096+32; diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c index 878a73dac..67acfa167 100644 --- a/src/cmd/8l/pass.c +++ b/src/cmd/8l/pass.c @@ -250,6 +250,7 @@ patch(void) Prog *p, *q; Sym *s; int32 vexit; + Sym *plan9_tos; if(debug['v']) Bprint(&bso, "%5.2f mkfwd\n", cputime()); @@ -260,6 +261,10 @@ patch(void) Bflush(&bso); s = lookup("exit", 0); vexit = s->value; + + if(HEADTYPE == 2) + plan9_tos = lookup("_tos", 0); + for(cursym = textp; cursym != nil; cursym = cursym->next) { for(p = cursym->text; p != P; p = p->link) { if(HEADTYPE == 10) { // Windows @@ -303,9 +308,15 @@ patch(void) if(HEADTYPE == 2) { // Plan 9 if(p->from.type == D_INDIR+D_GS && p->to.type >= D_AX && p->to.type <= D_DI) { + q = appendp(p); + q->from = p->from; + q->from.type = D_INDIR + p->to.type; + q->to = p->to; + q->as = p->as; p->as = AMOVL; - p->from.type = D_ADDR+D_STATIC; - p->from.offset += 0xdfffefc0; + p->from.type = D_EXTERN; + p->from.sym = plan9_tos; + p->from.offset = 0; } } if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH)) { @@ -389,6 +400,7 @@ dostkoff(void) int a; Prog *pmorestack; Sym *symmorestack; + Sym *plan9_tos; pmorestack = P; symmorestack = lookup("runtime.morestack", 0); @@ -399,6 +411,9 @@ dostkoff(void) pmorestack = symmorestack->text; symmorestack->text->from.scale |= NOSPLIT; } + + if(HEADTYPE == 2) + plan9_tos = lookup("_tos", 0); for(cursym = textp; cursym != nil; cursym = cursym->next) { if(cursym->text == nil || cursym->text->link == nil) @@ -443,9 +458,15 @@ dostkoff(void) case 2: // Plan 9 p->as = AMOVL; - p->from.type = D_ADDR+D_STATIC; - p->from.offset = 0xdfffefc0; + p->from.type = D_EXTERN; + p->from.sym = plan9_tos; p->to.type = D_CX; + + p = appendp(p); + p->as = AMOVL; + p->from.type = D_INDIR+D_CX; + p->from.offset = tlsoffset + 0; + p->to.type = D_CX; break; default: diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index c4868345c..b3aa9aded 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -25,9 +25,12 @@ the package. For example: CFLAGS and LDFLAGS may be defined with pseudo #cgo directives within these comments to tweak the behavior of gcc. Values defined -in multiple directives are concatenated together. For example: +in multiple directives are concatenated together. Options prefixed +by $GOOS, $GOARCH, or $GOOS/$GOARCH are only defined in matching +systems. For example: // #cgo CFLAGS: -DPNG_DEBUG=1 + // #cgo linux CFLAGS: -DLINUX=1 // #cgo LDFLAGS: -lpng // #include <png.h> import "C" diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index cadc6fae9..e6ce21ed3 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -19,6 +19,7 @@ import ( "go/parser" "go/token" "os" + "runtime" "strconv" "strings" "unicode" @@ -66,6 +67,8 @@ func cname(s string) string { func (p *Package) ParseFlags(f *File, srcfile string) { linesIn := strings.Split(f.Preamble, "\n", -1) linesOut := make([]string, 0, len(linesIn)) + +NextLine: for _, line := range linesIn { l := strings.TrimSpace(line) if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(int(l[4])) { @@ -79,11 +82,29 @@ func (p *Package) ParseFlags(f *File, srcfile string) { fatal("%s: bad #cgo line: %s", srcfile, line) } - k := fields[0] - v := strings.TrimSpace(fields[1]) + var k string + kf := strings.Fields(fields[0]) + switch len(kf) { + case 1: + k = kf[0] + case 2: + k = kf[1] + switch kf[0] { + case runtime.GOOS: + case runtime.GOARCH: + case runtime.GOOS + "/" + runtime.GOARCH: + default: + continue NextLine + } + default: + fatal("%s: bad #cgo option: %s", srcfile, fields[0]) + } + if k != "CFLAGS" && k != "LDFLAGS" { fatal("%s: unsupported #cgo option %s", srcfile, k) } + + v := strings.TrimSpace(fields[1]) args, err := splitQuoted(v) if err != nil { fatal("%s: bad #cgo option %s: %s", srcfile, k, err.String()) @@ -288,7 +309,7 @@ func (p *Package) guessKinds(f *File) []*Name { var b bytes.Buffer b.WriteString(builtinProlog) b.WriteString(f.Preamble) - b.WriteString("void f(void) {\n") + b.WriteString("void __cgo__f__(void) {\n") b.WriteString("#line 0 \"cgo-test\"\n") for i, n := range toSniff { fmt.Fprintf(&b, "%s; enum { _cgo_enum_%d = %s }; /* cgo-test:%d */\n", n.C, i, n.C, i) @@ -753,6 +774,8 @@ var dwarfToName = map[string]string{ "double complex": "complexdouble", } +const signedDelta = 64 + // Type returns a *Type with the same memory layout as // dtype when used as the type of a variable or a struct field. func (c *typeConv) Type(dtype dwarf.Type) *Type { @@ -818,7 +841,19 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { t.Align = 1 case *dwarf.EnumType: - switch t.Size { + if t.Align = t.Size; t.Align >= c.ptrSize { + t.Align = c.ptrSize + } + t.C = "enum " + dt.EnumName + signed := 0 + t.EnumValues = make(map[string]int64) + for _, ev := range dt.Val { + t.EnumValues[ev.Name] = ev.Val + if ev.Val < 0 { + signed = signedDelta + } + } + switch t.Size + int64(signed) { default: fatal("unexpected: %d-byte enum type - %s", t.Size, dtype) case 1: @@ -829,14 +864,14 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { t.Go = c.uint32 case 8: t.Go = c.uint64 - } - if t.Align = t.Size; t.Align >= c.ptrSize { - t.Align = c.ptrSize - } - t.C = "enum " + dt.EnumName - t.EnumValues = make(map[string]int64) - for _, ev := range dt.Val { - t.EnumValues[ev.Name] = ev.Val + case 1 + signedDelta: + t.Go = c.int8 + case 2 + signedDelta: + t.Go = c.int16 + case 4 + signedDelta: + t.Go = c.int32 + case 8 + signedDelta: + t.Go = c.int64 } case *dwarf.FloatType: diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go index a6f509dc4..59529a6d2 100644 --- a/src/cmd/cgo/util.go +++ b/src/cmd/cgo/util.go @@ -32,10 +32,11 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) { if err != nil { fatal("%s", err) } - pid, err := os.ForkExec(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2}) + p, err := os.StartProcess(cmd, argv, os.Environ(), "", []*os.File{r0, w1, w2}) if err != nil { fatal("%s", err) } + defer p.Release() r0.Close() w1.Close() w2.Close() @@ -55,7 +56,7 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) { <-c <-c - w, err := os.Wait(pid, 0) + w, err := p.Wait(0) if err != nil { fatal("%s", err) } diff --git a/src/cmd/clean.bash b/src/cmd/clean.bash index 6349919a8..92d8cc5c9 100644 --- a/src/cmd/clean.bash +++ b/src/cmd/clean.bash @@ -3,9 +3,14 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. +gomake=gomake +if [ "$1" == "--gomake" -a "$2" != "" ]; then + gomake=$2 +fi + for i in cc 6l 6a 6c 8l 8a 8c 8g 5l 5a 5c 5g gc 6g gopack nm cgo cov ebnflint godefs godoc gofmt goinstall gotest goyacc hgpatch prof do cd $i - gomake clean + $gomake clean cd .. done diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c index ed20e7e8b..833eba19a 100644 --- a/src/cmd/gc/align.c +++ b/src/cmd/gc/align.c @@ -54,7 +54,8 @@ widstruct(Type *t, uint32 o, int flag) if(f->type->width < 0) fatal("invalid width %lld", f->type->width); w = f->type->width; - o = rnd(o, f->type->align); + if(f->type->align > 0) + o = rnd(o, f->type->align); f->width = o; // really offset for TFIELD if(f->nname != N) { // this same stackparam logic is in addrescapes diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 994840ee8..86e3cae33 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -242,14 +242,6 @@ import_package: if(safemode && !curio.importsafe) yyerror("cannot import unsafe package %Z", importpkg->path); - - // NOTE(rsc): This is no longer a technical restriction: - // the 6g tool chain would work just fine without giving - // special meaning to a package being named main. - // Other implementations might need the restriction - // (gccgo does), so it stays in the language and the compiler. - if(strcmp($2->name, "main") == 0) - yyerror("cannot import package main"); } import_safety: diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index 45b1257fa..e79d3b0f8 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -405,7 +405,7 @@ void importfile(Val *f, int line) { Biobuf *imp; - char *file; + char *file, *p, *q; int32 c; int len; Strlit *path; @@ -423,6 +423,15 @@ importfile(Val *f, int line) errorexit(); } + // The package name main is no longer reserved, + // but we reserve the import path "main" to identify + // the main package, just as we reserve the import + // path "math" to identify the standard math package. + if(strcmp(f->u.sval->s, "main") == 0) { + yyerror("cannot import \"main\""); + errorexit(); + } + if(strcmp(f->u.sval->s, "unsafe") == 0) { if(safemode) { yyerror("cannot import package unsafe"); @@ -432,7 +441,7 @@ importfile(Val *f, int line) cannedimports("unsafe.6", unsafeimport); return; } - + path = f->u.sval; if(islocalname(path)) { cleanbuf = mal(strlen(pathname) + strlen(path->s) + 2); @@ -459,9 +468,24 @@ importfile(Val *f, int line) len = strlen(namebuf); if(len > 2 && namebuf[len-2] == '.' && namebuf[len-1] == 'a') { if(!skiptopkgdef(imp)) { - yyerror("import not package file: %s", namebuf); + yyerror("import %s: not a package file", file); + errorexit(); + } + } + + // check object header + p = Brdstr(imp, '\n', 1); + if(strcmp(p, "empty archive") != 0) { + if(strncmp(p, "go object ", 10) != 0) { + yyerror("import %s: not a go object file", file); errorexit(); } + q = smprint("%s %s %s", getgoos(), thestring, getgoversion()); + if(strcmp(p+10, q) != 0) { + yyerror("import %s: object is [%s] expected [%s]", file, p+10, q); + errorexit(); + } + free(q); } // assume files move (get installed) @@ -479,6 +503,7 @@ importfile(Val *f, int line) curio.infile = file; curio.nlsemi = 0; typecheckok = 1; + for(;;) { c = getc(); if(c == EOF) diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c index 7b7e66668..b11a4f5f1 100644 --- a/src/cmd/gc/mparith3.c +++ b/src/cmd/gc/mparith3.c @@ -179,7 +179,7 @@ mpdivfltflt(Mpflt *a, Mpflt *b) double mpgetflt(Mpflt *a) { - int s, i; + int s, i, e; uvlong v, vm; double f; @@ -200,12 +200,12 @@ mpgetflt(Mpflt *a) a->exp -= 1; } - // the magic numbers (64, 63, 53, 10) are + // the magic numbers (64, 63, 53, 10, -1074) are // IEEE specific. this should be done machine // independently or in the 6g half of the compiler - // pick up the mantissa in a uvlong - s = 53; + // pick up the mantissa and a rounding bit in a uvlong + s = 53+1; v = 0; for(i=Mpnorm-1; s>=Mpscale; i--) { v = (v<<Mpscale) | a->val.a[i]; @@ -224,13 +224,26 @@ mpgetflt(Mpflt *a) if(s > 0) v = (v<<s) | (a->val.a[i]>>(Mpscale-s)); + // gradual underflow + e = Mpnorm*Mpscale + a->exp - 53; + if(e < -1074) { + s = -e - 1074; + if(s > 54) + s = 54; + v |= vm & ((1ULL<<s) - 1); + vm >>= s; + e = -1074; + } + //print("vm=%.16llux v=%.16llux\n", vm, v); // round toward even - if(v != (1ULL<<63) || (vm&1ULL) != 0) - vm += v>>63; + if(v != 0 || (vm&2ULL) != 0) + vm = (vm>>1) + (vm&1ULL); + else + vm >>= 1; f = (double)(vm); - f = ldexp(f, Mpnorm*Mpscale + a->exp - 53); + f = ldexp(f, e); if(a->val.neg) f = -f; diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c index 0d0d70ac9..fbabe0d43 100644 --- a/src/cmd/gc/obj.c +++ b/src/cmd/gc/obj.c @@ -21,7 +21,7 @@ dumpobj(void) errorexit(); } - Bprint(bout, "%s\n", thestring); + Bprint(bout, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); Bprint(bout, " exports automatically generated from\n"); Bprint(bout, " %s in package \"%s\"\n", curio.infile, localpkg->name); dumpexport(); diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c index 5686e9599..58a147745 100644 --- a/src/cmd/gc/select.c +++ b/src/cmd/gc/select.c @@ -157,7 +157,7 @@ walkselect(Node *sel) if(n->left == N || isblank(n->left)) n->left = nodnil(); else if(n->left->op == ONAME && - (!n->colas || (n->class&PHEAP) == 0) && + (!n->colas || (n->left->class&PHEAP) == 0) && convertop(ch->type->type, n->left->type, nil) == OCONVNOP) { n->left = nod(OADDR, n->left, N); n->left->etype = 1; // pointer does not escape @@ -170,9 +170,9 @@ walkselect(Node *sel) typecheck(&a, Erv); r = nod(OAS, n->left, tmp); typecheck(&r, Etop); + cas->nbody = concat(list1(r), cas->nbody); cas->nbody = concat(n->ninit, cas->nbody); n->ninit = nil; - cas->nbody = concat(list1(r), cas->nbody); n->left = a; } } diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index cb5e2a831..0755ca3cd 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -203,6 +203,7 @@ fatal(char *fmt, ...) flusherrors(); +*(int*)0=0; print("%L: internal compiler error: ", lineno); va_start(arg, fmt); vfprint(1, fmt, arg); @@ -213,7 +214,7 @@ fatal(char *fmt, ...) if(strncmp(getgoversion(), "release", 7) == 0) { print("\n"); print("Please file a bug report including a short program that triggers the error.\n"); - print("http://code.google.com/p/go/issues/entry?template=compilerbug"); + print("http://code.google.com/p/go/issues/entry?template=compilerbug\n"); } hcrash(); errorexit(); diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index 931d0327a..5edca964a 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -96,7 +96,7 @@ typecheck(Node **np, int top) Node *n, *l, *r; NodeList *args; int lno, ok, ntop; - Type *t, *missing, *have; + Type *t, *tp, *missing, *have; Sym *sym; Val v; char *why; @@ -552,6 +552,7 @@ reswitch: ok = Erv; goto ret; } + tp = t; if(isptr[t->etype] && t->type->etype != TINTER) { t = t->type; if(t == T) @@ -563,7 +564,7 @@ reswitch: if(lookdot(n, t, 1)) yyerror("%#N undefined (cannot refer to unexported field or method %S)", n, n->right->sym); else - yyerror("%#N undefined (type %T has no field or method %S)", n, t, n->right->sym); + yyerror("%#N undefined (type %T has no field or method %S)", n, tp, n->right->sym); goto error; } switch(n->op) { diff --git a/src/cmd/godoc/format.go b/src/cmd/godoc/format.go index 66b01aa64..da1466b21 100644 --- a/src/cmd/godoc/format.go +++ b/src/cmd/godoc/format.go @@ -11,7 +11,6 @@ package main import ( - "bytes" "fmt" "go/scanner" "go/token" @@ -335,12 +334,12 @@ func selectionTag(w io.Writer, text []byte, selections int) { } -// FormatText HTML-escapes text and returns it wrapped in <pre> tags. -// Conscutive text segments are wrapped in HTML spans (with tags as +// FormatText HTML-escapes text and writes it to w. +// Consecutive text segments are wrapped in HTML spans (with tags as // defined by startTags and endTag) as follows: // -// - if line >= 0, line numbers are printed before each line, starting -// with the value of line +// - if line >= 0, line number (ln) spans are inserted before each line, +// starting with the value of line // - if the text is Go source, comments get the "comment" span class // - each occurrence of the regular expression pattern gets the "highlight" // span class @@ -349,10 +348,7 @@ func selectionTag(w io.Writer, text []byte, selections int) { // Comments, highlights, and selections may overlap arbitrarily; the respective // HTML span classes are specified in the startTags variable. // -func FormatText(text []byte, line int, goSource bool, pattern string, selection Selection) []byte { - var buf bytes.Buffer - buf.WriteString("<pre>\n") - +func FormatText(w io.Writer, text []byte, line int, goSource bool, pattern string, selection Selection) { var comments, highlights Selection if goSource { comments = commentSelection(text) @@ -370,11 +366,8 @@ func FormatText(text []byte, line int, goSource bool, pattern string, selection } } } - FormatSelections(&buf, text, lineTag, lineSelection(text), selectionTag, comments, highlights, selection) + FormatSelections(w, text, lineTag, lineSelection(text), selectionTag, comments, highlights, selection) } else { - template.HTMLEscape(&buf, text) + template.HTMLEscape(w, text) } - - buf.WriteString("</pre>\n") - return buf.Bytes() } diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 6a00a3e70..c91dc33db 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -274,7 +274,7 @@ func relativePath(path string) string { // ---------------------------------------------------------------------------- // Tab conversion -var spaces = []byte(" ") // 16 spaces seems like a good number +var spaces = []byte(" ") // 32 spaces seems like a good number const ( indenting = iota @@ -291,25 +291,31 @@ type tconv struct { func (p *tconv) writeIndent() (err os.Error) { i := p.indent - for i > len(spaces) { + for i >= len(spaces) { i -= len(spaces) if _, err = p.output.Write(spaces); err != nil { return } } - _, err = p.output.Write(spaces[0:i]) + // i < len(spaces) + if i > 0 { + _, err = p.output.Write(spaces[0:i]) + } return } func (p *tconv) Write(data []byte) (n int, err os.Error) { + if len(data) == 0 { + return + } pos := 0 // valid if p.state == collecting var b byte for n, b = range data { switch p.state { case indenting: switch b { - case '\t', '\v': + case '\t': p.indent += *tabwidth case '\n': p.indent = 0 @@ -336,7 +342,7 @@ func (p *tconv) Write(data []byte) (n int, err os.Error) { } } n = len(data) - if p.state == collecting { + if pos < n && p.state == collecting { _, err = p.output.Write(data[pos:]) } return @@ -346,47 +352,51 @@ func (p *tconv) Write(data []byte) (n int, err os.Error) { // ---------------------------------------------------------------------------- // Templates -// Write an AST-node to w; optionally html-escaped. -func writeNode(w io.Writer, fset *token.FileSet, node interface{}, html bool) { - mode := printer.TabIndent | printer.UseSpaces - if html { - mode |= printer.GenHTML - } +// Write an AST node to w. +func writeNode(w io.Writer, fset *token.FileSet, x interface{}) { // convert trailing tabs into spaces using a tconv filter // to ensure a good outcome in most browsers (there may still // be tabs in comments and strings, but converting those into // the right number of spaces is much harder) - (&printer.Config{mode, *tabwidth, nil}).Fprint(&tconv{output: w}, fset, node) + // + // TODO(gri) rethink printer flags - perhaps tconv can be eliminated + // with an another printer mode (which is more efficiently + // implemented in the printer than here with another layer) + mode := printer.TabIndent | printer.UseSpaces + (&printer.Config{mode, *tabwidth}).Fprint(&tconv{output: w}, fset, x) } -// Write text to w; optionally html-escaped. -func writeText(w io.Writer, text []byte, html bool) { - if html { - template.HTMLEscape(w, text) - return +// Write anything to w. +func writeAny(w io.Writer, fset *token.FileSet, x interface{}) { + switch v := x.(type) { + case []byte: + w.Write(v) + case string: + w.Write([]byte(v)) + case ast.Decl, ast.Expr, ast.Stmt, *ast.File: + writeNode(w, fset, x) + default: + fmt.Fprint(w, x) } - w.Write(text) } -// Write anything to w; optionally html-escaped. -func writeAny(w io.Writer, fset *token.FileSet, html bool, x interface{}) { +// Write anything html-escaped to w. +func writeAnyHTML(w io.Writer, fset *token.FileSet, x interface{}) { switch v := x.(type) { case []byte: - writeText(w, v, html) + template.HTMLEscape(w, v) case string: - writeText(w, []byte(v), html) + template.HTMLEscape(w, []byte(v)) case ast.Decl, ast.Expr, ast.Stmt, *ast.File: - writeNode(w, fset, x, html) + var buf bytes.Buffer + writeNode(&buf, fset, x) + FormatText(w, buf.Bytes(), -1, true, "", nil) default: - if html { - var buf bytes.Buffer - fmt.Fprint(&buf, x) - writeText(w, buf.Bytes(), true) - } else { - fmt.Fprint(w, x) - } + var buf bytes.Buffer + fmt.Fprint(&buf, x) + template.HTMLEscape(w, buf.Bytes()) } } @@ -401,24 +411,16 @@ func fileset(x []interface{}) *token.FileSet { } -// Template formatter for "html" format. -func htmlFmt(w io.Writer, format string, x ...interface{}) { - writeAny(w, fileset(x), true, x[0]) -} - - // Template formatter for "html-esc" format. func htmlEscFmt(w io.Writer, format string, x ...interface{}) { - var buf bytes.Buffer - writeAny(&buf, fileset(x), false, x[0]) - template.HTMLEscape(w, buf.Bytes()) + writeAnyHTML(w, fileset(x), x[0]) } // Template formatter for "html-comment" format. func htmlCommentFmt(w io.Writer, format string, x ...interface{}) { var buf bytes.Buffer - writeAny(&buf, fileset(x), false, x[0]) + writeAny(&buf, fileset(x), x[0]) // TODO(gri) Provide list of words (e.g. function parameters) // to be emphasized by ToHTML. doc.ToHTML(w, buf.Bytes(), nil) // does html-escaping @@ -427,14 +429,14 @@ func htmlCommentFmt(w io.Writer, format string, x ...interface{}) { // Template formatter for "" (default) format. func textFmt(w io.Writer, format string, x ...interface{}) { - writeAny(w, fileset(x), false, x[0]) + writeAny(w, fileset(x), x[0]) } // Template formatter for "urlquery-esc" format. func urlQueryEscFmt(w io.Writer, format string, x ...interface{}) { var buf bytes.Buffer - writeAny(&buf, fileset(x), false, x[0]) + writeAny(&buf, fileset(x), x[0]) template.HTMLEscape(w, []byte(http.URLEscape(string(buf.Bytes())))) } @@ -603,7 +605,6 @@ func numlinesFmt(w io.Writer, format string, x ...interface{}) { var fmap = template.FormatterMap{ "": textFmt, - "html": htmlFmt, "html-esc": htmlEscFmt, "html-comment": htmlCommentFmt, "urlquery-esc": urlQueryEscFmt, @@ -683,7 +684,7 @@ func servePage(w http.ResponseWriter, title, subtitle, query string, content []b content, } - if err := godocHTML.Execute(&d, w); err != nil { + if err := godocHTML.Execute(w, &d); err != nil { log.Printf("godocHTML.Execute: %s", err) } } @@ -751,7 +752,7 @@ func serveHTMLDoc(w http.ResponseWriter, r *http.Request, abspath, relpath strin func applyTemplate(t *template.Template, name string, data interface{}) []byte { var buf bytes.Buffer - if err := t.Execute(data, &buf); err != nil { + if err := t.Execute(&buf, data); err != nil { log.Printf("%s.Execute: %s", name, err) } return buf.Bytes() @@ -775,8 +776,12 @@ func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, tit return } - contents := FormatText(src, 1, pathutil.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s"))) - servePage(w, title+" "+relpath, "", "", contents) + var buf bytes.Buffer + buf.WriteString("<pre>") + FormatText(&buf, src, 1, pathutil.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s"))) + buf.WriteString("</pre>") + + servePage(w, title+" "+relpath, "", "", buf.Bytes()) } @@ -891,6 +896,11 @@ type PageInfo struct { } +func (info *PageInfo) IsEmpty() bool { + return info.Err != nil || info.PAst == nil && info.PDoc == nil && info.Dirs == nil +} + + type httpHandler struct { pattern string // url pattern; e.g. "/pkg/" fsRoot string // file system root to which the pattern is mapped diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go index 581409cde..56f31f5cf 100644 --- a/src/cmd/godoc/index.go +++ b/src/cmd/godoc/index.go @@ -430,7 +430,6 @@ func (a *AltWords) filter(s string) *AltWords { // Indexer // Adjust these flags as seems best. -const includeNonGoFiles = true const includeMainPackages = true const includeTestFiles = true @@ -728,7 +727,7 @@ func isWhitelisted(filename string) bool { } -func (x *Indexer) visitFile(dirname string, f *os.FileInfo) { +func (x *Indexer) visitFile(dirname string, f *os.FileInfo, fulltextIndex bool) { if !f.IsRegular() { return } @@ -746,7 +745,7 @@ func (x *Indexer) visitFile(dirname string, f *os.FileInfo) { } goFile = true - case !includeNonGoFiles || !isWhitelisted(f.Name): + case !fulltextIndex || !isWhitelisted(f.Name): return } @@ -811,7 +810,7 @@ func NewIndex(dirnames <-chan string, fulltextIndex bool) *Index { } for _, f := range list { if !f.IsDirectory() { - x.visitFile(dirname, f) + x.visitFile(dirname, f, fulltextIndex) } } } diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go index f1b11a760..ea1e3c42e 100644 --- a/src/cmd/godoc/main.go +++ b/src/cmd/godoc/main.go @@ -83,20 +83,21 @@ func exec(rw http.ResponseWriter, args []string) (status int) { if *verbose { log.Printf("executing %v", args) } - pid, err := os.ForkExec(bin, args, os.Environ(), *goroot, fds) + p, err := os.StartProcess(bin, args, os.Environ(), *goroot, fds) defer r.Close() w.Close() if err != nil { - log.Printf("os.ForkExec(%q): %v", bin, err) + log.Printf("os.StartProcess(%q): %v", bin, err) return 2 } + defer p.Release() var buf bytes.Buffer io.Copy(&buf, r) - wait, err := os.Wait(pid, 0) + wait, err := p.Wait(0) if err != nil { os.Stderr.Write(buf.Bytes()) - log.Printf("os.Wait(%d, 0): %v", pid, err) + log.Printf("os.Wait(%d, 0): %v", p.Pid, err) return 2 } status = wait.ExitStatus() @@ -317,7 +318,7 @@ func main() { } relpath := path abspath := path - if len(path) > 0 && path[0] != '/' { + if !pathutil.IsAbs(path) { abspath = absolutePath(path, pkgHandler.fsRoot) } else { relpath = relativePath(path) @@ -336,12 +337,17 @@ func main() { // if there are multiple packages in a directory. info := pkgHandler.getPageInfo(abspath, relpath, "", mode) - if info.Err != nil || info.PAst == nil && info.PDoc == nil && info.Dirs == nil { + if info.IsEmpty() { // try again, this time assume it's a command - if len(path) > 0 && path[0] != '/' { + if !pathutil.IsAbs(path) { abspath = absolutePath(path, cmdHandler.fsRoot) } - info = cmdHandler.getPageInfo(abspath, relpath, "", mode) + cmdInfo := cmdHandler.getPageInfo(abspath, relpath, "", mode) + // only use the cmdInfo if it actually contains a result + // (don't hide errors reported from looking up a package) + if !cmdInfo.IsEmpty() { + info = cmdInfo + } } if info.Err != nil { log.Fatalf("%v", info.Err) @@ -366,7 +372,11 @@ func main() { if i > 0 { fmt.Println() } - writeAny(os.Stdout, info.FSet, *html, d) + if *html { + writeAnyHTML(os.Stdout, info.FSet, d) + } else { + writeAny(os.Stdout, info.FSet, d) + } fmt.Println() } return @@ -376,7 +386,7 @@ func main() { } } - if err := packageText.Execute(info, os.Stdout); err != nil { + if err := packageText.Execute(os.Stdout, info); err != nil { log.Printf("packageText.Execute: %s", err) } } diff --git a/src/cmd/godoc/snippet.go b/src/cmd/godoc/snippet.go index c2838ed5a..c5f4c1edf 100755 --- a/src/cmd/godoc/snippet.go +++ b/src/cmd/godoc/snippet.go @@ -25,9 +25,14 @@ type Snippet struct { func newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet { // TODO instead of pretty-printing the node, should use the original source instead - var buf bytes.Buffer - writeNode(&buf, fset, decl, false) - return &Snippet{fset.Position(id.Pos()).Line, FormatText(buf.Bytes(), -1, true, id.Name, nil)} + var buf1 bytes.Buffer + writeNode(&buf1, fset, decl) + // wrap text with <pre> tag + var buf2 bytes.Buffer + buf2.WriteString("<pre>") + FormatText(&buf2, buf1.Bytes(), -1, true, id.Name, nil) + buf2.WriteString("</pre>") + return &Snippet{fset.Position(id.Pos()).Line, buf2.Bytes()} } diff --git a/src/cmd/godoc/utils.go b/src/cmd/godoc/utils.go index a032bd331..cc028cc4d 100644 --- a/src/cmd/godoc/utils.go +++ b/src/cmd/godoc/utils.go @@ -60,10 +60,10 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string { continue // ignore empty paths (don't assume ".") } // len(path) > 0: normalize path - if path[0] != '/' { - path = pathutil.Join(cwd, path) - } else { + if pathutil.IsAbs(path) { path = pathutil.Clean(path) + } else { + path = pathutil.Join(cwd, path) } // we have a non-empty absolute path if filter != nil && !filter(path) { diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index d7b70c461..41c12b88d 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -113,19 +113,20 @@ func processFile(f *os.File) os.Error { simplify(file) } - var res bytes.Buffer - _, err = (&printer.Config{printerMode, *tabWidth, nil}).Fprint(&res, fset, file) + var buf bytes.Buffer + _, err = (&printer.Config{printerMode, *tabWidth}).Fprint(&buf, fset, file) if err != nil { return err } + res := buf.Bytes() - if bytes.Compare(src, res.Bytes()) != 0 { + if !bytes.Equal(src, res) { // formatting has changed if *list { fmt.Fprintln(os.Stdout, f.Name()) } if *write { - err = ioutil.WriteFile(f.Name(), res.Bytes(), 0) + err = ioutil.WriteFile(f.Name(), res, 0) if err != nil { return err } @@ -133,7 +134,7 @@ func processFile(f *os.File) os.Error { } if !*list && !*write { - _, err = os.Stdout.Write(res.Bytes()) + _, err = os.Stdout.Write(res) } return err diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh index b5f4de1e2..2f60a3e7b 100755 --- a/src/cmd/gofmt/test.sh +++ b/src/cmd/gofmt/test.sh @@ -42,7 +42,7 @@ apply1() { bug163.go | bug166.go | bug169.go | bug217.go | bug222.go | \ bug226.go | bug228.go | bug248.go | bug274.go | bug280.go | \ bug282.go | bug287.go | bug298.go | bug299.go | bug300.go | \ - bug302.go | bug306.go ) return ;; + bug302.go | bug306.go | bug322.go ) return ;; esac # the following directories are skipped because they contain test # cases for syntax errors and thus won't parse in the first place: diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go index 93a648b2b..8d4d6c5d2 100644 --- a/src/cmd/goinstall/make.go +++ b/src/cmd/goinstall/make.go @@ -75,7 +75,7 @@ func makeMakefile(dir, pkg string) ([]byte, os.Error) { var buf bytes.Buffer md := makedata{pkg, goFiles, cgoFiles, oFiles} - if err := makefileTemplate.Execute(&md, &buf); err != nil { + if err := makefileTemplate.Execute(&buf, &md); err != nil { return nil, err } return buf.Bytes(), nil diff --git a/src/cmd/gopack/ar.c b/src/cmd/gopack/ar.c index a16e98cfe..702f104a6 100644 --- a/src/cmd/gopack/ar.c +++ b/src/cmd/gopack/ar.c @@ -131,6 +131,7 @@ Arfile *astart, *amiddle, *aend; /* Temp file control block pointers */ int allobj = 1; /* set when all members are object files of the same type */ int symdefsize; /* size of symdef file */ char *pkgstmt; /* string "package foo" */ +char *objhdr; /* string "go object darwin 386 release.2010-01-01 2345+" */ int dupfound; /* flag for duplicate symbol */ Hashchain *hash[NHASH]; /* hash table of text symbols */ @@ -246,6 +247,8 @@ main(int argc, char *argv[]) argc -= 3; argv += 3; (*comfun)(cp, argc, argv); /* do the command */ + if(errors && cflag) + remove(cp); cp = 0; while (argc--) { if (*argv) { @@ -590,10 +593,11 @@ void scanobj(Biobuf *b, Arfile *ap, long size) { int obj; - vlong offset; + vlong offset, offset1; Dir *d; static int lastobj = -1; uchar buf[4]; + char *p; if (!allobj) /* non-object file encountered */ return; @@ -628,14 +632,32 @@ scanobj(Biobuf *b, Arfile *ap, long size) Bseek(b, offset, 0); return; } - if (lastobj >= 0 && obj != lastobj) { + + offset1 = Boffset(b); + Bseek(b, offset, 0); + p = Brdstr(b, '\n', 1); + Bseek(b, offset1, 0); + if(p == nil || strncmp(p, "go object ", 10) != 0) { + fprint(2, "gopack: malformed object file %s\n", file); + errors++; + Bseek(b, offset, 0); + free(p); + return; + } + + if ((lastobj >= 0 && obj != lastobj) || (objhdr != nil && strcmp(p, objhdr) != 0)) { fprint(2, "gopack: inconsistent object file %s\n", file); errors++; allobj = 0; - Bseek(b, offset, 0); + free(p); return; } lastobj = obj; + if(objhdr == nil) + objhdr = p; + else + free(p); + if (!readar(b, obj, offset+size, 0)) { fprint(2, "gopack: invalid symbol reference in file %s\n", file); errors++; @@ -677,7 +699,7 @@ char* importblock; void getpkgdef(char **datap, int *lenp) { - char *tag; + char *tag, *hdr; if(pkgname == nil) { pkgname = "__emptyarchive__"; @@ -688,7 +710,11 @@ getpkgdef(char **datap, int *lenp) if(safe || Sflag) tag = "safe"; - *datap = smprint("import\n$$\npackage %s %s\n%s\n$$\n", pkgname, tag, importblock); + hdr = "empty archive"; + if(objhdr != nil) + hdr = objhdr; + + *datap = smprint("%s\nimport\n$$\npackage %s %s\n%s\n$$\n", hdr, pkgname, tag, importblock); *lenp = strlen(*datap); } diff --git a/src/cmd/gotest/gotest b/src/cmd/gotest/gotest index 87c680089..69eaae730 100755 --- a/src/cmd/gotest/gotest +++ b/src/cmd/gotest/gotest @@ -119,6 +119,12 @@ nmgrep() { done } +localname() { + # The package main has been renamed to __main__ when imported. + # Adjust its uses. + echo $1 | sed 's/^main\./__main__./' +} + importpath=$(gomake -s importpath) { # test functions are named TestFoo @@ -139,9 +145,20 @@ importpath=$(gomake -s importpath) echo # imports if echo "$tests" | egrep -v '_test\.' >/dev/null; then - if [ "$importpath" != "testing" ]; then + case "$importpath" in + testing) + ;; + main) + # Import path main is reserved, so import with + # explicit reference to ./_test/main instead. + # Also, the file we are writing defines a function named main, + # so rename this import to __main__ to avoid name conflict. + echo 'import __main__ "./_test/main"' + ;; + *) echo 'import "'$importpath'"' - fi + ;; + esac fi if $havex; then echo 'import "./_xtest_"' @@ -153,23 +170,20 @@ importpath=$(gomake -s importpath) echo 'var tests = []testing.InternalTest{' for i in $tests do - echo ' {"'$i'", '$i'},' + j=$(localname $i) + echo ' {"'$i'", '$j'},' done echo '}' # benchmark array - if [ "$benchmarks" = "" ] - then - # keep the empty array gofmt-safe. - # (not an issue for the test array, which is never empty.) - echo 'var benchmarks = []testing.InternalBenchmark{}' - else - echo 'var benchmarks = []testing.InternalBenchmark{' - for i in $benchmarks - do - echo ' {"'$i'", '$i'},' - done - echo '}' - fi + # The comment makes the multiline declaration + # gofmt-safe even when there are no benchmarks. + echo 'var benchmarks = []testing.InternalBenchmark{ //' + for i in $benchmarks + do + j=$(localname $i) + echo ' {"'$i'", '$j'},' + done + echo '}' # body echo echo 'func main() {' diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c index 8966b2a1f..2c6a6d084 100644 --- a/src/cmd/ld/go.c +++ b/src/cmd/ld/go.c @@ -148,8 +148,6 @@ ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence) } if(strcmp(pkg, "main") == 0 && strcmp(name, "main") != 0) fprint(2, "%s: %s: not package main (package %s)\n", argv0, filename, name); - else if(strcmp(pkg, "main") != 0 && strcmp(name, "main") == 0) - fprint(2, "%s: %s: importing %s, found package main", argv0, filename, pkg); loadpkgdata(filename, pkg, p0, p1 - p0); } diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index b1a62f25e..c144d4295 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -378,10 +378,9 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence) int n, c1, c2, c3, c4; uint32 magic; vlong import0, import1, eof; - char src[1024]; + char *t; eof = Boffset(f) + len; - src[0] = '\0'; pn = strdup(pn); @@ -415,22 +414,34 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence) line = Brdline(f, '\n'); if(line == nil) { if(Blinelen(f) > 0) { - diag("%s: malformed object file", pn); + diag("%s: not an object file", pn); return; } goto eof; } n = Blinelen(f) - 1; - if(n != strlen(thestring) || strncmp(line, thestring, n) != 0) { - if(line) - line[n] = '\0'; + line[n] = '\0'; + if(strncmp(line, "go object ", 10) != 0) { if(strlen(pn) > 3 && strcmp(pn+strlen(pn)-3, ".go") == 0) { print("%cl: input %s is not .%c file (use %cg to compile .go files)\n", thechar, pn, thechar, thechar); errorexit(); } - diag("file not %s [%s]\n", thestring, line); + if(strcmp(line, thestring) == 0) { + // old header format: just $GOOS + diag("%s: stale object file", pn); + return; + } + diag("%s: not an object file", pn); + return; + } + t = smprint("%s %s %s", getgoos(), thestring, getgoversion()); + if(strcmp(line+10, t) != 0) { + diag("%s: object is [%s] expected [%s]", pn, line+10, t); + free(t); return; } + free(t); + line[n] = '\n'; /* skip over exports and other info -- ends with \n!\n */ import0 = Boffset(f); diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 4ac5d37f9..16dfb0dc3 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -156,6 +156,7 @@ vlong adduint8(Sym*, uint8); vlong adduint16(Sym*, uint16); void asmsym(void); void asmelfsym64(void); +void asmplan9sym(void); void strnput(char*, int); void dodata(void); void address(void); diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c index 26e4def64..22777b6b5 100644 --- a/src/cmd/ld/symtab.c +++ b/src/cmd/ld/symtab.c @@ -136,6 +136,62 @@ asmelfsym32(void) genasmsym(putelfsym32); } +void +putplan9sym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go) +{ + int i; + + switch(t) { + case 'T': + case 't': + case 'L': + case 'l': + case 'D': + case 'd': + case 'B': + case 'b': + case 'a': + case 'p': + + case 'f': + case 'z': + case 'Z': + + case 'm': + lputb(addr); + cput(t+0x80); /* 0x80 is variable length */ + + if(t == 'z' || t == 'Z') { + cput(0); + for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { + cput(s[i]); + cput(s[i+1]); + } + cput(0); + cput(0); + i++; + } else { + /* skip the '<' in filenames */ + if(t=='f') + s++; + + for(i=0; s[i]; i++) + cput(s[i]); + cput(0); + } + + symsize += 4 + 1 + i + 1; + break; + default: + return; + }; +} + +void +asmplan9sym(void) +{ + genasmsym(putplan9sym); +} static Sym *symt; @@ -165,6 +221,52 @@ slputb(int32 v) } void +wputl(ushort w) +{ + cput(w); + cput(w>>8); +} + +void +wputb(ushort w) +{ + cput(w>>8); + cput(w); +} + +void +lputb(int32 l) +{ + cput(l>>24); + cput(l>>16); + cput(l>>8); + cput(l); +} + +void +lputl(int32 l) +{ + cput(l); + cput(l>>8); + cput(l>>16); + cput(l>>24); +} + +void +vputb(uint64 v) +{ + lputb(v>>32); + lputb(v); +} + +void +vputl(uint64 v) +{ + lputl(v); + lputl(v >> 32); +} + +void putsymb(Sym *s, char *name, int t, vlong v, vlong size, int ver, Sym *typ) { int i, f, l; |