summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-02-18 09:50:58 +0100
committerOndřej Surý <ondrej@sury.org>2011-02-18 09:50:58 +0100
commitc072558b90f1bbedc2022b0f30c8b1ac4712538e (patch)
tree67767591619e4bd8111fb05fac185cde94fb7378 /src/cmd
parent5859517b767c99749a45651c15d4bae5520ebae8 (diff)
downloadgolang-c072558b90f1bbedc2022b0f30c8b1ac4712538e.tar.gz
Imported Upstream version 2011.02.15upstream/2011.02.15
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5a/lex.c2
-rw-r--r--src/cmd/5c/swt.c2
-rw-r--r--src/cmd/5g/cgen64.c50
-rw-r--r--src/cmd/5g/list.c6
-rw-r--r--src/cmd/5g/peep.c216
-rw-r--r--src/cmd/5g/reg.c72
-rw-r--r--src/cmd/5l/asm.c44
-rw-r--r--src/cmd/5l/l.h1
-rw-r--r--src/cmd/5l/optab.c2
-rw-r--r--src/cmd/6a/lex.c2
-rw-r--r--src/cmd/6c/swt.c2
-rw-r--r--src/cmd/6l/asm.c46
-rw-r--r--src/cmd/6l/l.h1
-rw-r--r--src/cmd/8a/lex.c2
-rw-r--r--src/cmd/8c/swt.c2
-rw-r--r--src/cmd/8l/asm.c123
-rw-r--r--src/cmd/8l/l.h4
-rw-r--r--src/cmd/8l/obj.c1
-rw-r--r--src/cmd/8l/pass.c29
-rw-r--r--src/cmd/cgo/doc.go5
-rw-r--r--src/cmd/cgo/gcc.go59
-rw-r--r--src/cmd/cgo/util.go5
-rw-r--r--src/cmd/clean.bash7
-rw-r--r--src/cmd/gc/align.c3
-rw-r--r--src/cmd/gc/go.y8
-rw-r--r--src/cmd/gc/lex.c31
-rw-r--r--src/cmd/gc/mparith3.c27
-rw-r--r--src/cmd/gc/obj.c2
-rw-r--r--src/cmd/gc/select.c4
-rw-r--r--src/cmd/gc/subr.c3
-rw-r--r--src/cmd/gc/typecheck.c5
-rw-r--r--src/cmd/godoc/format.go21
-rw-r--r--src/cmd/godoc/godoc.go104
-rw-r--r--src/cmd/godoc/index.go7
-rw-r--r--src/cmd/godoc/main.go30
-rwxr-xr-xsrc/cmd/godoc/snippet.go11
-rw-r--r--src/cmd/godoc/utils.go6
-rw-r--r--src/cmd/gofmt/gofmt.go11
-rwxr-xr-xsrc/cmd/gofmt/test.sh2
-rw-r--r--src/cmd/goinstall/make.go2
-rw-r--r--src/cmd/gopack/ar.c36
-rwxr-xr-xsrc/cmd/gotest/gotest46
-rw-r--r--src/cmd/ld/go.c2
-rw-r--r--src/cmd/ld/lib.c25
-rw-r--r--src/cmd/ld/lib.h1
-rw-r--r--src/cmd/ld/symtab.c102
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;