summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5g/Makefile13
-rw-r--r--src/cmd/5g/cgen.c217
-rw-r--r--src/cmd/5g/ggen.c110
-rw-r--r--src/cmd/5l/asm.c6
-rw-r--r--src/cmd/6g/Makefile11
-rw-r--r--src/cmd/6g/ggen.c111
-rw-r--r--src/cmd/6l/asm.c1
-rw-r--r--src/cmd/6l/obj.c2
-rw-r--r--src/cmd/8g/Makefile11
-rw-r--r--src/cmd/8g/ggen.c111
-rw-r--r--src/cmd/8l/asm.c1
-rw-r--r--src/cmd/8l/obj.c2
-rw-r--r--src/cmd/cgo/doc.go14
-rw-r--r--src/cmd/cgo/gcc.go94
-rw-r--r--src/cmd/cgo/out.go2
-rw-r--r--src/cmd/gc/Makefile2
-rw-r--r--src/cmd/gc/align.c12
-rw-r--r--src/cmd/gc/closure.c44
-rw-r--r--src/cmd/gc/const.c4
-rw-r--r--src/cmd/gc/dcl.c28
-rw-r--r--src/cmd/gc/gen.c4
-rw-r--r--src/cmd/gc/go.h14
-rw-r--r--src/cmd/gc/go.y1
-rw-r--r--src/cmd/gc/init.c5
-rw-r--r--src/cmd/gc/lex.c16
-rw-r--r--src/cmd/gc/obj.c1
-rw-r--r--src/cmd/gc/pgen.c119
-rw-r--r--src/cmd/gc/sinit.c4
-rw-r--r--src/cmd/gc/subr.c3
-rw-r--r--src/cmd/gc/typecheck.c59
-rw-r--r--src/cmd/gc/walk.c18
-rw-r--r--src/cmd/godoc/spec.go5
-rw-r--r--src/cmd/gofix/main.go14
-rw-r--r--src/cmd/gofmt/gofmt.go18
-rw-r--r--src/cmd/goinstall/doc.go55
-rw-r--r--src/cmd/goinstall/download.go29
-rw-r--r--src/cmd/goinstall/main.go134
-rw-r--r--src/cmd/goinstall/make.go32
-rw-r--r--src/cmd/goinstall/path.go44
-rw-r--r--src/cmd/gotest/gotest.go4
-rw-r--r--src/cmd/hgpatch/main.go41
-rw-r--r--src/cmd/ld/dwarf.c49
-rw-r--r--src/cmd/ld/ldpe.c5
-rw-r--r--src/cmd/ld/lib.h1
-rw-r--r--src/cmd/ld/macho.c23
-rw-r--r--src/cmd/ld/macho.h2
-rw-r--r--src/cmd/ld/pe.c48
-rw-r--r--src/cmd/ld/pe.h2
48 files changed, 812 insertions, 734 deletions
diff --git a/src/cmd/5g/Makefile b/src/cmd/5g/Makefile
index 6873fbc68..b47014a4e 100644
--- a/src/cmd/5g/Makefile
+++ b/src/cmd/5g/Makefile
@@ -15,16 +15,17 @@ HFILES=\
OFILES=\
../5l/enam.$O\
- list.$O\
- galign.$O\
- gobj.$O\
- ggen.$O\
- gsubr.$O\
cgen.$O\
cgen64.$O\
cplx.$O\
- reg.$O\
+ galign.$O\
+ ggen.$O\
+ gobj.$O\
+ gsubr.$O\
+ list.$O\
peep.$O\
+ pgen.$O\
+ reg.$O\
LIB=\
../gc/gc.a\
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 4e5f7ebcd..76e2707fa 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -1190,7 +1190,8 @@ void
sgen(Node *n, Node *res, int32 w)
{
Node dst, src, tmp, nend;
- int32 c, q, odst, osrc;
+ int32 c, odst, osrc;
+ int dir, align, op;
Prog *p, *ploop;
if(debug['g']) {
@@ -1200,17 +1201,39 @@ sgen(Node *n, Node *res, int32 w)
}
if(w == 0)
return;
- if(n->ullman >= UINF && res->ullman >= UINF) {
- fatal("sgen UINF");
- }
-
if(w < 0)
fatal("sgen copy %d", w);
+ if(n->ullman >= UINF && res->ullman >= UINF)
+ fatal("sgen UINF");
+ if(n->type == T)
+ fatal("sgen: missing type");
+
+ // determine alignment.
+ // want to avoid unaligned access, so have to use
+ // smaller operations for less aligned types.
+ // for example moving [4]byte must use 4 MOVB not 1 MOVW.
+ align = n->type->align;
+ op = 0;
+ switch(align) {
+ default:
+ fatal("sgen: invalid alignment %d for %T", align, n->type);
+ case 1:
+ op = AMOVB;
+ break;
+ case 2:
+ op = AMOVH;
+ break;
+ case 4:
+ op = AMOVW;
+ break;
+ }
+ if(w%align)
+ fatal("sgen: unaligned size %d (align=%d) for %T", w, align, n->type);
+ c = w / align;
// offset on the stack
osrc = stkof(n);
odst = stkof(res);
-
if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
// osrc and odst both on stack, and at least one is in
// an unknown position. Could generate code to test
@@ -1221,12 +1244,15 @@ sgen(Node *n, Node *res, int32 w)
sgen(&tmp, res, w);
return;
}
-
- if(osrc % 4 != 0 || odst %4 != 0)
- fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst);
+ if(osrc%align != 0 || odst%align != 0)
+ fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
+ // if we are copying forward on the stack and
+ // the src and dst overlap, then reverse direction
+ dir = align;
+ if(osrc < odst && odst < osrc+w)
+ dir = -dir;
regalloc(&dst, types[tptr], res);
-
if(n->ullman >= res->ullman) {
agen(n, &dst); // temporarily use dst
regalloc(&src, types[tptr], N);
@@ -1240,141 +1266,64 @@ sgen(Node *n, Node *res, int32 w)
regalloc(&tmp, types[TUINT32], N);
- c = w % 4; // bytes
- q = w / 4; // quads
-
- // if we are copying forward on the stack and
- // the src and dst overlap, then reverse direction
- if(osrc < odst && odst < osrc+w) {
- if(c != 0)
- fatal("sgen: reverse character copy not implemented");
- if(q >= 4) {
- regalloc(&nend, types[TUINT32], N);
- // set up end marker to 4 bytes before source
- p = gins(AMOVW, &src, &nend);
- p->from.type = D_CONST;
- p->from.offset = -4;
-
- // move src and dest to the end of block
- p = gins(AMOVW, &src, &src);
- p->from.type = D_CONST;
- p->from.offset = (q-1)*4;
-
- p = gins(AMOVW, &dst, &dst);
- p->from.type = D_CONST;
- p->from.offset = (q-1)*4;
-
- p = gins(AMOVW, &src, &tmp);
- p->from.type = D_OREG;
- p->from.offset = -4;
- p->scond |= C_PBIT;
- ploop = p;
+ // set up end marker
+ memset(&nend, 0, sizeof nend);
+ if(c >= 4) {
+ regalloc(&nend, types[TUINT32], N);
- p = gins(AMOVW, &tmp, &dst);
- p->to.type = D_OREG;
- p->to.offset = -4;
- p->scond |= C_PBIT;
-
- p = gins(ACMP, &src, N);
- raddr(&nend, p);
+ p = gins(AMOVW, &src, &nend);
+ p->from.type = D_CONST;
+ if(dir < 0)
+ p->from.offset = dir;
+ else
+ p->from.offset = w;
+ }
- patch(gbranch(ABNE, T), ploop);
+ // move src and dest to the end of block if necessary
+ if(dir < 0) {
+ p = gins(AMOVW, &src, &src);
+ p->from.type = D_CONST;
+ p->from.offset = w + dir;
- regfree(&nend);
- } else {
- // move src and dest to the end of block
- p = gins(AMOVW, &src, &src);
- p->from.type = D_CONST;
- p->from.offset = (q-1)*4;
-
- p = gins(AMOVW, &dst, &dst);
- p->from.type = D_CONST;
- p->from.offset = (q-1)*4;
-
- while(q > 0) {
- p = gins(AMOVW, &src, &tmp);
- p->from.type = D_OREG;
- p->from.offset = -4;
- p->scond |= C_PBIT;
-
- p = gins(AMOVW, &tmp, &dst);
- p->to.type = D_OREG;
- p->to.offset = -4;
- p->scond |= C_PBIT;
-
- q--;
- }
- }
+ p = gins(AMOVW, &dst, &dst);
+ p->from.type = D_CONST;
+ p->from.offset = w + dir;
+ }
+
+ // move
+ if(c >= 4) {
+ p = gins(op, &src, &tmp);
+ p->from.type = D_OREG;
+ p->from.offset = dir;
+ p->scond |= C_PBIT;
+ ploop = p;
+
+ p = gins(op, &tmp, &dst);
+ p->to.type = D_OREG;
+ p->to.offset = dir;
+ p->scond |= C_PBIT;
+
+ p = gins(ACMP, &src, N);
+ raddr(&nend, p);
+
+ patch(gbranch(ABNE, T), ploop);
+ regfree(&nend);
} else {
- // normal direction
- if(q >= 4) {
- regalloc(&nend, types[TUINT32], N);
- p = gins(AMOVW, &src, &nend);
- p->from.type = D_CONST;
- p->from.offset = q*4;
-
- p = gins(AMOVW, &src, &tmp);
+ while(c-- > 0) {
+ p = gins(op, &src, &tmp);
p->from.type = D_OREG;
- p->from.offset = 4;
+ p->from.offset = dir;
p->scond |= C_PBIT;
ploop = p;
-
- p = gins(AMOVW, &tmp, &dst);
+
+ p = gins(op, &tmp, &dst);
p->to.type = D_OREG;
- p->to.offset = 4;
+ p->to.offset = dir;
p->scond |= C_PBIT;
-
- p = gins(ACMP, &src, N);
- raddr(&nend, p);
-
- patch(gbranch(ABNE, T), ploop);
-
- regfree(&nend);
- } else
- while(q > 0) {
- p = gins(AMOVW, &src, &tmp);
- p->from.type = D_OREG;
- p->from.offset = 4;
- p->scond |= C_PBIT;
-
- p = gins(AMOVW, &tmp, &dst);
- p->to.type = D_OREG;
- p->to.offset = 4;
- p->scond |= C_PBIT;
-
- q--;
- }
-
- if (c != 0) {
- // MOVW (src), tmp
- p = gins(AMOVW, &src, &tmp);
- p->from.type = D_OREG;
-
- // MOVW tmp<<((4-c)*8),src
- gshift(AMOVW, &tmp, SHIFT_LL, ((4-c)*8), &src);
-
- // MOVW src>>((4-c)*8),src
- gshift(AMOVW, &src, SHIFT_LR, ((4-c)*8), &src);
-
- // MOVW (dst), tmp
- p = gins(AMOVW, &dst, &tmp);
- p->from.type = D_OREG;
-
- // MOVW tmp>>(c*8),tmp
- gshift(AMOVW, &tmp, SHIFT_LR, (c*8), &tmp);
-
- // MOVW tmp<<(c*8),tmp
- gshift(AMOVW, &tmp, SHIFT_LL, c*8, &tmp);
-
- // ORR src, tmp
- gins(AORR, &src, &tmp);
-
- // MOVW tmp, (dst)
- p = gins(AMOVW, &tmp, &dst);
- p->to.type = D_OREG;
}
}
- regfree(&dst);
+
+ regfree(&dst);
regfree(&src);
regfree(&tmp);
}
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index 7197709d4..0bc1b38fc 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -7,107 +7,9 @@
#include "gg.h"
#include "opt.h"
-static Prog *pret;
-
void
-compile(Node *fn)
+defframe(Prog *ptxt)
{
- Plist *pl;
- Node nod1;
- Prog *ptxt;
- int32 lno;
- Type *t;
- Iter save;
-
- if(newproc == N) {
- newproc = sysfunc("newproc");
- deferproc = sysfunc("deferproc");
- deferreturn = sysfunc("deferreturn");
- panicindex = sysfunc("panicindex");
- panicslice = sysfunc("panicslice");
- throwreturn = sysfunc("throwreturn");
- }
-
- if(fn->nbody == nil)
- return;
-
- // set up domain for labels
- clearlabels();
-
- lno = setlineno(fn);
-
- curfn = fn;
- dowidth(curfn->type);
-
- if(curfn->type->outnamed) {
- // add clearing of the output parameters
- t = structfirst(&save, getoutarg(curfn->type));
- while(t != T) {
- if(t->nname != N)
- curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
- t = structnext(&save);
- }
- }
-
- hasdefer = 0;
- walk(curfn);
- if(nerrors != 0 || isblank(curfn->nname))
- goto ret;
-
- allocparams();
-
- continpc = P;
- breakpc = P;
-
- pl = newplist();
- pl->name = curfn->nname;
-
- setlineno(curfn);
-
- nodconst(&nod1, types[TINT32], 0);
- ptxt = gins(ATEXT, curfn->nname, &nod1);
- afunclit(&ptxt->from);
-
- ginit();
- genlist(curfn->enter);
-
- pret = nil;
- if(hasdefer || curfn->exit) {
- Prog *p1;
-
- p1 = gjmp(nil);
- pret = gjmp(nil);
- patch(p1, pc);
- }
-
- genlist(curfn->nbody);
- gclean();
- checklabels();
- if(nerrors != 0)
- goto ret;
-
- if(curfn->type->outtuple != 0)
- ginscall(throwreturn, 0);
-
- if(pret)
- patch(pret, pc);
- ginit();
- if(hasdefer)
- ginscall(deferreturn, 0);
- if(curfn->exit)
- genlist(curfn->exit);
- gclean();
- if(nerrors != 0)
- goto ret;
- if(curfn->endlineno)
- lineno = curfn->endlineno;
- pc->as = ARET; // overwrite AEND
- pc->lineno = lineno;
-
- if(!debug['N'] || debug['R'] || debug['P']) {
- regopt(ptxt);
- }
-
// fill in argument size
ptxt->to.type = D_CONST2;
ptxt->reg = 0; // flags
@@ -118,12 +20,6 @@ compile(Node *fn)
maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0;
-
- if(debug['f'])
- frame(0);
-
-ret:
- lineno = lno;
}
/*
@@ -197,7 +93,7 @@ ginscall(Node *f, int proc)
nodconst(&con, types[TINT32], 0);
p = gins(ACMP, &con, N);
p->reg = 0;
- patch(gbranch(ABNE, T), pret);
+ patch(gbranch(ABNE, T), retpc);
}
break;
}
@@ -401,7 +297,7 @@ cgen_ret(Node *n)
{
genlist(n->list); // copy out args
if(hasdefer || curfn->exit)
- gjmp(pret);
+ gjmp(retpc);
else
gins(ARET, N, N);
}
diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 9e9c2c1eb..81c08e353 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -1977,3 +1977,9 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
Bprint(&bso, "symsize = %ud\n", symsize);
Bflush(&bso);
}
+
+void
+setpersrc(Sym *s)
+{
+ USED(s);
+}
diff --git a/src/cmd/6g/Makefile b/src/cmd/6g/Makefile
index 023f5d111..64fa15399 100644
--- a/src/cmd/6g/Makefile
+++ b/src/cmd/6g/Makefile
@@ -14,16 +14,17 @@ HFILES=\
opt.h\
OFILES=\
- list.$O\
- gobj.$O\
- galign.$O\
- ggen.$O\
+ ../6l/enam.$O\
cgen.$O\
cplx.$O\
+ galign.$O\
+ ggen.$O\
+ gobj.$O\
gsubr.$O\
+ list.$O\
peep.$O\
+ pgen.$O\
reg.$O\
- ../6l/enam.$O\
LIB=\
../gc/gc.a\
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index ce66b43f0..5260335df 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -7,121 +7,18 @@
#include "gg.h"
#include "opt.h"
-static Prog *pret;
-
void
-compile(Node *fn)
+defframe(Prog *ptxt)
{
- Plist *pl;
- Node nod1;
- Prog *ptxt;
- int32 lno;
- Type *t;
- Iter save;
-
- if(newproc == N) {
- newproc = sysfunc("newproc");
- deferproc = sysfunc("deferproc");
- deferreturn = sysfunc("deferreturn");
- panicindex = sysfunc("panicindex");
- panicslice = sysfunc("panicslice");
- throwreturn = sysfunc("throwreturn");
- }
-
- if(fn->nbody == nil)
- return;
-
- // set up domain for labels
- clearlabels();
-
- lno = setlineno(fn);
-
- curfn = fn;
- dowidth(curfn->type);
-
- if(curfn->type->outnamed) {
- // add clearing of the output parameters
- t = structfirst(&save, getoutarg(curfn->type));
- while(t != T) {
- if(t->nname != N)
- curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
- t = structnext(&save);
- }
- }
-
- hasdefer = 0;
- walk(curfn);
- if(nerrors != 0 || isblank(curfn->nname))
- goto ret;
-
- allocparams();
-
- continpc = P;
- breakpc = P;
-
- pl = newplist();
- pl->name = curfn->nname;
-
- setlineno(curfn);
-
- nodconst(&nod1, types[TINT32], 0);
- ptxt = gins(ATEXT, curfn->nname, &nod1);
- afunclit(&ptxt->from);
-
- ginit();
- genlist(curfn->enter);
-
- pret = nil;
- if(hasdefer || curfn->exit) {
- Prog *p1;
-
- p1 = gjmp(nil);
- pret = gjmp(nil);
- patch(p1, pc);
- }
-
- genlist(curfn->nbody);
- gclean();
- checklabels();
- if(nerrors != 0)
- goto ret;
- if(curfn->endlineno)
- lineno = curfn->endlineno;
-
- if(curfn->type->outtuple != 0)
- ginscall(throwreturn, 0);
-
- if(pret)
- patch(pret, pc);
- ginit();
- if(hasdefer)
- ginscall(deferreturn, 0);
- if(curfn->exit)
- genlist(curfn->exit);
- gclean();
- if(nerrors != 0)
- goto ret;
- pc->as = ARET; // overwrite AEND
- pc->lineno = lineno;
-
- if(!debug['N'] || debug['R'] || debug['P']) {
- regopt(ptxt);
- }
-
// fill in argument size
ptxt->to.offset = rnd(curfn->type->argwid, widthptr);
// fill in final stack size
ptxt->to.offset <<= 32;
ptxt->to.offset |= rnd(stksize+maxarg, widthptr);
-
- if(debug['f'])
- frame(0);
-
-ret:
- lineno = lno;
}
+
/*
* generate:
* call f
@@ -163,7 +60,7 @@ ginscall(Node *f, int proc)
if(proc == 2) {
nodreg(&reg, types[TINT64], D_AX);
gins(ATESTQ, &reg, &reg);
- patch(gbranch(AJNE, T), pret);
+ patch(gbranch(AJNE, T), retpc);
}
break;
}
@@ -355,7 +252,7 @@ cgen_ret(Node *n)
{
genlist(n->list); // copy out args
if(hasdefer || curfn->exit)
- gjmp(pret);
+ gjmp(retpc);
else
gins(ARET, N, N);
}
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 6dffa20f2..320f4c9e9 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -828,6 +828,7 @@ asmb(void)
dwarfemitdebugsections();
}
break;
+ case Hdarwin:
case Hwindows:
seek(cout, symo, 0);
if(debug['v'])
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index d53814a74..e3191bb4d 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -177,7 +177,7 @@ main(int argc, char *argv[])
*/
tlsoffset = 0x8a0;
machoinit();
- HEADR = MACHORESERVE;
+ HEADR = INITIAL_MACHO_HEADR;
if(INITRND == -1)
INITRND = 4096;
if(INITTEXT == -1)
diff --git a/src/cmd/8g/Makefile b/src/cmd/8g/Makefile
index 09cf8d4e3..b459782a3 100644
--- a/src/cmd/8g/Makefile
+++ b/src/cmd/8g/Makefile
@@ -15,15 +15,16 @@ HFILES=\
OFILES=\
../8l/enam.$O\
- list.$O\
- galign.$O\
- gobj.$O\
- ggen.$O\
- gsubr.$O\
cgen.$O\
cgen64.$O\
cplx.$O\
+ galign.$O\
+ ggen.$O\
+ gobj.$O\
+ gsubr.$O\
+ list.$O\
peep.$O\
+ pgen.$O\
reg.$O\
LIB=\
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 223152536..25adb38c0 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -7,106 +7,9 @@
#include "gg.h"
#include "opt.h"
-static Prog *pret;
-
void
-compile(Node *fn)
+defframe(Prog *ptxt)
{
- Plist *pl;
- Node nod1;
- Prog *ptxt;
- int32 lno;
- Type *t;
- Iter save;
-
- if(newproc == N) {
- newproc = sysfunc("newproc");
- deferproc = sysfunc("deferproc");
- deferreturn = sysfunc("deferreturn");
- panicindex = sysfunc("panicindex");
- panicslice = sysfunc("panicslice");
- throwreturn = sysfunc("throwreturn");
- }
-
- if(fn->nbody == nil)
- return;
-
- // set up domain for labels
- clearlabels();
-
- lno = setlineno(fn);
-
- curfn = fn;
- dowidth(curfn->type);
-
- if(curfn->type->outnamed) {
- // add clearing of the output parameters
- t = structfirst(&save, getoutarg(curfn->type));
- while(t != T) {
- if(t->nname != N)
- curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
- t = structnext(&save);
- }
- }
-
- hasdefer = 0;
- walk(curfn);
- if(nerrors != 0 || isblank(curfn->nname))
- goto ret;
-
- allocparams();
-
- continpc = P;
- breakpc = P;
-
- pl = newplist();
- pl->name = curfn->nname;
-
- setlineno(curfn);
-
- nodconst(&nod1, types[TINT32], 0);
- ptxt = gins(ATEXT, curfn->nname, &nod1);
- afunclit(&ptxt->from);
-
- ginit();
- genlist(curfn->enter);
-
- pret = nil;
- if(hasdefer || curfn->exit) {
- Prog *p1;
-
- p1 = gjmp(nil);
- pret = gjmp(nil);
- patch(p1, pc);
- }
-
- genlist(curfn->nbody);
- gclean();
- checklabels();
- if(nerrors != 0)
- goto ret;
- if(curfn->endlineno)
- lineno = curfn->endlineno;
-
- if(curfn->type->outtuple != 0)
- ginscall(throwreturn, 0);
-
- if(pret)
- patch(pret, pc);
- ginit();
- if(hasdefer)
- ginscall(deferreturn, 0);
- if(curfn->exit)
- genlist(curfn->exit);
- gclean();
- if(nerrors != 0)
- goto ret;
- pc->as = ARET; // overwrite AEND
- pc->lineno = lineno;
-
- if(!debug['N'] || debug['R'] || debug['P']) {
- regopt(ptxt);
- }
// fill in argument size
ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
@@ -115,12 +18,6 @@ compile(Node *fn)
maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0;
-
- if(debug['f'])
- frame(0);
-
-ret:
- lineno = lno;
}
void
@@ -200,7 +97,7 @@ ginscall(Node *f, int proc)
if(proc == 2) {
nodreg(&reg, types[TINT64], D_AX);
gins(ATESTL, &reg, &reg);
- patch(gbranch(AJNE, T), pret);
+ patch(gbranch(AJNE, T), retpc);
}
break;
}
@@ -391,8 +288,8 @@ void
cgen_ret(Node *n)
{
genlist(n->list); // copy out args
- if(pret)
- gjmp(pret);
+ if(retpc)
+ gjmp(retpc);
else
gins(ARET, N, N);
}
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 7de7753a2..c426a88a4 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -781,6 +781,7 @@ asmb(void)
cflush();
}
break;
+ case Hdarwin:
case Hwindows:
seek(cout, symo, 0);
if(debug['v'])
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index f84a30f39..440dcb77f 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -218,7 +218,7 @@ main(int argc, char *argv[])
*/
tlsoffset = 0x468;
machoinit();
- HEADR = MACHORESERVE;
+ HEADR = INITIAL_MACHO_HEADR;
if(INITTEXT == -1)
INITTEXT = 4096+HEADR;
if(INITDAT == -1)
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index b3aa9aded..064725c1d 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -35,9 +35,17 @@ systems. For example:
// #include <png.h>
import "C"
-C identifiers or field names that are keywords in Go can be
-accessed by prefixing them with an underscore: if x points at
-a C struct with a field named "type", x._type accesses the field.
+Alternatively, CFLAGS and LDFLAGS may be obtained via the pkg-config
+tool using a '#cgo pkg-config:' directive followed by the package names.
+For example:
+
+ // #cgo pkg-config: png cairo
+ // #include <png.h>
+ import "C"
+
+Within the Go file, C identifiers or field names that are keywords in Go
+can be accessed by prefixing them with an underscore: if x points at a C
+struct with a field named "type", x._type accesses the field.
The standard C numeric types are available under the names
C.char, C.schar (signed char), C.uchar (unsigned char),
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index ac6561345..fa7602cf2 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -100,27 +100,81 @@ NextLine:
fatalf("%s: bad #cgo option: %s", srcfile, fields[0])
}
- if k != "CFLAGS" && k != "LDFLAGS" {
- fatalf("%s: unsupported #cgo option %s", srcfile, k)
- }
-
- v := strings.TrimSpace(fields[1])
- args, err := splitQuoted(v)
+ args, err := splitQuoted(fields[1])
if err != nil {
- fatalf("%s: bad #cgo option %s: %s", srcfile, k, err.String())
+ fatalf("%s: bad #cgo option %s: %s", srcfile, k, err)
}
- if oldv, ok := p.CgoFlags[k]; ok {
- p.CgoFlags[k] = oldv + " " + v
- } else {
- p.CgoFlags[k] = v
+ for _, arg := range args {
+ if !safeName(arg) {
+ fatalf("%s: #cgo option %s is unsafe: %s", srcfile, k, arg)
+ }
}
- if k == "CFLAGS" {
- p.GccOptions = append(p.GccOptions, args...)
+
+ switch k {
+
+ case "CFLAGS", "LDFLAGS":
+ p.addToFlag(k, args)
+
+ case "pkg-config":
+ cflags, ldflags, err := pkgConfig(args)
+ if err != nil {
+ fatalf("%s: bad #cgo option %s: %s", srcfile, k, err)
+ }
+ p.addToFlag("CFLAGS", cflags)
+ p.addToFlag("LDFLAGS", ldflags)
+
+ default:
+ fatalf("%s: unsupported #cgo option %s", srcfile, k)
+
}
}
f.Preamble = strings.Join(linesOut, "\n")
}
+// addToFlag appends args to flag. All flags are later written out onto the
+// _cgo_flags file for the build system to use.
+func (p *Package) addToFlag(flag string, args []string) {
+ if oldv, ok := p.CgoFlags[flag]; ok {
+ p.CgoFlags[flag] = oldv + " " + strings.Join(args, " ")
+ } else {
+ p.CgoFlags[flag] = strings.Join(args, " ")
+ }
+ if flag == "CFLAGS" {
+ // We'll also need these when preprocessing for dwarf information.
+ p.GccOptions = append(p.GccOptions, args...)
+ }
+}
+
+// pkgConfig runs pkg-config and extracts --libs and --cflags information
+// for packages.
+func pkgConfig(packages []string) (cflags, ldflags []string, err os.Error) {
+ for _, name := range packages {
+ if len(name) == 0 || name[0] == '-' {
+ return nil, nil, os.NewError(fmt.Sprintf("invalid name: %q", name))
+ }
+ }
+
+ args := append([]string{"pkg-config", "--cflags"}, packages...)
+ stdout, stderr, ok := run(nil, args)
+ if !ok {
+ os.Stderr.Write(stderr)
+ return nil, nil, os.NewError("pkg-config failed")
+ }
+ cflags, err = splitQuoted(string(stdout))
+ if err != nil {
+ return
+ }
+
+ args = append([]string{"pkg-config", "--libs"}, packages...)
+ stdout, stderr, ok = run(nil, args)
+ if !ok {
+ os.Stderr.Write(stderr)
+ return nil, nil, os.NewError("pkg-config failed")
+ }
+ ldflags, err = splitQuoted(string(stdout))
+ return
+}
+
// splitQuoted splits the string s around each instance of one or more consecutive
// white space characters while taking into account quotes and escaping, and
// returns an array of substrings of s or an empty list if s contains only white space.
@@ -182,6 +236,20 @@ func splitQuoted(s string) (r []string, err os.Error) {
return args, err
}
+var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+
+func safeName(s string) bool {
+ if s == "" {
+ return false
+ }
+ for i := 0; i < len(s); i++ {
+ if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+ return false
+ }
+ }
+ return true
+}
+
// Translate rewrites f.AST, the original Go input, to remove
// references to the imported package C, replacing them with
// references to the equivalent Go types, functions, and variables.
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 2ce4e9752..dbc7bcf69 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -142,7 +142,7 @@ func dynimport(obj string) {
if f, err := pe.Open(obj); err == nil {
sym, err := f.ImportedSymbols()
if err != nil {
- fatalf("cannot load imported symbols from PE file %s: v", obj, err)
+ fatalf("cannot load imported symbols from PE file %s: %v", obj, err)
}
for _, s := range sym {
ss := strings.Split(s, ":", -1)
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index dbfd86474..286618ec1 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -49,7 +49,7 @@ include ../../Make.clib
install: $(LIB)
y1.tab.c: y.tab.c # make yystate global, yytname mutable
- cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/' >y1.tab.c
+ cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/; s/char const \*yymsgp/char *yymsgp/' >y1.tab.c
yerr.h: bisonerrors go.errors y.tab.h # y.tab.h rule generates y.output too
awk -f bisonerrors y.output go.errors >yerr.h
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index a8454bf13..7fcac4833 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -234,9 +234,11 @@ dowidth(Type *t)
if(t->bound > cap)
yyerror("type %lT larger than address space", t);
w = t->bound * t->type->width;
- if(w == 0)
- w = 1;
t->align = t->type->align;
+ if(w == 0) {
+ w = 1;
+ t->align = 1;
+ }
}
else if(t->bound == -1) {
w = sizeof_Array;
@@ -253,10 +255,10 @@ dowidth(Type *t)
if(t->funarg)
fatal("dowidth fn struct %T", t);
w = widstruct(t, 0, 1);
- if(w == 0)
+ if(w == 0) {
w = 1;
- //if(t->align < widthptr)
- // warn("align %d: %T\n", t->align, t);
+ t->align = 1;
+ }
break;
case TFUNC:
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index eb7014366..906dadbc9 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -75,7 +75,7 @@ closurebody(NodeList *body)
}
void
-typecheckclosure(Node *func)
+typecheckclosure(Node *func, int top)
{
Node *oldfn;
NodeList *l;
@@ -106,6 +106,10 @@ typecheckclosure(Node *func)
v->op = 0;
continue;
}
+ // For a closure that is called in place, but not
+ // inside a go statement, avoid moving variables to the heap.
+ if ((top & (Ecall|Eproc)) == Ecall)
+ v->heapaddr->etype = 1;
typecheck(&v->heapaddr, Erv);
func->enter = list(func->enter, v->heapaddr);
v->heapaddr = N;
@@ -199,3 +203,41 @@ walkclosure(Node *func, NodeList **init)
walkexpr(&call, init);
return call;
}
+
+// Special case for closures that get called in place.
+// Optimize runtime.closure(X, __func__xxxx_, .... ) away
+// to __func__xxxx_(Y ....).
+// On entry, expect n->op == OCALL, n->left->op == OCLOSURE.
+void
+walkcallclosure(Node *n, NodeList **init)
+{
+ Node *z;
+ NodeList *ll, *cargs;
+
+ walkexpr(&n->left, init);
+ cargs = n->left // FUNC runtime.closure
+ ->list // arguments
+ ->next // skip first
+ ->next; // skip second
+
+ n->left = n->left // FUNC runtime.closure
+ ->list // arguments
+ ->next // skip first
+ ->n // AS (to indreg)
+ ->right; // argument == the generated function
+
+ // New arg list for n. First the closure-args, stolen from
+ // runtime.closure's 3rd and following,
+ ll = nil;
+ for (; cargs; cargs = cargs->next)
+ ll = list(ll, cargs->n->right); // cargs->n is the OAS(INDREG, arg)
+
+ // then an extra zero, to fill the dummy return pointer slot,
+ z = nod(OXXX, N, N);
+ nodconst(z, types[TUINTPTR], 0);
+ z->typecheck = 1;
+ ll = list(ll, z);
+
+ // and finally the original parameter list.
+ n->list = concat(ll, n->list);
+}
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index a36ec68c0..8fe9072b2 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -103,6 +103,8 @@ convlit1(Node **np, Type *t, int explicit)
case ORSH:
convlit1(&n->left, t, explicit && isideal(n->left->type));
t = n->left->type;
+ if(t != T && t->etype == TIDEAL && n->val.ctype != CTINT)
+ n->val = toint(n->val);
if(t != T && !isint[t->etype]) {
yyerror("invalid operation: %#N (shift of type %T)", n, t);
t = T;
@@ -514,6 +516,8 @@ evconst(Node *n)
n->right = nr;
if(nr->type && (issigned[nr->type->etype] || !isint[nr->type->etype]))
goto illegal;
+ nl->val = toint(nl->val);
+ nr->val = toint(nr->val);
break;
}
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 99af18d9f..78c676346 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -188,6 +188,7 @@ declare(Node *n, int ctxt)
else if(n->op == ONAME)
gen = ++vargen;
pushdcl(s);
+ n->curfn = curfn;
}
if(ctxt == PAUTO)
n->xoffset = BADWIDTH;
@@ -524,6 +525,30 @@ colas(NodeList *left, NodeList *right)
}
/*
+ * declare the arguments in an
+ * interface field declaration.
+ */
+void
+ifacedcl(Node *n)
+{
+ if(n->op != ODCLFIELD || n->right == N)
+ fatal("ifacedcl");
+
+ dclcontext = PAUTO;
+ markdcl();
+ funcdepth++;
+ n->outer = curfn;
+ curfn = n;
+ funcargs(n->right);
+
+ // funcbody is normally called after the parser has
+ // seen the body of a function but since an interface
+ // field declaration does not have a body, we must
+ // call it now to pop the current declaration context.
+ funcbody(n);
+}
+
+/*
* declare the function proper
* and declare the arguments.
* called in extern-declaration context
@@ -1226,9 +1251,6 @@ funccompile(Node *n, int isclosure)
if(curfn)
fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym);
- curfn = n;
- typechecklist(n->nbody, Etop);
- curfn = nil;
stksize = 0;
dclcontext = PAUTO;
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 8ad6c437d..0b6f5bbd8 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -59,6 +59,8 @@ allocparams(void)
fatal("bad width");
stksize += w;
stksize = rnd(stksize, n->type->align);
+ if(thechar == '5')
+ stksize = rnd(stksize, widthptr);
n->xoffset = -stksize;
}
lineno = lno;
@@ -698,6 +700,8 @@ tempname(Node *n, Type *t)
w = t->width;
stksize += w;
stksize = rnd(stksize, t->align);
+ if(thechar == '5')
+ stksize = rnd(stksize, widthptr);
n->xoffset = -stksize;
n->pun = anyregalloc();
}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 359881e11..f5c0443f8 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -254,6 +254,7 @@ struct Node
Node* ntype;
Node* defn;
Node* pack; // real package for import . names
+ Node* curfn; // function for local variables
// ONAME func param with PHEAP
Node* heapaddr; // temp holding heap address of param
@@ -517,15 +518,16 @@ enum
enum
{
- Etop = 1<<1, // evaluated at statement level
- Erv = 1<<2, // evaluated in value context
+ Etop = 1<<1, // evaluated at statement level
+ Erv = 1<<2, // evaluated in value context
Etype = 1<<3,
- Ecall = 1<<4, // call-only expressions are ok
+ Ecall = 1<<4, // call-only expressions are ok
Efnstruct = 1<<5, // multivalue function returns are ok
Eiota = 1<<6, // iota is ok
Easgn = 1<<7, // assigning to expression
Eindir = 1<<8, // indirecting through expression
Eaddr = 1<<9, // taking address of expression
+ Eproc = 1<<10, // inside a go statement
};
#define BITS 5
@@ -815,8 +817,9 @@ int bset(Bits a, uint n);
*/
Node* closurebody(NodeList *body);
void closurehdr(Node *ntype);
-void typecheckclosure(Node *func);
+void typecheckclosure(Node *func, int top);
Node* walkclosure(Node *func, NodeList **init);
+void walkcallclosure(Node *n, NodeList **init);
/*
* const.c
@@ -870,6 +873,7 @@ void funcbody(Node *n);
void funccompile(Node *n, int isclosure);
void funchdr(Node *n);
Type* functype(Node *this, NodeList *in, NodeList *out);
+void ifacedcl(Node *n);
int isifacemethod(Type *f);
void markdcl(void);
Node* methodname(Node *n, Type *t);
@@ -1209,6 +1213,7 @@ EXTERN Prog* continpc;
EXTERN Prog* breakpc;
EXTERN Prog* pc;
EXTERN Prog* firstpc;
+EXTERN Prog* retpc;
EXTERN Node* nodfp;
@@ -1222,6 +1227,7 @@ void cgen_callinter(Node *n, Node *res, int proc);
void cgen_ret(Node *n);
void clearfat(Node *n);
void compile(Node*);
+void defframe(Prog*);
int dgostringptr(Sym*, int off, char *str);
int dgostrlitptr(Sym*, int off, Strlit*);
int dstringptr(Sym *s, int off, char *str);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 7adfd002a..fdaab4fa4 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1380,6 +1380,7 @@ interfacedcl:
new_name indcl
{
$$ = nod(ODCLFIELD, $1, $2);
+ ifacedcl($$);
}
| packname
{
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
index af4eb0336..8818db08c 100644
--- a/src/cmd/gc/init.c
+++ b/src/cmd/gc/init.c
@@ -182,11 +182,14 @@ fninit(NodeList *n)
// (11)
a = nod(ORETURN, N, N);
r = list(r, a);
-
exportsym(fn->nname);
fn->nbody = r;
funcbody(fn);
+
+ curfn = fn;
typecheck(&fn, Etop);
+ typechecklist(r, Etop);
+ curfn = nil;
funccompile(fn, 0);
}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 04dd0d5b9..5e2f73fc5 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -235,13 +235,14 @@ main(int argc, char *argv[])
if(debug['f'])
frame(1);
- // Process top-level declarations in three phases.
+ // Process top-level declarations in four phases.
// Phase 1: const, type, and names and types of funcs.
// This will gather all the information about types
// and methods but doesn't depend on any of it.
// Phase 2: Variable assignments.
// To check interface assignments, depends on phase 1.
- // Phase 3: Function bodies.
+ // Phase 3: Type check function bodies.
+ // Phase 4: Compile function bodies.
defercheckwidth();
for(l=xtop; l; l=l->next)
if(l->n->op != ODCL && l->n->op != OAS)
@@ -251,17 +252,28 @@ main(int argc, char *argv[])
typecheck(&l->n, Etop);
resumetypecopy();
resumecheckwidth();
+
+ for(l=xtop; l; l=l->next)
+ if(l->n->op == ODCLFUNC) {
+ curfn = l->n;
+ typechecklist(l->n->nbody, Etop);
+ }
+ curfn = nil;
+
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC)
funccompile(l->n, 0);
+
if(nerrors == 0)
fninit(xtop);
+
while(closures) {
l = closures;
closures = nil;
for(; l; l=l->next)
funccompile(l->n, 1);
}
+
dclchecks();
if(nerrors)
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 9f4b7b318..f34fc76c8 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -284,6 +284,7 @@ stringsym(char *s, int len)
off = dsname(sym, off, s+n, m);
}
off = duint8(sym, off, 0); // terminating NUL for runtime
+ off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment
ggloblsym(sym, off, 1);
text();
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
new file mode 100644
index 000000000..9bd845dde
--- /dev/null
+++ b/src/cmd/gc/pgen.c
@@ -0,0 +1,119 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#undef EXTERN
+#define EXTERN
+#include "gg.h"
+#include "opt.h"
+
+void
+compile(Node *fn)
+{
+ Plist *pl;
+ Node nod1, *n;
+ Prog *ptxt;
+ int32 lno;
+ Type *t;
+ Iter save;
+
+ if(newproc == N) {
+ newproc = sysfunc("newproc");
+ deferproc = sysfunc("deferproc");
+ deferreturn = sysfunc("deferreturn");
+ panicindex = sysfunc("panicindex");
+ panicslice = sysfunc("panicslice");
+ throwreturn = sysfunc("throwreturn");
+ }
+
+ if(fn->nbody == nil)
+ return;
+
+ // set up domain for labels
+ clearlabels();
+
+ lno = setlineno(fn);
+
+ curfn = fn;
+ dowidth(curfn->type);
+
+ if(curfn->type->outnamed) {
+ // add clearing of the output parameters
+ t = structfirst(&save, getoutarg(curfn->type));
+ while(t != T) {
+ if(t->nname != N) {
+ n = nod(OAS, t->nname, N);
+ typecheck(&n, Etop);
+ curfn->nbody = concat(list1(n), curfn->nbody);
+ }
+ t = structnext(&save);
+ }
+ }
+
+ hasdefer = 0;
+ walk(curfn);
+ if(nerrors != 0 || isblank(curfn->nname))
+ goto ret;
+
+ allocparams();
+
+ continpc = P;
+ breakpc = P;
+
+ pl = newplist();
+ pl->name = curfn->nname;
+
+ setlineno(curfn);
+
+ nodconst(&nod1, types[TINT32], 0);
+ ptxt = gins(ATEXT, curfn->nname, &nod1);
+ afunclit(&ptxt->from);
+
+ ginit();
+ genlist(curfn->enter);
+
+ retpc = nil;
+ if(hasdefer || curfn->exit) {
+ Prog *p1;
+
+ p1 = gjmp(nil);
+ retpc = gjmp(nil);
+ patch(p1, pc);
+ }
+
+ genlist(curfn->nbody);
+ gclean();
+ checklabels();
+ if(nerrors != 0)
+ goto ret;
+ if(curfn->endlineno)
+ lineno = curfn->endlineno;
+
+ if(curfn->type->outtuple != 0)
+ ginscall(throwreturn, 0);
+
+ if(retpc)
+ patch(retpc, pc);
+ ginit();
+ if(hasdefer)
+ ginscall(deferreturn, 0);
+ if(curfn->exit)
+ genlist(curfn->exit);
+ gclean();
+ if(nerrors != 0)
+ goto ret;
+ pc->as = ARET; // overwrite AEND
+ pc->lineno = lineno;
+
+ if(!debug['N'] || debug['R'] || debug['P']) {
+ regopt(ptxt);
+ }
+
+ defframe(ptxt);
+
+ if(debug['f'])
+ frame(0);
+
+ret:
+ lineno = lno;
+}
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index be96a1477..eb7ef31ec 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -173,10 +173,10 @@ initfix(NodeList *l)
/*
* from here down is the walk analysis
- * of composit literals.
+ * of composite literals.
* most of the work is to generate
* data statements for the constant
- * part of the composit literal.
+ * part of the composite literal.
*/
static void structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 326a5ba74..4c0819cd8 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -3170,7 +3170,10 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
dumplist("genwrapper body", fn->nbody);
funcbody(fn);
+ curfn = fn;
typecheck(&fn, Etop);
+ typechecklist(fn->nbody, Etop);
+ curfn = nil;
funccompile(fn, 0);
}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 9aaf3e6ef..44d08352d 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -29,8 +29,8 @@ static void typecheckfunc(Node*);
static void checklvalue(Node*, char*);
static void checkassign(Node*);
static void checkassignlist(NodeList*);
-static void stringtoarraylit(Node**);
-static Node* resolve(Node*);
+static void stringtoarraylit(Node**);
+static Node* resolve(Node*);
static Type* getforwtype(Node*);
/*
@@ -780,7 +780,7 @@ reswitch:
n = r;
goto reswitch;
}
- typecheck(&n->left, Erv | Etype | Ecall);
+ typecheck(&n->left, Erv | Etype | Ecall |(top&Eproc));
l = n->left;
if(l->op == ONAME && l->etype != 0) {
if(n->isddd && l->etype != OAPPEND)
@@ -794,7 +794,7 @@ reswitch:
defaultlit(&n->left, T);
l = n->left;
if(l->op == OTYPE) {
- if(n->isddd)
+ if(n->isddd || l->type->bound == -100)
yyerror("invalid use of ... in type conversion", l);
// pick off before type-checking arguments
ok |= Erv;
@@ -822,7 +822,13 @@ reswitch:
case ODOTMETH:
n->op = OCALLMETH;
- typecheckaste(OCALL, n->left, 0, getthisx(t), list1(l->left), "method receiver");
+ // typecheckaste was used here but there wasn't enough
+ // information further down the call chain to know if we
+ // were testing a method receiver for unexported fields.
+ // It isn't necessary, so just do a sanity check.
+ tp = getthisx(t)->type->type;
+ if(l->left == N || !eqtype(l->left->type, tp))
+ fatal("method receiver");
break;
default:
@@ -1021,9 +1027,9 @@ reswitch:
// copy([]byte, string)
if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
- if (n->left->type->type ==types[TUINT8])
- goto ret;
- yyerror("arguments to copy have different element types: %lT and string", n->left->type);
+ if (n->left->type->type == types[TUINT8])
+ goto ret;
+ yyerror("arguments to copy have different element types: %lT and string", n->left->type);
goto error;
}
@@ -1211,7 +1217,7 @@ reswitch:
case OCLOSURE:
ok |= Erv;
- typecheckclosure(n);
+ typecheckclosure(n, top);
if(n->type == T)
goto error;
goto ret;
@@ -1240,11 +1246,15 @@ reswitch:
goto ret;
case ODEFER:
- case OPROC:
ok |= Etop;
typecheck(&n->left, Etop);
goto ret;
+ case OPROC:
+ ok |= Etop;
+ typecheck(&n->left, Etop|Eproc);
+ goto ret;
+
case OFOR:
ok |= Etop;
typechecklist(n->ninit, Etop);
@@ -2159,7 +2169,9 @@ addrescapes(Node *n)
if(n->noescape)
break;
switch(n->class) {
- case PAUTO:
+ case PPARAMREF:
+ addrescapes(n->defn);
+ break;
case PPARAM:
case PPARAMOUT:
// if func param, need separate temporary
@@ -2167,16 +2179,17 @@ addrescapes(Node *n)
// the function type has already been checked
// (we're in the function body)
// so the param already has a valid xoffset.
- if(n->class == PPARAM || n->class == PPARAMOUT) {
- // expression to refer to stack copy
- n->stackparam = nod(OPARAM, n, N);
- n->stackparam->type = n->type;
- n->stackparam->addable = 1;
- if(n->xoffset == BADWIDTH)
- fatal("addrescapes before param assignment");
- n->stackparam->xoffset = n->xoffset;
- n->xoffset = 0;
- }
+
+ // expression to refer to stack copy
+ n->stackparam = nod(OPARAM, n, N);
+ n->stackparam->type = n->type;
+ n->stackparam->addable = 1;
+ if(n->xoffset == BADWIDTH)
+ fatal("addrescapes before param assignment");
+ n->stackparam->xoffset = n->xoffset;
+ n->xoffset = 0;
+ // fallthrough
+ case PAUTO:
n->class |= PHEAP;
n->addable = 0;
@@ -2189,7 +2202,9 @@ addrescapes(Node *n)
snprint(buf, sizeof buf, "&%S", n->sym);
n->heapaddr->sym = lookup(buf);
n->heapaddr->class = PHEAP-1; // defer tempname to allocparams
- curfn->dcl = list(curfn->dcl, n->heapaddr);
+ n->heapaddr->ullman = 1;
+ n->curfn->dcl = list(n->curfn->dcl, n->heapaddr);
+
break;
}
break;
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index b3b400556..ccc65ff21 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -66,6 +66,7 @@ walk(Node *fn)
int lno;
curfn = fn;
+
if(debug['W']) {
snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
dumplist(s, curfn->nbody);
@@ -73,7 +74,7 @@ walk(Node *fn)
if(curfn->type->outtuple)
if(walkret(curfn->nbody))
yyerror("function ends without a return statement");
- typechecklist(curfn->nbody, Etop);
+
lno = lineno;
for(l=fn->dcl; l; l=l->next) {
n = l->n;
@@ -468,8 +469,10 @@ walkstmt(Node **np)
case OPANIC:
case OEMPTY:
case ORECOVER:
- if(n->typecheck == 0)
+ if(n->typecheck == 0) {
+ dump("missing typecheck:", n);
fatal("missing typecheck");
+ }
init = n->ninit;
n->ninit = nil;
walkexpr(&n, &init);
@@ -770,8 +773,15 @@ walkexpr(Node **np, NodeList **init)
t = n->left->type;
if(n->list && n->list->n->op == OAS)
goto ret;
- walkexpr(&n->left, init);
+
+ if(n->left->op == OCLOSURE) {
+ walkcallclosure(n, init);
+ t = n->left->type;
+ } else
+ walkexpr(&n->left, init);
+
walkexprlist(n->list, init);
+
ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
n->list = reorder1(ll);
if(isselect(n)) {
@@ -1525,7 +1535,7 @@ ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
static int
fncall(Node *l, Type *rt)
{
- if(l->ullman >= UINF)
+ if(l->ullman >= UINF || l->op == OINDEXMAP)
return 1;
if(eqtype(l->type, rt))
return 0;
diff --git a/src/cmd/godoc/spec.go b/src/cmd/godoc/spec.go
index f8b95e387..d863ca0d8 100644
--- a/src/cmd/godoc/spec.go
+++ b/src/cmd/godoc/spec.go
@@ -99,7 +99,8 @@ func (p *ebnfParser) parseTerm() bool {
case token.STRING:
p.next()
- if p.tok == token.ELLIPSIS {
+ const ellipsis = "…" // U+2026, the horizontal ellipsis character
+ if p.tok == token.ILLEGAL && p.lit == ellipsis {
p.next()
p.expect(token.STRING)
}
@@ -157,7 +158,7 @@ func (p *ebnfParser) parse(fset *token.FileSet, out io.Writer, src []byte) {
p.out = out
p.src = src
p.file = fset.AddFile("", fset.Base(), len(src))
- p.scanner.Init(p.file, src, p, 0)
+ p.scanner.Init(p.file, src, p, scanner.AllowIllegalChars)
p.next() // initializes pos, tok, lit
// process source
diff --git a/src/cmd/gofix/main.go b/src/cmd/gofix/main.go
index 4f7e923e3..ba2061a00 100644
--- a/src/cmd/gofix/main.go
+++ b/src/cmd/gofix/main.go
@@ -248,17 +248,5 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) {
f1.Write(b1)
f2.Write(b2)
- diffcmd, err := exec.LookPath("diff")
- if err != nil {
- return nil, err
- }
-
- c, err := exec.Run(diffcmd, []string{"diff", f1.Name(), f2.Name()}, nil, "",
- exec.DevNull, exec.Pipe, exec.MergeWithStdout)
- if err != nil {
- return nil, err
- }
- defer c.Close()
-
- return ioutil.ReadAll(c.Stdout)
+ return exec.Command("diff", f1.Name(), f2.Name()).CombinedOutput()
}
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 5dd801d90..16bcd3c4d 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -245,14 +245,14 @@ func gofmtMain() {
func diff(b1, b2 []byte) (data []byte, err os.Error) {
f1, err := ioutil.TempFile("", "gofmt")
if err != nil {
- return nil, err
+ return
}
defer os.Remove(f1.Name())
defer f1.Close()
f2, err := ioutil.TempFile("", "gofmt")
if err != nil {
- return nil, err
+ return
}
defer os.Remove(f2.Name())
defer f2.Close()
@@ -260,17 +260,5 @@ func diff(b1, b2 []byte) (data []byte, err os.Error) {
f1.Write(b1)
f2.Write(b2)
- diffcmd, err := exec.LookPath("diff")
- if err != nil {
- return nil, err
- }
-
- c, err := exec.Run(diffcmd, []string{"diff", "-u", f1.Name(), f2.Name()},
- nil, "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
- if err != nil {
- return nil, err
- }
- defer c.Close()
-
- return ioutil.ReadAll(c.Stdout)
+ return exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
}
diff --git a/src/cmd/goinstall/doc.go b/src/cmd/goinstall/doc.go
index 15845b574..13c37d0a2 100644
--- a/src/cmd/goinstall/doc.go
+++ b/src/cmd/goinstall/doc.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
/*
-
Goinstall is an experiment in automatic package installation.
It installs packages, possibly downloading them from the internet.
It maintains a list of public Go packages at http://godashboard.appspot.com/package.
@@ -100,5 +99,59 @@ Instead, it invokes "make install" after locating the package sources.
For local packages without a Makefile and all remote packages,
goinstall creates and uses a temporary Makefile constructed from
the import path and the list of Go files in the package.
+
+
+The GOPATH Environment Variable
+
+GOPATH may be set to a colon-separated list of paths inside which Go code,
+package objects, and executables may be found.
+
+Set a GOPATH to use goinstall to build and install your own code and
+external libraries outside of the Go tree (and to avoid writing Makefiles).
+
+The top-level directory structure of a GOPATH is prescribed:
+
+The 'src' directory is for source code. The directory naming inside 'src'
+determines the package import path or executable name.
+
+The 'pkg' directory is for package objects. Like the Go tree, package objects
+are stored inside a directory named after the target operating system and
+processor architecture ('pkg/$GOOS_$GOARCH').
+A package whose source is located at '$GOPATH/src/foo/bar' would be imported
+as 'foo/bar' and installed as '$GOPATH/pkg/$GOOS_$GOARCH/foo/bar.a'.
+
+The 'bin' directory is for executable files.
+Goinstall installs program binaries using the name of the source folder.
+A binary whose source is at 'src/foo/qux' would be built and installed to
+'$GOPATH/bin/qux'. (Note 'bin/qux', not 'bin/foo/qux' - this is such that
+you can put the bin directory in your PATH.)
+
+Here's an example directory layout:
+
+ GOPATH=/home/user/gocode
+
+ /home/user/gocode/
+ src/foo/
+ bar/ (go code in package bar)
+ qux/ (go code in package main)
+ bin/qux (executable file)
+ pkg/linux_amd64/foo/bar.a (object file)
+
+Run 'goinstall foo/bar' to build and install the package 'foo/bar'
+(and its dependencies).
+Goinstall will search each GOPATH (in order) for 'src/foo/bar'.
+If the directory cannot be found, goinstall will attempt to fetch the
+source from a remote repository and write it to the 'src' directory of the
+first GOPATH (or $GOROOT/src/pkg if GOPATH is not set).
+
+Goinstall recognizes relative and absolute paths (paths beginning with / or .).
+The following commands would build our example packages:
+
+ goinstall /home/user/gocode/src/foo/bar # build and install foo/bar
+ cd /home/user/gocode/src/foo
+ goinstall ./bar # build and install foo/bar (again)
+ cd qux
+ goinstall . # build and install foo/qux
+
*/
package documentation
diff --git a/src/cmd/goinstall/download.go b/src/cmd/goinstall/download.go
index 7dad596ab..2edf85efd 100644
--- a/src/cmd/goinstall/download.go
+++ b/src/cmd/goinstall/download.go
@@ -31,23 +31,36 @@ func maybeReportToDashboard(path string) {
}
}
-var googlecode = regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`)
-var github = regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
-var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
-var launchpad = regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`)
+var vcsPatterns = map[string]*regexp.Regexp{
+ "googlecode": regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`),
+ "github": regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`),
+ "bitbucket": regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`),
+ "launchpad": regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`),
+}
+
+// isRemote returns true if the provided package path
+// matches one of the supported remote repositories.
+func isRemote(pkg string) bool {
+ for _, r := range vcsPatterns {
+ if r.MatchString(pkg) {
+ return true
+ }
+ }
+ return false
+}
// download checks out or updates pkg from the remote server.
func download(pkg, srcDir string) os.Error {
if strings.Contains(pkg, "..") {
return os.ErrorString("invalid path (contains ..)")
}
- if m := bitbucket.FindStringSubmatch(pkg); m != nil {
+ if m := vcsPatterns["bitbucket"].FindStringSubmatch(pkg); m != nil {
if err := vcsCheckout(&hg, srcDir, m[1], "http://"+m[1], m[1]); err != nil {
return err
}
return nil
}
- if m := googlecode.FindStringSubmatch(pkg); m != nil {
+ if m := vcsPatterns["googlecode"].FindStringSubmatch(pkg); m != nil {
var v *vcs
switch m[2] {
case "hg":
@@ -63,7 +76,7 @@ func download(pkg, srcDir string) os.Error {
}
return nil
}
- if m := github.FindStringSubmatch(pkg); m != nil {
+ if m := vcsPatterns["github"].FindStringSubmatch(pkg); m != nil {
if strings.HasSuffix(m[1], ".git") {
return os.ErrorString("repository " + pkg + " should not have .git suffix")
}
@@ -72,7 +85,7 @@ func download(pkg, srcDir string) os.Error {
}
return nil
}
- if m := launchpad.FindStringSubmatch(pkg); m != nil {
+ if m := vcsPatterns["launchpad"].FindStringSubmatch(pkg); m != nil {
// Either lp.net/<project>[/<series>[/<path>]]
// or lp.net/~<user or team>/<project>/<branch>[/<path>]
if err := vcsCheckout(&bzr, srcDir, m[1], "https://"+m[1], m[1]); err != nil {
diff --git a/src/cmd/goinstall/main.go b/src/cmd/goinstall/main.go
index 6cd92907a..721e719d2 100644
--- a/src/cmd/goinstall/main.go
+++ b/src/cmd/goinstall/main.go
@@ -12,7 +12,6 @@ import (
"flag"
"fmt"
"go/token"
- "io"
"io/ioutil"
"os"
"path/filepath"
@@ -32,9 +31,8 @@ var (
argv0 = os.Args[0]
errors = false
parents = make(map[string]string)
- root = runtime.GOROOT()
visit = make(map[string]status)
- logfile = filepath.Join(root, "goinstall.log")
+ logfile = filepath.Join(runtime.GOROOT(), "goinstall.log")
installedPkgs = make(map[string]bool)
allpkg = flag.Bool("a", false, "install all previously installed packages")
@@ -52,14 +50,30 @@ const (
done
)
+func logf(format string, args ...interface{}) {
+ format = "%s: " + format
+ args = append([]interface{}{argv0}, args...)
+ fmt.Fprintf(os.Stderr, format, args...)
+}
+
+func vlogf(format string, args ...interface{}) {
+ if *verbose {
+ logf(format, args...)
+ }
+}
+
+func errorf(format string, args ...interface{}) {
+ errors = true
+ logf(format, args...)
+}
+
func main() {
flag.Usage = usage
flag.Parse()
- if root == "" {
+ if runtime.GOROOT() == "" {
fmt.Fprintf(os.Stderr, "%s: no $GOROOT\n", argv0)
os.Exit(1)
}
- root += filepath.FromSlash("/src/pkg/")
// special case - "unsafe" is already installed
visit["unsafe"] = done
@@ -88,6 +102,11 @@ func main() {
usage()
}
for _, path := range args {
+ if strings.HasPrefix(path, "http://") {
+ errorf("'http://' used in remote path, try '%s'\n", path[7:])
+ continue
+ }
+
install(path, "")
}
if errors {
@@ -143,49 +162,44 @@ func install(pkg, parent string) {
}
visit[pkg] = visiting
parents[pkg] = parent
- if *verbose {
- fmt.Println(pkg)
- }
+
+ vlogf("%s: visit\n", pkg)
// Check whether package is local or remote.
// If remote, download or update it.
- var dir string
- proot := gopath[0] // default to GOROOT
- local := false
- if strings.HasPrefix(pkg, "http://") {
- fmt.Fprintf(os.Stderr, "%s: %s: 'http://' used in remote path, try '%s'\n", argv0, pkg, pkg[7:])
- errors = true
+ proot, pkg, err := findPackageRoot(pkg)
+ // Don't build the standard library.
+ if err == nil && proot.goroot && isStandardPath(pkg) {
+ if parent == "" {
+ errorf("%s: can not goinstall the standard library\n", pkg)
+ } else {
+ vlogf("%s: skipping standard library\n", pkg)
+ }
+ visit[pkg] = done
return
}
- if isLocalPath(pkg) {
- dir = pkg
- local = true
- } else if isStandardPath(pkg) {
- dir = filepath.Join(root, filepath.FromSlash(pkg))
- local = true
- } else {
- proot = findPkgroot(pkg)
- err := download(pkg, proot.srcDir())
- dir = filepath.Join(proot.srcDir(), pkg)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
- errors = true
- visit[pkg] = done
- return
- }
+ // Download remote packages if not found or forced with -u flag.
+ remote := isRemote(pkg)
+ if remote && (err == ErrPackageNotFound || (err == nil && *update)) {
+ vlogf("%s: download\n", pkg)
+ err = download(pkg, proot.srcDir())
}
+ if err != nil {
+ errorf("%s: %v\n", pkg, err)
+ visit[pkg] = done
+ return
+ }
+ dir := filepath.Join(proot.srcDir(), pkg)
// Install prerequisites.
dirInfo, err := scanDir(dir, parent == "")
if err != nil {
- fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
- errors = true
+ errorf("%s: %v\n", pkg, err)
visit[pkg] = done
return
}
if len(dirInfo.goFiles) == 0 {
- fmt.Fprintf(os.Stderr, "%s: %s: package has no files\n", argv0, pkg)
- errors = true
+ errorf("%s: package has no files\n", pkg)
visit[pkg] = done
return
}
@@ -198,22 +212,16 @@ func install(pkg, parent string) {
// Install this package.
if !errors {
isCmd := dirInfo.pkgName == "main"
- if err := domake(dir, pkg, proot, local, isCmd); err != nil {
- fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err)
- errors = true
- } else if !local && *logPkgs {
- // mark this package as installed in $GOROOT/goinstall.log
+ if err := domake(dir, pkg, proot, isCmd); err != nil {
+ errorf("installing: %v\n", err)
+ } else if remote && *logPkgs {
+ // mark package as installed in $GOROOT/goinstall.log
logPackage(pkg)
}
}
visit[pkg] = done
}
-// Is this a local path? /foo ./foo ../foo . ..
-func isLocalPath(s string) bool {
- const sep = string(filepath.Separator)
- return strings.HasPrefix(s, sep) || strings.HasPrefix(s, "."+sep) || strings.HasPrefix(s, ".."+sep) || s == "." || s == ".."
-}
// Is this a standard package path? strings container/vector etc.
// Assume that if the first element has a dot, it's a domain name
@@ -237,40 +245,22 @@ func quietRun(dir string, stdin []byte, cmd ...string) os.Error {
}
// genRun implements run and quietRun.
-func genRun(dir string, stdin []byte, cmd []string, quiet bool) os.Error {
- bin, err := exec.LookPath(cmd[0])
+func genRun(dir string, stdin []byte, arg []string, quiet bool) os.Error {
+ cmd := exec.Command(arg[0], arg[1:]...)
+ cmd.Stdin = bytes.NewBuffer(stdin)
+ cmd.Dir = dir
+ vlogf("%s: %s %s\n", dir, cmd.Path, strings.Join(arg[1:], " "))
+ out, err := cmd.CombinedOutput()
if err != nil {
- return err
- }
- p, err := exec.Run(bin, cmd, os.Environ(), dir, exec.Pipe, exec.Pipe, exec.MergeWithStdout)
- if *verbose {
- fmt.Fprintf(os.Stderr, "%s: %s; %s %s\n", argv0, dir, bin, strings.Join(cmd[1:], " "))
- }
- if err != nil {
- return err
- }
- go func() {
- p.Stdin.Write(stdin)
- p.Stdin.Close()
- }()
- var buf bytes.Buffer
- io.Copy(&buf, p.Stdout)
- io.Copy(&buf, p.Stdout)
- w, err := p.Wait(0)
- p.Close()
- if err != nil {
- return err
- }
- if !w.Exited() || w.ExitStatus() != 0 {
if !quiet || *verbose {
if dir != "" {
dir = "cd " + dir + "; "
}
- fmt.Fprintf(os.Stderr, "%s: === %s%s\n", argv0, dir, strings.Join(cmd, " "))
- os.Stderr.Write(buf.Bytes())
- fmt.Fprintf(os.Stderr, "--- %s\n", w)
+ fmt.Fprintf(os.Stderr, "%s: === %s%s\n", cmd.Path, dir, strings.Join(cmd.Args, " "))
+ os.Stderr.Write(out)
+ fmt.Fprintf(os.Stderr, "--- %s\n", err)
}
- return os.ErrorString("running " + cmd[0] + ": " + w.String())
+ return os.ErrorString("running " + arg[0] + ": " + err.String())
}
return nil
}
diff --git a/src/cmd/goinstall/make.go b/src/cmd/goinstall/make.go
index b2ca82b46..0c44481d7 100644
--- a/src/cmd/goinstall/make.go
+++ b/src/cmd/goinstall/make.go
@@ -14,26 +14,14 @@ import (
)
// domake builds the package in dir.
-// If local is false, the package was copied from an external system.
-// For non-local packages or packages without Makefiles,
// domake generates a standard Makefile and passes it
// to make on standard input.
-func domake(dir, pkg string, root *pkgroot, local, isCmd bool) (err os.Error) {
- needMakefile := true
- if local {
- _, err := os.Stat(dir + "/Makefile")
- if err == nil {
- needMakefile = false
- }
- }
- cmd := []string{"gomake"}
- var makefile []byte
- if needMakefile {
- if makefile, err = makeMakefile(dir, pkg, root, isCmd); err != nil {
- return err
- }
- cmd = append(cmd, "-f-")
+func domake(dir, pkg string, root *pkgroot, isCmd bool) (err os.Error) {
+ makefile, err := makeMakefile(dir, pkg, root, isCmd)
+ if err != nil {
+ return err
}
+ cmd := []string{"bash", "gomake", "-f-"}
if *clean {
cmd = append(cmd, "clean")
}
@@ -51,16 +39,8 @@ func makeMakefile(dir, pkg string, root *pkgroot, isCmd bool) ([]byte, os.Error)
targ := pkg
targDir := root.pkgDir()
if isCmd {
- // use the last part of the package name only
+ // use the last part of the package name for targ
_, targ = filepath.Split(pkg)
- // if building the working dir use the directory name
- if targ == "." {
- d, err := filepath.Abs(dir)
- if err != nil {
- return nil, os.NewError("finding path: " + err.String())
- }
- _, targ = filepath.Split(d)
- }
targDir = root.binDir()
}
dirInfo, err := scanDir(dir, isCmd)
diff --git a/src/cmd/goinstall/path.go b/src/cmd/goinstall/path.go
index 1153e0471..b8c392931 100644
--- a/src/cmd/goinstall/path.go
+++ b/src/cmd/goinstall/path.go
@@ -5,10 +5,12 @@
package main
import (
+ "fmt"
"log"
"os"
"path/filepath"
"runtime"
+ "strings"
)
var (
@@ -19,6 +21,7 @@ var (
// set up gopath: parse and validate GOROOT and GOPATH variables
func init() {
+ root := runtime.GOROOT()
p, err := newPkgroot(root)
if err != nil {
log.Fatalf("Invalid GOROOT %q: %v", root, err)
@@ -105,13 +108,42 @@ func (r *pkgroot) hasPkg(name string) bool {
// TODO(adg): check object version is consistent
}
-// findPkgroot searches each of the gopath roots
-// for the source code for the given import path.
-func findPkgroot(importPath string) *pkgroot {
+
+var ErrPackageNotFound = os.NewError("package could not be found locally")
+
+// findPackageRoot takes an import or filesystem path and returns the
+// root where the package source should be and the package import path.
+func findPackageRoot(path string) (root *pkgroot, pkg string, err os.Error) {
+ if isLocalPath(path) {
+ if path, err = filepath.Abs(path); err != nil {
+ return
+ }
+ for _, r := range gopath {
+ rpath := r.srcDir() + string(filepath.Separator)
+ if !strings.HasPrefix(path, rpath) {
+ continue
+ }
+ root = r
+ pkg = path[len(rpath):]
+ return
+ }
+ err = fmt.Errorf("path %q not inside a GOPATH", path)
+ return
+ }
+ root = defaultRoot
+ pkg = path
for _, r := range gopath {
- if r.hasSrcDir(importPath) {
- return r
+ if r.hasSrcDir(path) {
+ root = r
+ return
}
}
- return defaultRoot
+ err = ErrPackageNotFound
+ return
+}
+
+// Is this a local path? /foo ./foo ../foo . ..
+func isLocalPath(s string) bool {
+ const sep = string(filepath.Separator)
+ return strings.HasPrefix(s, sep) || strings.HasPrefix(s, "."+sep) || strings.HasPrefix(s, ".."+sep) || s == "." || s == ".."
}
diff --git a/src/cmd/gotest/gotest.go b/src/cmd/gotest/gotest.go
index 8c81baf97..4cb3da23c 100644
--- a/src/cmd/gotest/gotest.go
+++ b/src/cmd/gotest/gotest.go
@@ -285,8 +285,8 @@ func doRun(argv []string, returnStdout bool) string {
}
cmd += `"` + v + `"`
}
- command = "sh"
- argv = []string{"sh", "-c", cmd}
+ command = "bash"
+ argv = []string{"bash", "-c", cmd}
}
var err os.Error
argv[0], err = exec.LookPath(argv[0])
diff --git a/src/cmd/hgpatch/main.go b/src/cmd/hgpatch/main.go
index 2dcb5234c..8ee3422e2 100644
--- a/src/cmd/hgpatch/main.go
+++ b/src/cmd/hgpatch/main.go
@@ -10,7 +10,6 @@ import (
"exec"
"flag"
"fmt"
- "io"
"io/ioutil"
"os"
"patch"
@@ -333,6 +332,7 @@ func run(argv []string, input []byte) (out string, err os.Error) {
err = os.EINVAL
goto Error
}
+
prog, ok := lookPathCache[argv[0]]
if !ok {
prog, err = exec.LookPath(argv[0])
@@ -341,40 +341,15 @@ func run(argv []string, input []byte) (out string, err os.Error) {
}
lookPathCache[argv[0]] = prog
}
- // fmt.Fprintf(os.Stderr, "%v\n", argv);
- var cmd *exec.Cmd
- if len(input) == 0 {
- cmd, err = exec.Run(prog, argv, os.Environ(), "", exec.DevNull, exec.Pipe, exec.MergeWithStdout)
- if err != nil {
- goto Error
- }
- } else {
- cmd, err = exec.Run(prog, argv, os.Environ(), "", exec.Pipe, exec.Pipe, exec.MergeWithStdout)
- if err != nil {
- goto Error
- }
- go func() {
- cmd.Stdin.Write(input)
- cmd.Stdin.Close()
- }()
- }
- defer cmd.Close()
- var buf bytes.Buffer
- _, err = io.Copy(&buf, cmd.Stdout)
- out = buf.String()
- if err != nil {
- cmd.Wait(0)
- goto Error
- }
- w, err := cmd.Wait(0)
- if err != nil {
- goto Error
+
+ cmd := exec.Command(prog, argv[1:]...)
+ if len(input) > 0 {
+ cmd.Stdin = bytes.NewBuffer(input)
}
- if !w.Exited() || w.ExitStatus() != 0 {
- err = w
- goto Error
+ bs, err := cmd.CombinedOutput()
+ if err == nil {
+ return string(bs), nil
}
- return
Error:
err = &runError{dup(argv), err}
diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c
index ed11f5e5a..de600f555 100644
--- a/src/cmd/ld/dwarf.c
+++ b/src/cmd/ld/dwarf.c
@@ -529,8 +529,10 @@ find_or_diag(DWDie *die, char* name)
{
DWDie *r;
r = find(die, name);
- if (r == nil)
+ if (r == nil) {
diag("dwarf find: %s has no %s", getattr(die, DW_AT_name)->data, name);
+ errorexit();
+ }
return r;
}
@@ -613,7 +615,7 @@ putattr(int form, int cls, vlong value, char *data)
case DW_FORM_ref_addr: // reference to a DIE in the .info section
if (data == nil) {
- diag("null dwarf reference");
+ diag("dwarf: null reference");
LPUT(0); // invalid dwarf, gdb will complain.
} else {
if (((DWDie*)data)->offs == 0)
@@ -631,7 +633,7 @@ putattr(int form, int cls, vlong value, char *data)
case DW_FORM_strp: // string
case DW_FORM_indirect: // (see Section 7.5.3)
default:
- diag("Unsupported atribute form %d / class %d", form, cls);
+ diag("dwarf: unsupported attribute form %d / class %d", form, cls);
errorexit();
}
}
@@ -823,7 +825,7 @@ decode_inuxi(uchar* p, int sz)
inuxi = inuxi8;
break;
default:
- diag("decode inuxi %d", sz);
+ diag("dwarf: decode inuxi %d", sz);
errorexit();
}
for (i = 0; i < sz; i++)
@@ -1013,7 +1015,7 @@ defgotype(Sym *gotype)
return find_or_diag(&dwtypes, "<unspecified>");
if (strncmp("type.", gotype->name, 5) != 0) {
- diag("Type name doesn't start with \".type\": %s", gotype->name);
+ diag("dwarf: type name doesn't start with \".type\": %s", gotype->name);
return find_or_diag(&dwtypes, "<unspecified>");
}
name = gotype->name + 5; // could also decode from Type.string
@@ -1164,7 +1166,7 @@ defgotype(Sym *gotype)
break;
default:
- diag("definition of unknown kind %d: %s", kind, gotype->name);
+ diag("dwarf: definition of unknown kind %d: %s", kind, gotype->name);
die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name);
newrefattr(die, DW_AT_type, find_or_diag(&dwtypes, "<unspecified>"));
}
@@ -1513,12 +1515,12 @@ decodez(char *s)
ss = s + 1; // first is 0
while((o = ((uint8)ss[0] << 8) | (uint8)ss[1]) != 0) {
if (o < 0 || o >= ftabsize) {
- diag("corrupt z entry");
+ diag("dwarf: corrupt z entry");
return 0;
}
f = ftab[o];
if (f == nil) {
- diag("corrupt z entry");
+ diag("dwarf: corrupt z entry");
return 0;
}
len += strlen(f) + 1; // for the '/'
@@ -1630,11 +1632,11 @@ checknesting(void)
int i;
if (includetop < 0) {
- diag("corrupt z stack");
+ diag("dwarf: corrupt z stack");
errorexit();
}
if (includetop >= nelem(includestack)) {
- diag("nesting too deep");
+ diag("dwarf: nesting too deep");
for (i = 0; i < nelem(includestack); i++)
diag("\t%s", histfile[includestack[i].file]);
errorexit();
@@ -1660,7 +1662,7 @@ inithist(Auto *a)
// We have a new history. They are guaranteed to come completely
// at the beginning of the compilation unit.
if (a->aoffset != 1) {
- diag("stray 'z' with offset %d", a->aoffset);
+ diag("dwarf: stray 'z' with offset %d", a->aoffset);
return 0;
}
@@ -1915,7 +1917,7 @@ writelines(void)
continue;
if (unitstart < 0) {
- diag("reachable code before seeing any history: %P", s->text);
+ diag("dwarf: reachable code before seeing any history: %P", s->text);
continue;
}
@@ -1932,7 +1934,7 @@ writelines(void)
for(q = s->text; q != P; q = q->link) {
lh = searchhist(q->line);
if (lh == nil) {
- diag("corrupt history or bad absolute line: %P", q);
+ diag("dwarf: corrupt history or bad absolute line: %P", q);
continue;
}
@@ -2066,7 +2068,7 @@ writeframes(void)
// 4 is to exclude the length field.
pad = CIERESERVE + frameo + 4 - cpos();
if (pad < 0) {
- diag("CIERESERVE too small by %lld bytes.", -pad);
+ diag("dwarf: CIERESERVE too small by %lld bytes.", -pad);
errorexit();
}
strnput("", pad);
@@ -2296,6 +2298,9 @@ dwarfemitdebugsections(void)
vlong infoe;
DWDie* die;
+ if(debug['w']) // disable dwarf
+ return;
+
// For diagnostic messages.
newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, strlen("dwtypes"), "dwtypes");
@@ -2348,11 +2353,11 @@ dwarfemitdebugsections(void)
seek(cout, infoo, 0);
writeinfo();
if (fwdcount > 0) {
- diag("unresolved references after first dwarf info pass");
+ diag("dwarf: unresolved references after first dwarf info pass");
errorexit();
}
if (infoe != cpos()) {
- diag("inconsistent second dwarf info pass");
+ diag("dwarf: inconsistent second dwarf info pass");
errorexit();
}
}
@@ -2401,6 +2406,9 @@ vlong elfstrdbg[NElfStrDbg];
void
dwarfaddshstrings(Sym *shstrtab)
{
+ if(debug['w']) // disable dwarf
+ return;
+
elfstrdbg[ElfStrDebugAbbrev] = addstring(shstrtab, ".debug_abbrev");
elfstrdbg[ElfStrDebugAranges] = addstring(shstrtab, ".debug_aranges");
elfstrdbg[ElfStrDebugFrame] = addstring(shstrtab, ".debug_frame");
@@ -2420,6 +2428,9 @@ dwarfaddelfheaders(void)
{
ElfShdr *sh;
+ if(debug['w']) // disable dwarf
+ return;
+
sh = newElfShdr(elfstrdbg[ElfStrDebugAbbrev]);
sh->type = SHT_PROGBITS;
sh->off = abbrevo;
@@ -2488,6 +2499,9 @@ dwarfaddmachoheaders(void)
vlong fakestart;
int nsect;
+ if(debug['w']) // disable dwarf
+ return;
+
// Zero vsize segments won't be loaded in memory, even so they
// have to be page aligned in the file.
fakestart = abbrevo & ~0xfff;
@@ -2562,6 +2576,9 @@ dwarfaddmachoheaders(void)
void
dwarfaddpeheaders(void)
{
+ if(debug['w']) // disable dwarf
+ return;
+
newPEDWARFSection(".debug_abbrev", abbrevsize);
newPEDWARFSection(".debug_line", linesize);
newPEDWARFSection(".debug_frame", framesize);
diff --git a/src/cmd/ld/ldpe.c b/src/cmd/ld/ldpe.c
index d8b0a6fc2..d6aa267c4 100644
--- a/src/cmd/ld/ldpe.c
+++ b/src/cmd/ld/ldpe.c
@@ -147,7 +147,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
goto bad;
obj->sect[i].size = obj->sect[i].sh.SizeOfRawData;
obj->sect[i].name = (char*)obj->sect[i].sh.Name;
- // TODO return error if found .cormeta .rsrc
+ // TODO return error if found .cormeta
}
// load string table
Bseek(f, base+obj->fh.PointerToSymbolTable+18*obj->fh.NumberOfSymbols, 0);
@@ -222,6 +222,8 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
etextp = s;
}
sect->sym = s;
+ if(strcmp(sect->name, ".rsrc") == 0)
+ setpersrc(sect->sym);
}
// load relocations
@@ -259,6 +261,7 @@ ldpe(Biobuf *f, char *pkg, int64 len, char *pn)
rp->type = D_PCREL;
rp->add = 0;
break;
+ case IMAGE_REL_I386_DIR32NB:
case IMAGE_REL_I386_DIR32:
rp->type = D_ADDR;
// load addend from image
diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h
index cd4608085..f69f5a35d 100644
--- a/src/cmd/ld/lib.h
+++ b/src/cmd/ld/lib.h
@@ -202,6 +202,7 @@ void addexport(void);
void dostkcheck(void);
void undef(void);
void doweak(void);
+void setpersrc(Sym*);
int pathchar(void);
void* mal(uint32);
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 01349bb10..0b12ac17b 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -17,6 +17,14 @@ static MachoSeg seg[16];
static MachoDebug xdebug[16];
static int nload, mload, nseg, ndebug, nsect;
+// Amount of space left for adding load commands
+// that refer to dynamic libraries. Because these have
+// to go in the Mach-O header, we can't just pick a
+// "big enough" header size. The initial header is
+// one page, the non-dynamic library stuff takes
+// up about 1300 bytes; we overestimate that as 2k.
+static int load_budget = INITIAL_MACHO_HEADR - 2*1024;
+
void
machoinit(void)
{
@@ -267,6 +275,17 @@ domacho(void)
void
machoadddynlib(char *lib)
{
+ // Will need to store the library name rounded up
+ // and 24 bytes of header metadata. If not enough
+ // space, grab another page of initial space at the
+ // beginning of the output file.
+ load_budget -= (strlen(lib)+7)/8*8 + 24;
+ if(load_budget < 0) {
+ HEADR += 4096;
+ INITTEXT += 4096;
+ load_budget += 4096;
+ }
+
if(ndylib%32 == 0) {
dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
if(dylib == nil) {
@@ -463,8 +482,8 @@ asmbmacho(void)
}
a = machowrite();
- if(a > MACHORESERVE)
- diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE);
+ if(a > HEADR)
+ diag("HEADR too small: %d > %d", a, HEADR);
}
vlong
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
index 4cc7edc80..f55104150 100644
--- a/src/cmd/ld/macho.h
+++ b/src/cmd/ld/macho.h
@@ -63,7 +63,7 @@ void machoinit(void);
* for Header, PHeaders, and SHeaders.
* May waste some.
*/
-#define MACHORESERVE 3*1024
+#define INITIAL_MACHO_HEADR 4*1024
enum {
MACHO_CPU_AMD64 = (1<<24)|7,
diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c
index 1c0c66538..91e15d343 100644
--- a/src/cmd/ld/pe.c
+++ b/src/cmd/ld/pe.c
@@ -34,6 +34,8 @@ static char dosstub[] =
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+static Sym *rsrcsym;
+
static char symnames[256];
static int nextsymoff;
@@ -459,6 +461,48 @@ addsymtable(void)
}
void
+setpersrc(Sym *sym)
+{
+ if(rsrcsym != nil)
+ diag("too many .rsrc sections");
+
+ rsrcsym = sym;
+}
+
+void
+addpersrc(void)
+{
+ IMAGE_SECTION_HEADER *h;
+ uchar *p;
+ uint32 val;
+ Reloc *r;
+
+ if(rsrcsym == nil)
+ return;
+
+ h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size, 0);
+ h->Characteristics = IMAGE_SCN_MEM_READ|
+ IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
+ // relocation
+ for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) {
+ p = rsrcsym->p + r->off;
+ val = h->VirtualAddress + r->add;
+ // 32-bit little-endian
+ p[0] = val;
+ p[1] = val>>8;
+ p[2] = val>>16;
+ p[3] = val>>24;
+ }
+ ewrite(cout, rsrcsym->p, rsrcsym->size);
+ strnput("", h->SizeOfRawData - rsrcsym->size);
+ cflush();
+
+ // update data directory
+ dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress;
+ dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize;
+}
+
+void
asmbpe(void)
{
IMAGE_SECTION_HEADER *t, *d;
@@ -492,7 +536,9 @@ asmbpe(void)
addexports(nextfileoff);
addsymtable();
-
+
+ addpersrc();
+
fh.NumberOfSections = nsect;
fh.TimeDateStamp = time(0);
fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED|
diff --git a/src/cmd/ld/pe.h b/src/cmd/ld/pe.h
index 2180fb88c..7aa938829 100644
--- a/src/cmd/ld/pe.h
+++ b/src/cmd/ld/pe.h
@@ -175,3 +175,5 @@ typedef struct {
uint32 NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
} PE64_IMAGE_OPTIONAL_HEADER;
+
+void setpersrc(Sym *sym);