diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-05-23 09:45:29 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-05-23 09:45:29 +0200 |
commit | 63d29fefab5290dc96e0a03ff70603aefa995887 (patch) | |
tree | 95da0105686f9aba568a72e7a8ebd580a4fda20e /src/cmd | |
parent | ad811fbb8897a9a3063274e927133915941f1dca (diff) | |
download | golang-63d29fefab5290dc96e0a03ff70603aefa995887.tar.gz |
Imported Upstream version 2011.05.22upstream-weekly/2011.05.22
Diffstat (limited to 'src/cmd')
49 files changed, 731 insertions, 606 deletions
diff --git a/src/cmd/5a/lex.c b/src/cmd/5a/lex.c index dbee3657f..a04cda220 100644 --- a/src/cmd/5a/lex.c +++ b/src/cmd/5a/lex.c @@ -50,7 +50,7 @@ void main(int argc, char *argv[]) { char *p; - int nout, nproc, i, c; + int c; thechar = '5'; thestring = "arm"; @@ -94,46 +94,10 @@ main(int argc, char *argv[]) print("usage: %ca [-options] file.s\n", thechar); errorexit(); } - if(argc > 1 && systemtype(Windows)){ - print("can't assemble multiple files on windows\n"); + if(argc > 1){ + print("can't assemble multiple files\n"); errorexit(); } - if(argc > 1 && !systemtype(Windows)) { - nproc = 1; - if(p = getenv("NPROC")) - nproc = atol(p); /* */ - c = 0; - nout = 0; - for(;;) { - Waitmsg *w; - - while(nout < nproc && argc > 0) { - i = fork(); - if(i < 0) { - fprint(2, "fork: %r\n"); - errorexit(); - } - if(i == 0) { - print("%s:\n", *argv); - if(assemble(*argv)) - errorexit(); - exits(0); - } - nout++; - argc--; - argv++; - } - w = wait(); - if(w == nil) { - if(c) - errorexit(); - exits(0); - } - if(w->msg[0]) - c++; - nout--; - } - } if(assemble(argv[0])) errorexit(); exits(0); @@ -142,7 +106,7 @@ main(int argc, char *argv[]) int assemble(char *file) { - char *ofile, incfile[20], *p; + char *ofile, *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) @@ -167,15 +131,6 @@ assemble(char *file) } else outfile = "/dev/null"; } - p = getenv("INCLUDE"); - if(p) { - setinclude(p); - } else { - if(systemtype(Plan9)) { - sprint(incfile,"/%s/include", thestring); - setinclude(strdup(incfile)); - } - } of = create(outfile, OWRITE, 0664); if(of < 0) { diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h index 9e9d1bd7d..549e0c88a 100644 --- a/src/cmd/5c/gc.h +++ b/src/cmd/5c/gc.h @@ -69,7 +69,7 @@ struct Adr Sym* sym; char type; - char reg; + uchar reg; char name; char etype; }; @@ -83,7 +83,7 @@ struct Prog Prog* link; int32 lineno; char as; - char reg; + uchar reg; uchar scond; }; #define P ((Prog*)0) diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h index 78e6833b2..fe404ed79 100644 --- a/src/cmd/5g/gg.h +++ b/src/cmd/5g/gg.h @@ -26,7 +26,7 @@ struct Addr int width; uchar type; char name; - char reg; + uchar reg; char pun; uchar etype; }; @@ -41,7 +41,7 @@ struct Prog Addr to; // dst address Prog* link; // next instruction in this func void* regp; // points to enclosing Reg struct - char reg; // doubles as width in DATA op + uchar reg; // doubles as width in DATA op uchar scond; }; diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c index e2583e7c3..9e9c2c1eb 100644 --- a/src/cmd/5l/asm.c +++ b/src/cmd/5l/asm.c @@ -73,6 +73,8 @@ enum { ElfStrGosymcounts, ElfStrGosymtab, ElfStrGopclntab, + ElfStrSymtab, + ElfStrStrtab, ElfStrShstrtab, ElfStrRelPlt, ElfStrPlt, @@ -87,6 +89,9 @@ needlib(char *name) char *p; Sym *s; + if(*name == '\0') + return 0; + /* reuse hash code in symbol table */ p = smprint(".dynlib.%s", name); s = lookup(p, 0); @@ -163,6 +168,8 @@ doelf(void) elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts"); elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab"); elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab"); + elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab"); + elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab"); } elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab"); @@ -288,19 +295,20 @@ asmb(void) { int32 t; int a, dynsym; - uint32 va, fo, w, startva; - int strtabsize; + uint32 fo, symo, startva, elfsymo, elfstro, elfsymsize; ElfEhdr *eh; ElfPhdr *ph, *pph; ElfShdr *sh; Section *sect; - strtabsize = 0; - if(debug['v']) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); + elfsymsize = 0; + elfstro = 0; + elfsymo = 0; + sect = segtext.sect; seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0); codeblk(sect->vaddr, sect->len); @@ -322,15 +330,30 @@ asmb(void) seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0); datblk(sect->vaddr, sect->len); + if(iself) { + /* index of elf text section; needed by asmelfsym, double-checked below */ + /* !debug['d'] causes extra sections before the .text section */ + elftextsh = 1; + if(!debug['d']) { + elftextsh += 10; + if(elfverneed) + elftextsh += 2; + } + } + /* output symbol table */ symsize = 0; lcsize = 0; + symo = 0; if(!debug['s']) { // TODO: rationalize if(debug['v']) Bprint(&bso, "%5.2f sym\n", cputime()); Bflush(&bso); switch(HEADTYPE) { + default: + if(iself) + goto ElfSym; case Hnoheader: case Hrisc: case Hixp1200: @@ -345,14 +368,29 @@ asmb(void) OFFSET += rnd(segdata.filelen, 4096); seek(cout, OFFSET, 0); break; - case Hlinux: - OFFSET += segdata.filelen; - seek(cout, rnd(OFFSET, INITRND), 0); + ElfSym: + symo = rnd(HEADR+segtext.filelen, INITRND)+segdata.filelen; + symo = rnd(symo, INITRND); break; } - if(!debug['s']) - asmthumbmap(); + if(iself) { + if(debug['v']) + Bprint(&bso, "%5.2f elfsym\n", cputime()); + elfsymo = symo+8+symsize+lcsize; + seek(cout, elfsymo, 0); + asmelfsym32(); + cflush(); + elfstro = seek(cout, 0, 1); + elfsymsize = elfstro - elfsymo; + ewrite(cout, elfstrdat, elfstrsize); + + // if(debug['v']) + // Bprint(&bso, "%5.2f dwarf\n", cputime()); + // dwarfemitdebugsections(); + } + asmthumbmap(); cflush(); + } cursym = nil; @@ -426,9 +464,7 @@ asmb(void) /* elf arm */ eh = getElfEhdr(); fo = HEADR; - va = INITTEXT; startva = INITTEXT - fo; /* va of byte 0 of file */ - w = textsize; /* This null SHdr must appear before all others */ sh = newElfShdr(elfstr[ElfStrEmpty]); @@ -541,6 +577,8 @@ asmb(void) ph->flags = PF_W+PF_R; ph->align = 4; + if(elftextsh != eh->shnum) + diag("elftextsh = %d, want %d", elftextsh, eh->shnum); for(sect=segtext.sect; sect!=nil; sect=sect->next) elfshbits(sect); for(sect=segdata.sect; sect!=nil; sect=sect->next) @@ -558,6 +596,22 @@ asmb(void) sh->flags = SHF_ALLOC; sh->addralign = 1; shsym(sh, lookup("pclntab", 0)); + + sh = newElfShdr(elfstr[ElfStrSymtab]); + sh->type = SHT_SYMTAB; + sh->off = elfsymo; + sh->size = elfsymsize; + sh->addralign = 4; + sh->entsize = 16; + sh->link = eh->shnum; // link to strtab + + sh = newElfShdr(elfstr[ElfStrStrtab]); + sh->type = SHT_STRTAB; + sh->off = elfstro; + sh->size = elfstrsize; + sh->addralign = 1; + + // dwarfaddelfheaders(); } sh = newElfShstrtab(elfstr[ElfStrShstrtab]); @@ -990,40 +1044,6 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o1 |= 1<<22; break; - case 22: /* movb/movh/movhu O(R),R -> lr,shl,shr */ - aclass(&p->from); - r = p->from.reg; - if(r == NREG) - r = o->param; - o1 = olr(instoffset, r, p->to.reg, p->scond); - - o2 = oprrr(ASLL, p->scond); - o3 = oprrr(ASRA, p->scond); - r = p->to.reg; - if(p->as == AMOVB) { - o2 |= (24<<7)|(r)|(r<<12); - o3 |= (24<<7)|(r)|(r<<12); - } else { - o2 |= (16<<7)|(r)|(r<<12); - if(p->as == AMOVHU) - o3 = oprrr(ASRL, p->scond); - o3 |= (16<<7)|(r)|(r<<12); - } - break; - - case 23: /* movh/movhu R,O(R) -> sb,sb */ - aclass(&p->to); - r = p->to.reg; - if(r == NREG) - r = o->param; - o1 = osr(AMOVH, p->from.reg, instoffset, r, p->scond); - - o2 = oprrr(ASRL, p->scond); - o2 |= (8<<7)|(p->from.reg)|(REGTMP<<12); - - o3 = osr(AMOVH, REGTMP, instoffset+1, r, p->scond); - break; - case 30: /* mov/movb/movbu R,L(R) */ o1 = omvl(p, &p->to, REGTMP); if(!o1) @@ -1037,7 +1057,6 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na break; case 31: /* mov/movbu L(R),R -> lr[b] */ - case 32: /* movh/movb L(R),R -> lr[b] */ o1 = omvl(p, &p->from, REGTMP); if(!o1) break; @@ -1047,53 +1066,6 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o2 = olrr(REGTMP,r, p->to.reg, p->scond); if(p->as == AMOVBU || p->as == AMOVB) o2 |= 1<<22; - if(o->type == 31) - break; - - o3 = oprrr(ASLL, p->scond); - - if(p->as == AMOVBU || p->as == AMOVHU) - o4 = oprrr(ASRL, p->scond); - else - o4 = oprrr(ASRA, p->scond); - - r = p->to.reg; - o3 |= (r)|(r<<12); - o4 |= (r)|(r<<12); - if(p->as == AMOVB || p->as == AMOVBU) { - o3 |= (24<<7); - o4 |= (24<<7); - } else { - o3 |= (16<<7); - o4 |= (16<<7); - } - break; - - case 33: /* movh/movhu R,L(R) -> sb, sb */ - o1 = omvl(p, &p->to, REGTMP); - if(!o1) - break; - r = p->to.reg; - if(r == NREG) - r = o->param; - o2 = osrr(p->from.reg, REGTMP, r, p->scond); - o2 |= (1<<22) ; - - o3 = oprrr(ASRL, p->scond); - o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); - o3 |= (1<<6); /* ROR 8 */ - - o4 = oprrr(AADD, p->scond); - o4 |= (REGTMP << 12) | (REGTMP << 16); - o4 |= immrot(1); - - o5 = osrr(p->from.reg, REGTMP,r,p->scond); - o5 |= (1<<22); - - o6 = oprrr(ASRL, p->scond); - o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); - o6 |= (1<<6); /* ROL 8 */ - break; case 34: /* mov $lacon,R */ @@ -1304,54 +1276,12 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na break; case 65: /* mov/movbu addr,R */ - case 66: /* movh/movhu/movb addr,R */ o1 = omvl(p, &p->from, REGTMP); if(!o1) break; o2 = olr(0, REGTMP, p->to.reg, p->scond); if(p->as == AMOVBU || p->as == AMOVB) o2 |= 1<<22; - if(o->type == 65) - break; - - o3 = oprrr(ASLL, p->scond); - - if(p->as == AMOVBU || p->as == AMOVHU) - o4 = oprrr(ASRL, p->scond); - else - o4 = oprrr(ASRA, p->scond); - - r = p->to.reg; - o3 |= (r)|(r<<12); - o4 |= (r)|(r<<12); - if(p->as == AMOVB || p->as == AMOVBU) { - o3 |= (24<<7); - o4 |= (24<<7); - } else { - o3 |= (16<<7); - o4 |= (16<<7); - } - break; - - case 67: /* movh/movhu R,addr -> sb, sb */ - o1 = omvl(p, &p->to, REGTMP); - if(!o1) - break; - o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); - - o3 = oprrr(ASRL, p->scond); - o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); - o3 |= (1<<6); /* ROR 8 */ - - o4 = oprrr(AADD, p->scond); - o4 |= (REGTMP << 12) | (REGTMP << 16); - o4 |= immrot(1); - - o5 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); - - o6 = oprrr(ASRL, p->scond); - o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); - o6 |= (1<<6); /* ROL 8 */ break; case 68: /* floating point store -> ADDR */ @@ -1572,6 +1502,22 @@ if(debug['G']) print("%ux: %s: arm %d %d %d\n", (uint32)(p->pc), p->from.sym->na o1 |= p->to.reg << 12; o1 |= (p->scond & C_SCOND) << 28; break; + case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */ + o1 = omvl(p, &p->from, REGTMP); + if(!o1) + break; + o2 = olhr(0, REGTMP, p->to.reg, p->scond); + if(p->as == AMOVB) + o2 ^= (1<<5)|(1<<6); + else if(p->as == AMOVH) + o2 ^= (1<<6); + break; + case 94: /* movh/movhu R,addr -> strh */ + o1 = omvl(p, &p->to, REGTMP); + if(!o1) + break; + o2 = oshr(p->from.reg, 0, REGTMP, p->scond); + break; } out[0] = o1; diff --git a/src/cmd/5l/obj.c b/src/cmd/5l/obj.c index c4a2bfc3f..96ba0010f 100644 --- a/src/cmd/5l/obj.c +++ b/src/cmd/5l/obj.c @@ -219,7 +219,7 @@ main(int argc, char *argv[]) elfinit(); HEADR = ELFRESERVE; if(INITTEXT == -1) - INITTEXT = 0x8000 + HEADR; + INITTEXT = 0x10000 + HEADR; if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) @@ -412,7 +412,7 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) { int32 ipc; Prog *p; - Sym *h[NSYM], *s, *di; + Sym *h[NSYM], *s; int v, o, r, skip; uint32 sig; char *name; @@ -424,7 +424,6 @@ ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) lastp = nil; ntext = 0; eof = Boffset(f) + len; - di = S; src[0] = 0; newloop: diff --git a/src/cmd/5l/optab.c b/src/cmd/5l/optab.c index 625b66812..4816aa40f 100644 --- a/src/cmd/5l/optab.c +++ b/src/cmd/5l/optab.c @@ -117,18 +117,6 @@ Optab optab[] = { AMOVBU, C_SAUTO,C_NONE, C_REG, 21, 4, REGSP }, { AMOVBU, C_SOREG,C_NONE, C_REG, 21, 4, 0 }, - { AMOVB, C_SAUTO,C_NONE, C_REG, 22, 12, REGSP }, - { AMOVB, C_SOREG,C_NONE, C_REG, 22, 12, 0 }, - { AMOVH, C_SAUTO,C_NONE, C_REG, 22, 12, REGSP }, - { AMOVH, C_SOREG,C_NONE, C_REG, 22, 12, 0 }, - { AMOVHU, C_SAUTO,C_NONE, C_REG, 22, 12, REGSP }, - { AMOVHU, C_SOREG,C_NONE, C_REG, 22, 12, 0 }, - - { AMOVH, C_REG, C_NONE, C_SAUTO, 23, 12, REGSP }, - { AMOVH, C_REG, C_NONE, C_SOREG, 23, 12, 0 }, - { AMOVHU, C_REG, C_NONE, C_SAUTO, 23, 12, REGSP }, - { AMOVHU, C_REG, C_NONE, C_SOREG, 23, 12, 0 }, - { AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO }, { AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO }, { AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO }, @@ -146,23 +134,6 @@ Optab optab[] = { AMOVBU, C_LOREG,C_NONE, C_REG, 31, 8, 0, LFROM }, { AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM }, - { AMOVB, C_LAUTO,C_NONE, C_REG, 32, 16, REGSP, LFROM }, - { AMOVB, C_LOREG,C_NONE, C_REG, 32, 16, 0, LFROM }, - { AMOVB, C_ADDR, C_NONE, C_REG, 66, 16, 0, LFROM }, - { AMOVH, C_LAUTO,C_NONE, C_REG, 32, 16, REGSP, LFROM }, - { AMOVH, C_LOREG,C_NONE, C_REG, 32, 16, 0, LFROM }, - { AMOVH, C_ADDR, C_NONE, C_REG, 66, 16, 0, LFROM }, - { AMOVHU, C_LAUTO,C_NONE, C_REG, 32, 16, REGSP, LFROM }, - { AMOVHU, C_LOREG,C_NONE, C_REG, 32, 16, 0, LFROM }, - { AMOVHU, C_ADDR, C_NONE, C_REG, 66, 16, 0, LFROM }, - - { AMOVH, C_REG, C_NONE, C_LAUTO, 33, 24, REGSP, LTO }, - { AMOVH, C_REG, C_NONE, C_LOREG, 33, 24, 0, LTO }, - { AMOVH, C_REG, C_NONE, C_ADDR, 67, 24, 0, LTO }, - { AMOVHU, C_REG, C_NONE, C_LAUTO, 33, 24, REGSP, LTO }, - { AMOVHU, C_REG, C_NONE, C_LOREG, 33, 24, 0, LTO }, - { AMOVHU, C_REG, C_NONE, C_ADDR, 67, 24, 0, LTO }, - { AMOVW, C_LACON,C_NONE, C_REG, 34, 8, REGSP, LFROM }, { AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0 }, @@ -224,15 +195,21 @@ Optab optab[] = { AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO|V4 }, { AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO|V4 }, + { AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO|V4 }, { AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO|V4 }, { AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO|V4 }, + { AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO|V4 }, { AMOVB, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM|V4 }, { AMOVB, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM|V4 }, + { AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM|V4 }, { AMOVH, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM|V4 }, { AMOVH, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM|V4 }, + { AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM|V4 }, { AMOVHU, C_LAUTO,C_NONE, C_REG, 73, 8, REGSP, LFROM|V4 }, { AMOVHU, C_LOREG,C_NONE, C_REG, 73, 8, 0, LFROM|V4 }, + { AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM|V4 }, + { ALDREX, C_SOREG,C_NONE, C_REG, 77, 4, 0 }, { ASTREX, C_SOREG,C_REG, C_REG, 78, 4, 0 }, diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c index 482d3e90a..4067f1a32 100644 --- a/src/cmd/5l/span.c +++ b/src/cmd/5l/span.c @@ -168,7 +168,6 @@ span(void) Optab *o; int m, bflag, i, v; int32 c, otxt, out[6]; - int lastthumb = -1; Section *sect; uchar *bp; @@ -187,7 +186,6 @@ span(void) p->pc = c; cursym->value = c; - lastthumb = thumb; autosize = p->to.offset + 4; if(p->from.sym != S) p->from.sym->value = c; @@ -927,7 +925,7 @@ buildop(void) { int i, n, r; - armv4 = !debug['h']; + armv4 = 1; for(i=0; i<C_GOK; i++) for(n=0; n<C_GOK; n++) xcmp[i][n] = cmp(n, i); diff --git a/src/cmd/6a/lex.c b/src/cmd/6a/lex.c index 37144c888..b4c7d0c2c 100644 --- a/src/cmd/6a/lex.c +++ b/src/cmd/6a/lex.c @@ -56,7 +56,7 @@ void main(int argc, char *argv[]) { char *p; - int nout, nproc, i, c; + int c; thechar = '6'; thestring = "amd64"; @@ -96,46 +96,10 @@ main(int argc, char *argv[]) print("usage: %ca [-options] file.s\n", thechar); errorexit(); } - if(argc > 1 && systemtype(Windows)){ - print("can't assemble multiple files on windows\n"); + if(argc > 1){ + print("can't assemble multiple files\n"); errorexit(); } - if(argc > 1 && !systemtype(Windows)) { - nproc = 1; - if(p = getenv("NPROC")) - nproc = atol(p); /* */ - c = 0; - nout = 0; - for(;;) { - Waitmsg *w; - - while(nout < nproc && argc > 0) { - i = fork(); - if(i < 0) { - fprint(2, "fork: %r\n"); - errorexit(); - } - if(i == 0) { - print("%s:\n", *argv); - if(assemble(*argv)) - errorexit(); - exits(0); - } - nout++; - argc--; - argv++; - } - w = wait(); - if(w == nil) { - if(c) - errorexit(); - exits(0); - } - if(w->msg[0]) - c++; - nout--; - } - } if(assemble(argv[0])) errorexit(); exits(0); @@ -144,7 +108,7 @@ main(int argc, char *argv[]) int assemble(char *file) { - char *ofile, incfile[20], *p; + char *ofile, *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) @@ -169,15 +133,6 @@ assemble(char *file) } else outfile = "/dev/null"; } - p = getenv("INCLUDE"); - if(p) { - setinclude(p); - } else { - if(systemtype(Plan9)) { - sprint(incfile,"/%s/include", thestring); - setinclude(strdup(incfile)); - } - } of = create(outfile, OWRITE, 0664); if(of < 0) { diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index 75dc4fe13..fca4b64dd 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -283,11 +283,9 @@ cgen(Node *n, Node *res) if(istype(nl->type, TSTRING) || isslice(nl->type)) { // both slice and string have len one pointer into the struct. // a zero pointer means zero length - regalloc(&n1, types[tptr], res); - agen(nl, &n1); - n1.op = OINDREG; + igen(nl, &n1, res); n1.type = types[TUINT32]; - n1.xoffset = Array_nel; + n1.xoffset += Array_nel; gmove(&n1, res); regfree(&n1); break; @@ -319,11 +317,9 @@ cgen(Node *n, Node *res) break; } if(isslice(nl->type)) { - regalloc(&n1, types[tptr], res); - agen(nl, &n1); - n1.op = OINDREG; + igen(nl, &n1, res); n1.type = types[TUINT32]; - n1.xoffset = Array_cap; + n1.xoffset += Array_cap; gmove(&n1, res); regfree(&n1); break; @@ -542,7 +538,8 @@ agen(Node *n, Node *res) gmove(&n1, &n3); } - ginscon(optoas(OADD, types[tptr]), v*w, &n3); + if (v*w != 0) + ginscon(optoas(OADD, types[tptr]), v*w, &n3); gmove(&n3, res); regfree(&n3); break; @@ -682,6 +679,28 @@ ret: void igen(Node *n, Node *a, Node *res) { + Type *fp; + Iter flist; + + switch(n->op) { + case ONAME: + if((n->class&PHEAP) || n->class == PPARAMREF) + break; + *a = *n; + return; + + case OCALLFUNC: + fp = structfirst(&flist, getoutarg(n->left->type)); + cgen_call(n, 0); + memset(a, 0, sizeof *a); + a->op = OINDREG; + a->val.u.reg = D_SP; + a->addable = 1; + a->xoffset = fp->width; + a->type = n->type; + return; + } + regalloc(a, types[tptr], res); agen(n, a); a->op = OINDREG; @@ -848,6 +867,7 @@ bgen(Node *n, int true, Prog *to) n2 = n1; n2.op = OINDREG; n2.xoffset = Array_array; + n2.type = types[tptr]; nodconst(&tmp, types[tptr], 0); gins(optoas(OCMP, types[tptr]), &n2, &tmp); patch(gbranch(a, types[tptr]), to); diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c index 8d89fb164..ce66b43f0 100644 --- a/src/cmd/6g/ggen.c +++ b/src/cmd/6g/ggen.c @@ -201,7 +201,7 @@ cgen_callinter(Node *n, Node *res, int proc) regalloc(&nodo, types[tptr], &nodr); nodo.op = OINDREG; - agen(i, &nodr); // REG = &inter + agen(i, &nodr); // REG = &inter nodindreg(&nodsp, types[tptr], D_SP); nodo.xoffset += widthptr; @@ -1206,7 +1206,7 @@ cgen_inline(Node *n, Node *res) Node nodes[5]; Node n1, n2, nres, ntemp; vlong v; - int i, narg; + int i, narg, nochk; if(n->op != OCALLFUNC) goto no; @@ -1242,6 +1242,7 @@ slicearray: // len = hb[3] - lb[2] (destroys hb) n2 = *res; n2.xoffset += Array_nel; + n2.type = types[TUINT32]; if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) { v = mpgetfix(nodes[3].val.u.xval) - @@ -1260,6 +1261,7 @@ slicearray: // cap = nel[1] - lb[2] (destroys nel) n2 = *res; n2.xoffset += Array_cap; + n2.type = types[TUINT32]; if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) { v = mpgetfix(nodes[1].val.u.xval) - @@ -1288,6 +1290,7 @@ slicearray: // ary = old[0] + (lb[2] * width[4]) (destroys old) n2 = *res; n2.xoffset += Array_array; + n2.type = types[tptr]; if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) { v = mpgetfix(nodes[2].val.u.xval) * @@ -1311,6 +1314,7 @@ slicearray: return 1; sliceslice: + nochk = n->etype; // skip bounds checking ntemp.op = OXXX; if(!sleasy(n->list->n->right)) { Node *n0; @@ -1340,11 +1344,13 @@ sliceslice: n2 = nodes[0]; n2.xoffset += Array_nel; n2.type = types[TUINT32]; - cmpandthrow(&nodes[1], &n2); + if(!nochk) + cmpandthrow(&nodes[1], &n2); // ret.nel = old.nel[0]-lb[1]; n2 = nodes[0]; n2.xoffset += Array_nel; + n2.type = types[TUINT32]; regalloc(&n1, types[TUINT32], N); gins(optoas(OAS, types[TUINT32]), &n2, &n1); @@ -1353,22 +1359,24 @@ sliceslice: n2 = nres; n2.xoffset += Array_nel; + n2.type = types[TUINT32]; gins(optoas(OAS, types[TUINT32]), &n1, &n2); regfree(&n1); } else { // old[lb:hb] - // if(hb[2] > old.cap[0]) goto throw; n2 = nodes[0]; n2.xoffset += Array_cap; n2.type = types[TUINT32]; - cmpandthrow(&nodes[2], &n2); - - // if(lb[1] > hb[2]) goto throw; - cmpandthrow(&nodes[1], &nodes[2]); - + if(!nochk) { + // if(hb[2] > old.cap[0]) goto throw; + cmpandthrow(&nodes[2], &n2); + // if(lb[1] > hb[2]) goto throw; + cmpandthrow(&nodes[1], &nodes[2]); + } // ret.len = hb[2]-lb[1]; (destroys hb[2]) n2 = nres; n2.xoffset += Array_nel; - + n2.type = types[TUINT32]; + if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) { v = mpgetfix(nodes[2].val.u.xval) - mpgetfix(nodes[1].val.u.xval); @@ -1387,6 +1395,7 @@ sliceslice: // ret.cap = old.cap[0]-lb[1]; (uses hb[2]) n2 = nodes[0]; n2.xoffset += Array_cap; + n2.type = types[TUINT32]; regalloc(&n1, types[TUINT32], &nodes[2]); gins(optoas(OAS, types[TUINT32]), &n2, &n1); @@ -1395,13 +1404,15 @@ sliceslice: n2 = nres; n2.xoffset += Array_cap; + n2.type = types[TUINT32]; + gins(optoas(OAS, types[TUINT32]), &n1, &n2); regfree(&n1); // ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1]) n2 = nodes[0]; n2.xoffset += Array_array; - + n2.type = types[tptr]; regalloc(&n1, types[tptr], &nodes[1]); if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) { gins(optoas(OAS, types[tptr]), &n2, &n1); @@ -1418,6 +1429,7 @@ sliceslice: n2 = nres; n2.xoffset += Array_array; + n2.type = types[tptr]; gins(optoas(OAS, types[tptr]), &n1, &n2); regfree(&n1); diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index c3dac1fdc..ed98d1bc9 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -48,7 +48,7 @@ clearp(Prog *p) /* * generate and return proc with p->as = as, - * linked into program. pc is next instruction. + * linked into program. pc is next instruction. */ Prog* prog(int as) @@ -330,11 +330,13 @@ regfree(Node *n) { int i; - if(n->op == ONAME && iscomplex[n->type->etype]) + if(n->op == ONAME) return; if(n->op != OREGISTER && n->op != OINDREG) fatal("regfree: not a register"); i = n->val.u.reg; + if(i == D_SP) + return; if(i < 0 || i >= sizeof(reg)) fatal("regfree: reg out of range"); if(reg[i] <= 0) @@ -888,7 +890,7 @@ Prog* gins(int as, Node *f, Node *t) { // Node nod; -// int32 v; + int32 w; Prog *p; Addr af, at; @@ -933,6 +935,27 @@ gins(int as, Node *f, Node *t) p->to = at; if(debug['g']) print("%P\n", p); + + + w = 0; + switch(as) { + case AMOVB: + w = 1; + break; + case AMOVW: + w = 2; + break; + case AMOVL: + w = 4; + break; + case AMOVQ: + w = 8; + break; + } + if(w != 0 && f != N && (af.width > w || at.width > w)) { + fatal("bad width: %P (%d, %d)\n", p, af.width, at.width); + } + return p; } @@ -947,7 +970,7 @@ checkoffset(Addr *a, int canemitcode) fatal("checkoffset %#llx, cannot emit code", a->offset); // cannot rely on unmapped nil page at 0 to catch - // reference with large offset. instead, emit explicit + // reference with large offset. instead, emit explicit // test of 0(reg). p = gins(ATESTB, nodintconst(0), N); p->to = *a; @@ -1106,8 +1129,9 @@ naddr(Node *n, Addr *a, int canemitcode) naddr(n->left, a, canemitcode); if(a->type == D_CONST && a->offset == 0) break; // len(nil) - a->etype = TUINT; + a->etype = TUINT32; a->offset += Array_nel; + a->width = 4; if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) checkoffset(a, canemitcode); break; @@ -1117,8 +1141,9 @@ naddr(Node *n, Addr *a, int canemitcode) naddr(n->left, a, canemitcode); if(a->type == D_CONST && a->offset == 0) break; // cap(nil) - a->etype = TUINT; + a->etype = TUINT32; a->offset += Array_cap; + a->width = 4; if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero) checkoffset(a, canemitcode); break; @@ -1962,12 +1987,12 @@ oindex: if(o & OAddable) { n2 = *l; n2.xoffset += Array_array; - n2.type = types[TUINT64]; + n2.type = types[tptr]; gmove(&n2, reg); } else { n2 = *reg; - n2.xoffset = Array_array; n2.op = OINDREG; + n2.xoffset = Array_array; n2.type = types[tptr]; gmove(&n2, reg); } diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index ed8bac3f0..b4b5b7d6b 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -873,14 +873,17 @@ mkvar(Reg *r, Adr *a) // if they overlaps, disable both if(overlap(v->offset, v->width, o, w)) { +// print("disable overlap %s %d %d %d %d, %E != %E\n", s->name, v->offset, v->width, o, w, v->etype, et); v->addr = 1; flag = 1; } } } - if(a->pun) + if(a->pun) { +// print("disable pun %s\n", s->name); flag = 1; + } switch(et) { case 0: case TFUNC: diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c index dda19e48d..6dffa20f2 100644 --- a/src/cmd/6l/asm.c +++ b/src/cmd/6l/asm.c @@ -108,6 +108,9 @@ needlib(char *name) char *p; Sym *s; + if(*name == '\0') + return 0; + /* reuse hash code in symbol table */ p = smprint(".elfload.%s", name); s = lookup(p, 0); @@ -787,40 +790,51 @@ asmb(void) symo = rnd(symo, PEFILEALIGN); break; } - /* - * the symbol information is stored as - * 32-bit symbol table size - * 32-bit line number table size - * symbol table - * line number table - */ - seek(cout, symo+8, 0); - if(debug['v']) - Bprint(&bso, "%5.2f sp\n", cputime()); - Bflush(&bso); - if(debug['v']) - Bprint(&bso, "%5.2f pc\n", cputime()); - Bflush(&bso); - if(!debug['s']) - strnput("", INITRND-(8+symsize+lcsize)%INITRND); - cflush(); - seek(cout, symo, 0); - lputl(symsize); - lputl(lcsize); - cflush(); - if(HEADTYPE != Hwindows && !debug['s']) { - elfsymo = symo+8+symsize+lcsize; - seek(cout, elfsymo, 0); - asmelfsym64(); - cflush(); - elfstro = seek(cout, 0, 1); - elfsymsize = elfstro - elfsymo; - ewrite(cout, elfstrdat, elfstrsize); - + switch(HEADTYPE) { + default: + if(iself) { + /* + * the symbol information is stored as + * 32-bit symbol table size + * 32-bit line number table size + * symbol table + * line number table + */ + seek(cout, symo+8, 0); + if(debug['v']) + Bprint(&bso, "%5.2f sp\n", cputime()); + Bflush(&bso); + if(debug['v']) + Bprint(&bso, "%5.2f pc\n", cputime()); + Bflush(&bso); + if(!debug['s']) + strnput("", INITRND-(8+symsize+lcsize)%INITRND); + cflush(); + seek(cout, symo, 0); + lputl(symsize); + lputl(lcsize); + cflush(); + elfsymo = symo+8+symsize+lcsize; + seek(cout, elfsymo, 0); + asmelfsym64(); + cflush(); + elfstro = seek(cout, 0, 1); + elfsymsize = elfstro - elfsymo; + ewrite(cout, elfstrdat, elfstrsize); + + if(debug['v']) + Bprint(&bso, "%5.2f dwarf\n", cputime()); + + dwarfemitdebugsections(); + } + break; + case Hwindows: + seek(cout, symo, 0); if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); + break; } } diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index 33ca51b2c..f4ee6aa92 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -350,9 +350,6 @@ EXTERN Sym* fromgotype; // type symbol on last p->from read EXTERN vlong textstksiz; EXTERN vlong textarg; -EXTERN int elfstrsize; -EXTERN char* elfstrdat; -EXTERN int elftextsh; extern Optab optab[]; extern Optab* opindex[]; diff --git a/src/cmd/8a/lex.c b/src/cmd/8a/lex.c index ca18b69ce..078861877 100644 --- a/src/cmd/8a/lex.c +++ b/src/cmd/8a/lex.c @@ -56,7 +56,7 @@ void main(int argc, char *argv[]) { char *p; - int nout, nproc, i, c; + int c; thechar = '8'; thestring = "386"; @@ -96,46 +96,10 @@ main(int argc, char *argv[]) print("usage: %ca [-options] file.s\n", thechar); errorexit(); } - if(argc > 1 && systemtype(Windows)){ - print("can't assemble multiple files on windows\n"); + if(argc > 1){ + print("can't assemble multiple files\n"); errorexit(); } - if(argc > 1 && !systemtype(Windows)) { - nproc = 1; - if(p = getenv("NPROC")) - nproc = atol(p); /* */ - c = 0; - nout = 0; - for(;;) { - Waitmsg *w; - - while(nout < nproc && argc > 0) { - i = fork(); - if(i < 0) { - fprint(2, "fork: %r\n"); - errorexit(); - } - if(i == 0) { - print("%s:\n", *argv); - if(assemble(*argv)) - errorexit(); - exits(0); - } - nout++; - argc--; - argv++; - } - w = wait(); - if(w == nil) { - if(c) - errorexit(); - exits(0); - } - if(w->msg[0]) - c++; - nout--; - } - } if(assemble(argv[0])) errorexit(); exits(0); @@ -144,7 +108,7 @@ main(int argc, char *argv[]) int assemble(char *file) { - char *ofile, incfile[20], *p; + char *ofile, *p; int i, of; ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) @@ -169,15 +133,6 @@ assemble(char *file) } else outfile = "/dev/null"; } - p = getenv("INCLUDE"); - if(p) { - setinclude(p); - } else { - if(systemtype(Plan9)) { - sprint(incfile,"/%s/include", thestring); - setinclude(strdup(incfile)); - } - } of = create(outfile, OWRITE, 0664); if(of < 0) { diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index 596824a6c..1614a2d77 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -232,6 +232,7 @@ cgen(Node *n, Node *res) cgen(nl, res); break; } + tempname(&n2, n->type); mgen(nl, &n1, res); gmove(&n1, &n2); @@ -277,15 +278,10 @@ cgen(Node *n, Node *res) if(istype(nl->type, TSTRING) || isslice(nl->type)) { // both slice and string have len one pointer into the struct. igen(nl, &n1, res); - n1.op = OREGISTER; // was OINDREG - regalloc(&n2, types[TUINT32], &n1); - n1.op = OINDREG; n1.type = types[TUINT32]; - n1.xoffset = Array_nel; - gmove(&n1, &n2); - gmove(&n2, res); + n1.xoffset += Array_nel; + gmove(&n1, res); regfree(&n1); - regfree(&n2); break; } fatal("cgen: OLEN: unknown type %lT", nl->type); @@ -594,9 +590,10 @@ agen(Node *n, Node *res) gmove(&n1, &n3); } - nodconst(&n2, types[tptr], v*w); - gins(optoas(OADD, types[tptr]), &n2, &n3); - + if (v*w != 0) { + nodconst(&n2, types[tptr], v*w); + gins(optoas(OADD, types[tptr]), &n2, &n3); + } gmove(&n3, res); regfree(&n3); break; @@ -729,7 +726,27 @@ void igen(Node *n, Node *a, Node *res) { Node n1; - + Type *fp; + Iter flist; + + switch(n->op) { + case ONAME: + if((n->class&PHEAP) || n->class == PPARAMREF) + break; + *a = *n; + return; + + case OCALLFUNC: + fp = structfirst(&flist, getoutarg(n->left->type)); + cgen_call(n, 0); + memset(a, 0, sizeof *a); + a->op = OINDREG; + a->val.u.reg = D_SP; + a->addable = 1; + a->xoffset = fp->width; + a->type = n->type; + return; + } // release register for now, to avoid // confusing tempname. if(res != N && res->op == OREGISTER) @@ -919,6 +936,7 @@ bgen(Node *n, int true, Prog *to) n2 = n1; n2.op = OINDREG; n2.xoffset = Array_array; + n2.type = types[tptr]; nodconst(&tmp, types[tptr], 0); gins(optoas(OCMP, types[tptr]), &n2, &tmp); patch(gbranch(a, types[tptr]), to); diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 920725c3e..223152536 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -915,7 +915,7 @@ cgen_inline(Node *n, Node *res) Node nodes[5]; Node n1, n2, nres, ntemp; vlong v; - int i, narg; + int i, narg, nochk; if(n->op != OCALLFUNC) goto no; @@ -953,6 +953,7 @@ slicearray: // len = hb[3] - lb[2] (destroys hb) n2 = *res; n2.xoffset += Array_nel; + n2.type = types[TUINT32]; if(smallintconst(&nodes[3]) && smallintconst(&nodes[2])) { v = mpgetfix(nodes[3].val.u.xval) - @@ -971,6 +972,7 @@ slicearray: // cap = nel[1] - lb[2] (destroys nel) n2 = *res; n2.xoffset += Array_cap; + n2.type = types[TUINT32]; if(smallintconst(&nodes[1]) && smallintconst(&nodes[2])) { v = mpgetfix(nodes[1].val.u.xval) - @@ -999,6 +1001,7 @@ slicearray: // ary = old[0] + (lb[2] * width[4]) (destroys old) n2 = *res; n2.xoffset += Array_array; + n2.type = types[tptr]; if(smallintconst(&nodes[2]) && smallintconst(&nodes[4])) { v = mpgetfix(nodes[2].val.u.xval) * @@ -1026,6 +1029,7 @@ slicearray: sliceslice: if(!fix64(n->list, narg)) goto no; + nochk = n->etype; // skip bounds checking ntemp.op = OXXX; if(!sleasy(n->list->n->right)) { Node *n0; @@ -1055,11 +1059,13 @@ sliceslice: n2 = nodes[0]; n2.xoffset += Array_nel; n2.type = types[TUINT32]; - cmpandthrow(&nodes[1], &n2); + if(!nochk) + cmpandthrow(&nodes[1], &n2); // ret.nel = old.nel[0]-lb[1]; n2 = nodes[0]; n2.xoffset += Array_nel; + n2.type = types[TUINT32]; regalloc(&n1, types[TUINT32], N); gins(optoas(OAS, types[TUINT32]), &n2, &n1); @@ -1068,22 +1074,25 @@ sliceslice: n2 = nres; n2.xoffset += Array_nel; + n2.type = types[TUINT32]; gins(optoas(OAS, types[TUINT32]), &n1, &n2); regfree(&n1); } else { // old[lb:hb] - // if(hb[2] > old.cap[0]) goto throw; n2 = nodes[0]; n2.xoffset += Array_cap; n2.type = types[TUINT32]; - cmpandthrow(&nodes[2], &n2); - - // if(lb[1] > hb[2]) goto throw; - cmpandthrow(&nodes[1], &nodes[2]); + if (!nochk) { + // if(hb[2] > old.cap[0]) goto throw; + cmpandthrow(&nodes[2], &n2); + // if(lb[1] > hb[2]) goto throw; + cmpandthrow(&nodes[1], &nodes[2]); + } // ret.len = hb[2]-lb[1]; (destroys hb[2]) n2 = nres; n2.xoffset += Array_nel; - + n2.type = types[TUINT32]; + if(smallintconst(&nodes[2]) && smallintconst(&nodes[1])) { v = mpgetfix(nodes[2].val.u.xval) - mpgetfix(nodes[1].val.u.xval); @@ -1102,6 +1111,7 @@ sliceslice: // ret.cap = old.cap[0]-lb[1]; (uses hb[2]) n2 = nodes[0]; n2.xoffset += Array_cap; + n2.type = types[TUINT32]; regalloc(&n1, types[TUINT32], &nodes[2]); gins(optoas(OAS, types[TUINT32]), &n2, &n1); @@ -1110,12 +1120,14 @@ sliceslice: n2 = nres; n2.xoffset += Array_cap; + n2.type = types[TUINT32]; gins(optoas(OAS, types[TUINT32]), &n1, &n2); regfree(&n1); // ret.array = old.array[0]+lb[1]*width[3]; (uses lb[1]) n2 = nodes[0]; n2.xoffset += Array_array; + n2.type = types[tptr]; regalloc(&n1, types[tptr], &nodes[1]); if(smallintconst(&nodes[1]) && smallintconst(&nodes[3])) { @@ -1135,6 +1147,7 @@ sliceslice: n2 = nres; n2.xoffset += Array_array; + n2.type = types[tptr]; gins(optoas(OAS, types[tptr]), &n1, &n2); regfree(&n1); diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c index 8ed7e5564..5ad35fdce 100644 --- a/src/cmd/8g/gsubr.c +++ b/src/cmd/8g/gsubr.c @@ -698,7 +698,6 @@ ginit(void) reg[i] = 1; for(i=D_AL; i<=D_DI; i++) reg[i] = 0; - for(i=0; i<nelem(resvd); i++) reg[resvd[i]]++; } @@ -789,6 +788,8 @@ err: return; out: + if (i == D_SP) + print("alloc SP\n"); if(reg[i] == 0) { regpc[i] = (ulong)__builtin_return_address(0); if(i == D_AX || i == D_CX || i == D_DX || i == D_SP) { @@ -804,10 +805,14 @@ void regfree(Node *n) { int i; - + + if(n->op == ONAME) + return; if(n->op != OREGISTER && n->op != OINDREG) fatal("regfree: not a register"); i = n->val.u.reg; + if(i == D_SP) + return; if(i < 0 || i >= sizeof(reg)) fatal("regfree: reg out of range"); if(reg[i] <= 0) @@ -1129,6 +1134,9 @@ gmove(Node *f, Node *t) case CASE(TINT8, TUINT8): case CASE(TUINT8, TINT8): case CASE(TUINT8, TUINT8): + a = AMOVB; + break; + case CASE(TINT16, TINT8): // truncate case CASE(TUINT16, TINT8): case CASE(TINT32, TINT8): @@ -1138,7 +1146,7 @@ gmove(Node *f, Node *t) case CASE(TINT32, TUINT8): case CASE(TUINT32, TUINT8): a = AMOVB; - break; + goto rsrc; case CASE(TINT64, TINT8): // truncate low word case CASE(TUINT64, TINT8): @@ -1146,7 +1154,7 @@ gmove(Node *f, Node *t) case CASE(TUINT64, TUINT8): split64(f, &flo, &fhi); nodreg(&r1, t->type, D_AX); - gins(AMOVB, &flo, &r1); + gmove(&flo, &r1); gins(AMOVB, &r1, t); splitclean(); return; @@ -1155,12 +1163,15 @@ gmove(Node *f, Node *t) case CASE(TINT16, TUINT16): case CASE(TUINT16, TINT16): case CASE(TUINT16, TUINT16): + a = AMOVW; + break; + case CASE(TINT32, TINT16): // truncate case CASE(TUINT32, TINT16): case CASE(TINT32, TUINT16): case CASE(TUINT32, TUINT16): a = AMOVW; - break; + goto rsrc; case CASE(TINT64, TINT16): // truncate low word case CASE(TUINT64, TINT16): @@ -1168,7 +1179,7 @@ gmove(Node *f, Node *t) case CASE(TUINT64, TUINT16): split64(f, &flo, &fhi); nodreg(&r1, t->type, D_AX); - gins(AMOVW, &flo, &r1); + gmove(&flo, &r1); gins(AMOVW, &r1, t); splitclean(); return; @@ -1186,7 +1197,7 @@ gmove(Node *f, Node *t) case CASE(TUINT64, TUINT32): split64(f, &flo, &fhi); nodreg(&r1, t->type, D_AX); - gins(AMOVL, &flo, &r1); + gmove(&flo, &r1); gins(AMOVL, &r1, t); splitclean(); return; @@ -1340,14 +1351,14 @@ gmove(Node *f, Node *t) case TUINT8: gins(ATESTL, ncon(0xffffff00), &t1); p1 = gbranch(AJEQ, T); - gins(AMOVB, ncon(0), &t1); + gins(AMOVL, ncon(0), &t1); patch(p1, pc); gmove(&t1, t); break; case TUINT16: gins(ATESTL, ncon(0xffff0000), &t1); p1 = gbranch(AJEQ, T); - gins(AMOVW, ncon(0), &t1); + gins(AMOVL, ncon(0), &t1); patch(p1, pc); gmove(&t1, t); break; @@ -1418,11 +1429,11 @@ gmove(Node *f, Node *t) split64(t, &tlo, &thi); gins(AXORL, ncon(0x80000000), &thi); // + 2^63 patch(p3, pc); - patch(p1, pc); splitclean(); - // restore rounding mode gins(AFLDCW, &t1, N); + + patch(p1, pc); return; /* @@ -1571,6 +1582,14 @@ gmove(Node *f, Node *t) gins(a, f, t); return; +rsrc: + // requires register source + regalloc(&r1, f->type, t); + gmove(f, &r1); + gins(a, &r1, t); + regfree(&r1); + return; + rdst: // requires register destination regalloc(&r1, t->type, t); @@ -1623,6 +1642,7 @@ gins(int as, Node *f, Node *t) { Prog *p; Addr af, at; + int w; if(as == AFMOVF && f && f->op == OREGISTER && t && t->op == OREGISTER) fatal("gins MOVF reg, reg"); @@ -1648,6 +1668,26 @@ gins(int as, Node *f, Node *t) p->to = at; if(debug['g']) print("%P\n", p); + + w = 0; + switch(as) { + case AMOVB: + w = 1; + break; + case AMOVW: + w = 2; + break; + case AMOVL: + w = 4; + break; + } + + if(1 && w != 0 && f != N && (af.width > w || at.width > w)) { + dump("bad width from:", f); + dump("bad width to:", t); + fatal("bad width: %P (%d, %d)\n", p, af.width, at.width); + } + return p; } @@ -1799,8 +1839,9 @@ naddr(Node *n, Addr *a, int canemitcode) naddr(n->left, a, canemitcode); if(a->type == D_CONST && a->offset == 0) break; // len(nil) - a->etype = TUINT; + a->etype = TUINT32; a->offset += Array_nel; + a->width = 4; if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) checkoffset(a, canemitcode); break; @@ -1810,8 +1851,9 @@ naddr(Node *n, Addr *a, int canemitcode) naddr(n->left, a, canemitcode); if(a->type == D_CONST && a->offset == 0) break; // cap(nil) - a->etype = TUINT; + a->etype = TUINT32; a->offset += Array_cap; + a->width = 4; if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) checkoffset(a, canemitcode); break; diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c index f28b8d904..7de7753a2 100644 --- a/src/cmd/8l/asm.c +++ b/src/cmd/8l/asm.c @@ -104,6 +104,9 @@ needlib(char *name) char *p; Sym *s; + if(*name == '\0') + return 0; + /* reuse hash code in symbol table */ p = smprint(".dynlib.%s", name); s = lookup(p, 0); @@ -532,6 +535,8 @@ doelf(void) elfstr[ElfStrGosymcounts] = addstring(shstrtab, ".gosymcounts"); elfstr[ElfStrGosymtab] = addstring(shstrtab, ".gosymtab"); elfstr[ElfStrGopclntab] = addstring(shstrtab, ".gopclntab"); + elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab"); + elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab"); dwarfaddshstrings(shstrtab); } elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab"); @@ -658,7 +663,7 @@ asmb(void) { int32 v, magic; int a, dynsym; - uint32 symo, startva, machlink; + uint32 symo, startva, machlink, elfsymo, elfstro, elfsymsize; ElfEhdr *eh; ElfPhdr *ph, *pph; ElfShdr *sh; @@ -670,6 +675,10 @@ asmb(void) Bprint(&bso, "%5.2f asmb\n", cputime()); Bflush(&bso); + elfsymsize = 0; + elfstro = 0; + elfsymo = 0; + sect = segtext.sect; seek(cout, sect->vaddr - segtext.vaddr + segtext.fileoff, 0); codeblk(sect->vaddr, sect->len); @@ -736,32 +745,48 @@ asmb(void) symo = rnd(symo, INITRND); break; case Hwindows: - // TODO(brainman): not sure what symo meant to be, but it is not used for Windows PE for now anyway symo = rnd(HEADR+segtext.filelen, PEFILEALIGN)+segdata.filelen; symo = rnd(symo, PEFILEALIGN); break; } - if(!debug['s']) { - seek(cout, symo, 0); - - if(HEADTYPE == Hplan9x32) { - asmplan9sym(); + switch(HEADTYPE) { + default: + if(iself) { + if(debug['v']) + Bprint(&bso, "%5.2f elfsym\n", cputime()); + elfsymo = symo+8+symsize+lcsize; + seek(cout, elfsymo, 0); + asmelfsym32(); 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 != Hwindows) { + elfstro = seek(cout, 0, 1); + elfsymsize = elfstro - elfsymo; + ewrite(cout, elfstrdat, elfstrsize); + if(debug['v']) Bprint(&bso, "%5.2f dwarf\n", cputime()); dwarfemitdebugsections(); } + break; + case Hplan9x32: + seek(cout, symo, 0); + asmplan9sym(); + cflush(); + + sym = lookup("pclntab", 0); + if(sym != nil) { + lcsize = sym->np; + for(i=0; i < lcsize; i++) + cput(sym->p[i]); + + cflush(); + } + break; + case Hwindows: + seek(cout, symo, 0); + if(debug['v']) + Bprint(&bso, "%5.2f dwarf\n", cputime()); + dwarfemitdebugsections(); + break; } } if(debug['v']) @@ -1082,6 +1107,20 @@ asmb(void) sh->addralign = 1; shsym(sh, lookup("pclntab", 0)); + sh = newElfShdr(elfstr[ElfStrSymtab]); + sh->type = SHT_SYMTAB; + sh->off = elfsymo; + sh->size = elfsymsize; + sh->addralign = 4; + sh->entsize = 16; + sh->link = eh->shnum; // link to strtab + + sh = newElfShdr(elfstr[ElfStrStrtab]); + sh->type = SHT_STRTAB; + sh->off = elfstro; + sh->size = elfstrsize; + sh->addralign = 1; + dwarfaddelfheaders(); } diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c index 2a38f7ef0..f84a30f39 100644 --- a/src/cmd/8l/obj.c +++ b/src/cmd/8l/obj.c @@ -188,7 +188,7 @@ main(int argc, char *argv[]) if(INITDAT == -1) INITDAT = 0; if(INITRND == -1) - INITRND = 1; + INITRND = 4096; break; case Hmsdoscom: /* MS-DOS .COM */ HEADR = 0; diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c index 28589b66a..72ae043d6 100644 --- a/src/cmd/8l/pass.c +++ b/src/cmd/8l/pass.c @@ -32,23 +32,10 @@ #include "l.h" #include "../ld/lib.h" +#include "../../pkg/runtime/stack.h" static void xfol(Prog*, Prog**); -// see ../../pkg/runtime/proc.c:/StackGuard -enum -{ -#ifdef __WINDOWS__ - // use larger stacks to compensate for larger stack guard, - // needed for exception handling. - StackSmall = 256, - StackBig = 8192, -#else - StackSmall = 128, - StackBig = 4096, -#endif -}; - Prog* brchain(Prog *p) { diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c index dba8ff634..71cc89bf0 100644 --- a/src/cmd/cc/lex.c +++ b/src/cmd/cc/lex.c @@ -88,7 +88,7 @@ void main(int argc, char *argv[]) { char **defs, *p; - int nproc, nout, i, c, ndef; + int c, ndef; ensuresymb(NSYMB); memset(debug, 0, sizeof(debug)); @@ -142,51 +142,10 @@ main(int argc, char *argv[]) print("usage: %cc [-options] files\n", thechar); errorexit(); } - if(argc > 1 && systemtype(Windows)){ - print("can't compile multiple files on windows\n"); + if(argc > 1){ + print("can't compile multiple files\n"); errorexit(); } - if(argc > 1 && !systemtype(Windows)) { - nproc = 1; - /* - * if we're writing acid to standard output, don't compile - * concurrently, to avoid interleaving output. - */ - if(((!debug['a'] && !debug['q'] && !debug['Q']) || debug['n']) && - (p = getenv("NPROC")) != nil) - nproc = atol(p); /* */ - c = 0; - nout = 0; - for(;;) { - Waitmsg *w; - - while(nout < nproc && argc > 0) { - i = fork(); - if(i < 0) { - print("cannot create a process\n"); - errorexit(); - } - if(i == 0) { - fprint(2, "%s:\n", *argv); - if (compile(*argv, defs, ndef)) - errorexit(); - exits(0); - } - nout++; - argc--; - argv++; - } - w = wait(); - if(w == nil) { - if(c) - errorexit(); - exits(0); - } - if(w->msg[0]) - c++; - nout--; - } - } if(argc == 0) c = compile("stdin", defs, ndef); @@ -201,7 +160,7 @@ main(int argc, char *argv[]) int compile(char *file, char **defs, int ndef) { - char *ofile, incfile[20]; + char *ofile; char *p, **av, opt[256]; int i, c, fd[2]; static int first = 1; @@ -236,15 +195,6 @@ compile(char *file, char **defs, int ndef) outfile = "/dev/null"; } - if(p = getenv("INCLUDE")) { - setinclude(p); - } else { - if(systemtype(Plan9)) { - sprint(incfile, "/%s/include", thestring); - setinclude(strdup(incfile)); - setinclude("/sys/include"); - } - } if (first) Binit(&diagbuf, 1, OWRITE); /* diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index ae5ca2c7d..ac6561345 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -604,7 +604,7 @@ const gccTmp = "_obj/_cgo_.o" // gccCmd returns the gcc command line to use for compiling // the input. func (p *Package) gccCmd() []string { - return []string{ + c := []string{ p.gccName(), p.gccMachine(), "-Wall", // many warnings @@ -614,15 +614,17 @@ func (p *Package) gccCmd() []string { "-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise "-c", // do not link "-xc", // input language is C - "-", // read input from standard input } + c = append(c, p.GccOptions...) + c = append(c, "-") //read input from standard input + return c } // gccDebug runs gcc -gdwarf-2 over the C program stdin and // returns the corresponding DWARF data and any messages // printed to standard error. func (p *Package) gccDebug(stdin []byte) *dwarf.Data { - runGcc(stdin, append(p.gccCmd(), p.GccOptions...)) + runGcc(stdin, p.gccCmd()) // Try to parse f as ELF and Mach-O and hope one works. var f interface { @@ -649,8 +651,8 @@ func (p *Package) gccDebug(stdin []byte) *dwarf.Data { // #defines that gcc encountered while processing the input // and its included files. func (p *Package) gccDefines(stdin []byte) string { - base := []string{p.gccName(), p.gccMachine(), "-E", "-dM", "-xc", "-"} - stdout, _ := runGcc(stdin, append(base, p.GccOptions...)) + base := []string{p.gccName(), p.gccMachine(), "-E", "-dM", "-xc"} + stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) return stdout } @@ -659,7 +661,7 @@ func (p *Package) gccDefines(stdin []byte) string { // gcc to fail. func (p *Package) gccErrors(stdin []byte) string { // TODO(rsc): require failure - args := append(p.gccCmd(), p.GccOptions...) + args := p.gccCmd() if *debugGcc { fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " ")) os.Stderr.Write(stdin) diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index bc031cc58..2ce4e9752 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -331,7 +331,11 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { fmt.Fprintf(fgcc, "\tint e;\n") // assuming 32 bit (see comment above structType) fmt.Fprintf(fgcc, "\terrno = 0;\n") } - fmt.Fprintf(fgcc, "\t%s *a = v;\n", ctype) + // We're trying to write a gcc struct that matches 6c/8c/5c's layout. + // Use packed attribute to force no padding in this struct in case + // gcc has different packing requirements. For example, + // on 386 Windows, gcc wants to 8-align int64s, but 8c does not. + fmt.Fprintf(fgcc, "\t%s __attribute__((__packed__)) *a = v;\n", ctype) fmt.Fprintf(fgcc, "\t") if t := n.FuncType.Result; t != nil { fmt.Fprintf(fgcc, "a->r = ") @@ -370,7 +374,9 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) { fn := exp.Func // Construct a gcc struct matching the 6c argument and - // result frame. + // result frame. The gcc struct will be compiled with + // __attribute__((packed)) so all padding must be accounted + // for explicitly. ctype := "struct {\n" off := int64(0) npad := 0 @@ -458,7 +464,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) { fmt.Fprintf(fgcc, "extern _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName) fmt.Fprintf(fgcc, "\n%s\n", s) fmt.Fprintf(fgcc, "{\n") - fmt.Fprintf(fgcc, "\t%s a;\n", ctype) + fmt.Fprintf(fgcc, "\t%s __attribute__((packed)) a;\n", ctype) if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) { fmt.Fprintf(fgcc, "\t%s r;\n", gccResult) } diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot index bdbca7f78..c9bf501d1 100644 --- a/src/cmd/gc/builtin.c.boot +++ b/src/cmd/gc/builtin.c.boot @@ -1,5 +1,6 @@ char *runtimeimport = "package runtime\n" + "import runtime \"runtime\"\n" "func \"\".new (? int32) *any\n" "func \"\".panicindex ()\n" "func \"\".panicslice ()\n" @@ -21,7 +22,6 @@ char *runtimeimport = "func \"\".printsp ()\n" "func \"\".goprintf ()\n" "func \"\".concatstring ()\n" - "func \"\".append ()\n" "func \"\".appendslice (typ *uint8, x any, y []any) any\n" "func \"\".cmpstring (? string, ? string) int\n" "func \"\".slicestring (? string, ? int, ? int) string\n" @@ -81,6 +81,7 @@ char *runtimeimport = "func \"\".selectgo (sel *uint8)\n" "func \"\".block ()\n" "func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n" + "func \"\".growslice (typ *uint8, old []any, cap int64) []any\n" "func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n" "func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n" "func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n" @@ -98,6 +99,7 @@ char *runtimeimport = "$$\n"; char *unsafeimport = "package unsafe\n" + "import runtime \"runtime\"\n" "type \"\".Pointer uintptr\n" "func \"\".Offsetof (? any) int\n" "func \"\".Sizeof (? any) int\n" diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index f58b76789..359881e11 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -225,6 +225,7 @@ struct Node Type* realtype; // as determined by typecheck NodeList* list; NodeList* rlist; + Node* orig; // original form, for printing // for-body NodeList* ninit; diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go index 35d11eca9..00fc720b8 100644 --- a/src/cmd/gc/runtime.go +++ b/src/cmd/gc/runtime.go @@ -110,6 +110,7 @@ func selectgo(sel *byte) func block() func makeslice(typ *byte, nel int64, cap int64) (ary []any) +func growslice(typ *byte, old []any, n int64) (ary []any) func sliceslice1(old []any, lb uint64, width uint64) (ary []any) func sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any) func slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) (ary []any) diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index bb2505694..326a5ba74 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -1073,6 +1073,9 @@ Jconv(Fmt *fp) if(n->implicit != 0) fmtprint(fp, " implicit(%d)", n->implicit); + if(n->pun != 0) + fmtprint(fp, " pun(%d)", n->pun); + return 0; } @@ -1141,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t) Type *t1; Sym *s; - if(debug['r']) { + if(0 && debug['r']) { debug['r'] = 0; fmtprint(fp, "%T (orig=%T)", t, t->orig); debug['r'] = 1; @@ -1454,6 +1457,8 @@ Nconv(Fmt *fp) } if(fp->flags & FmtSharp) { + if(n->orig != N) + n = n->orig; exprfmt(fp, n, 0); goto out; } @@ -3107,7 +3112,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) Type *tpad; int isddd; - if(debug['r']) + if(0 && debug['r']) print("genwrapper rcvrtype=%T method=%T newnam=%S\n", rcvr, method, newnam); @@ -3161,7 +3166,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) fn->nbody = list1(n); } - if(debug['r']) + if(0 && debug['r']) dumplist("genwrapper body", fn->nbody); funcbody(fn); @@ -3256,8 +3261,9 @@ implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr) // the method does not exist for value types. rcvr = getthisx(tm->type)->type->type; if(isptr[rcvr->etype] && !isptr[t0->etype] && !followptr && !isifacemethod(tm->type)) { - if(debug['r']) + if(0 && debug['r']) yyerror("interface pointer mismatch"); + *m = im; *samename = nil; *ptr = 1; diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c index 6e8436c3c..c2968c44b 100644 --- a/src/cmd/gc/swt.c +++ b/src/cmd/gc/swt.c @@ -867,8 +867,11 @@ typecheckswitch(Node *n) case Etype: // type switch if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) ; - else if(ll->n->op != OTYPE && ll->n->type != T) + else if(ll->n->op != OTYPE && ll->n->type != T) { yyerror("%#N is not a type", ll->n); + // reset to original type + ll->n = n->ntest->right; + } break; } } diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index c48bf7a29..9aaf3e6ef 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -894,12 +894,20 @@ reswitch: // might be constant switch(t->etype) { case TSTRING: - if(isconst(l, CTSTR)) - nodconst(n, types[TINT], l->val.u.sval->len); + if(isconst(l, CTSTR)) { + r = nod(OXXX, N, N); + nodconst(r, types[TINT], l->val.u.sval->len); + r->orig = n; + n = r; + } break; case TARRAY: - if(t->bound >= 0 && l->op == ONAME) - nodconst(n, types[TINT], t->bound); + if(t->bound >= 0 && l->op == ONAME) { + r = nod(OXXX, N, N); + nodconst(r, types[TINT], t->bound); + r->orig = n; + n = r; + } break; } n->type = types[TINT]; @@ -1357,7 +1365,10 @@ ret: goto error; } if((top & Etop) && !(top & (Ecall|Erv|Etype)) && !(ok & Etop)) { - yyerror("%#N not used", n); + if(n->diag == 0) { + yyerror("%#N not used", n); + n->diag = 1; + } goto error; } diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c index 33f375631..540994ddd 100644 --- a/src/cmd/gc/unsafe.c +++ b/src/cmd/gc/unsafe.c @@ -41,6 +41,7 @@ unsafenmagic(Node *nn) tr = r->type; if(tr == T) goto bad; + dowidth(tr); v = tr->width; goto yes; } diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 278eef414..b3b400556 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -18,12 +18,13 @@ static NodeList* paramstoheap(Type **argin, int out); static NodeList* reorder1(NodeList*); static NodeList* reorder3(NodeList*); static Node* addstr(Node*, NodeList**); +static Node* appendslice(Node*, NodeList**); static Node* append(Node*, NodeList**); static NodeList* walkdefstack; // can this code branch reach the end -// without an undcontitional RETURN +// without an unconditional RETURN // this is hard, so it is conservative static int walkret(NodeList *l) @@ -805,18 +806,17 @@ walkexpr(Node **np, NodeList **init) n->ninit = nil; walkexpr(&n->left, init); n->left = safeexpr(n->left, init); + if(oaslit(n, init)) goto ret; + walkexpr(&n->right, init); - l = n->left; - r = n->right; - if(l == N || r == N) - goto ret; - r = ascompatee1(n->op, l, r, init); - if(r != N) { + if(n->left != N && n->right != N) { + r = convas(nod(OAS, n->left, n->right), init); r->dodata = n->dodata; n = r; } + goto ret; case OAS2: @@ -1134,6 +1134,7 @@ walkexpr(Node **np, NodeList **init) case OINDEXMAP: if(n->etype == 1) goto ret; + t = n->left->type; n = mkcall1(mapfn("mapaccess1", t), t->type, init, n->left, n->right); goto ret; @@ -1188,6 +1189,7 @@ walkexpr(Node **np, NodeList **init) // sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any) // sliceslice1(old []any, lb uint64, width uint64) (ary []any) t = n->type; + et = n->etype; if(n->right->left == N) l = nodintconst(0); else @@ -1210,6 +1212,7 @@ walkexpr(Node **np, NodeList **init) l, nodintconst(t->type->width)); } + n->etype = et; // preserve no-typecheck flag from OSLICE to the slice* call. goto ret; slicearray: @@ -1332,7 +1335,10 @@ walkexpr(Node **np, NodeList **init) goto ret; case OAPPEND: - n = append(n, init); + if(n->isddd) + n = appendslice(n, init); + else + n = append(n, init); goto ret; case OCOPY: @@ -1953,23 +1959,18 @@ callnew(Type *t) static Node* convas(Node *n, NodeList **init) { - Node *l, *r; Type *lt, *rt; if(n->op != OAS) fatal("convas: not OAS %O", n->op); - n->typecheck = 1; - lt = T; - rt = T; + n->typecheck = 1; - l = n->left; - r = n->right; - if(l == N || r == N) + if(n->left == N || n->right == N) goto out; - lt = l->type; - rt = r->type; + lt = n->left->type; + rt = n->right->type; if(lt == T || rt == T) goto out; @@ -1987,7 +1988,7 @@ convas(Node *n, NodeList **init) if(eqtype(lt, rt)) goto out; - n->right = assignconv(r, lt, "assignment"); + n->right = assignconv(n->right, lt, "assignment"); walkexpr(&n->right, init); out: @@ -2365,42 +2366,85 @@ addstr(Node *n, NodeList **init) } static Node* -append(Node *n, NodeList **init) +appendslice(Node *n, NodeList **init) { - int i, j; - Node *f, *r; - NodeList *in, *args; + Node *f; - if(n->isddd) { - f = syslook("appendslice", 1); - argtype(f, n->type); - argtype(f, n->type->type); - argtype(f, n->type); - r = mkcall1(f, n->type, init, typename(n->type), n->list->n, n->list->next->n); - return r; + f = syslook("appendslice", 1); + argtype(f, n->type); + argtype(f, n->type->type); + argtype(f, n->type); + return mkcall1(f, n->type, init, typename(n->type), n->list->n, n->list->next->n); +} + +// expand append(src, a [, b]* ) to +// +// init { +// s := src +// const argc = len(args) - 1 +// if cap(s) - len(s) < argc { +// s = growslice(s, argc) +// } +// n := len(s) +// s = s[:n+argc] +// s[n] = a +// s[n+1] = b +// ... +// } +// s +static Node* +append(Node *n, NodeList **init) +{ + NodeList *l, *a; + Node *nsrc, *ns, *nn, *na, *nx, *fn; + int argc; + + walkexprlistsafe(n->list, init); + + nsrc = n->list->n; + argc = count(n->list) - 1; + if (argc < 1) { + return nsrc; } - j = count(n->list) - 1; - f = syslook("append", 1); - f->type = T; - f->ntype = nod(OTFUNC, N, N); - in = list1(nod(ODCLFIELD, N, typenod(ptrto(types[TUINT8])))); // type - in = list(in, nod(ODCLFIELD, N, typenod(types[TINT]))); // count - in = list(in, nod(ODCLFIELD, N, typenod(n->type))); // slice - for(i=0; i<j; i++) - in = list(in, nod(ODCLFIELD, N, typenod(n->type->type))); - f->ntype->list = in; - f->ntype->rlist = list1(nod(ODCLFIELD, N, typenod(n->type))); - - args = list1(typename(n->type)); - args = list(args, nodintconst(j)); - args = concat(args, n->list); - - r = nod(OCALL, f, N); - r->list = args; - typecheck(&r, Erv); - walkexpr(&r, init); - r->type = n->type; + l = nil; - return r; + ns = nod(OXXX, N, N); // var s + tempname(ns, nsrc->type); + l = list(l, nod(OAS, ns, nsrc)); // s = src + + na = nodintconst(argc); // const argc + nx = nod(OIF, N, N); // if cap(s) - len(s) < argc + nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na); + + fn = syslook("growslice", 1); // growslice(<type>, old []T, n int64) (ret []T) + argtype(fn, ns->type->type); // 1 old []any + argtype(fn, ns->type->type); // 2 ret []any + + nx->nbody = list1(nod(OAS, ns, mkcall1(fn, ns->type, &nx->ninit, + typename(ns->type), + ns, + conv(na, types[TINT64])))); + l = list(l, nx); + + nn = nod(OXXX, N, N); // var n + tempname(nn, types[TINT]); + l = list(l, nod(OAS, nn, nod(OLEN, ns, N))); // n = len(s) + + nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na))); // ...s[:n+argc] + nx->etype = 1; // disable bounds check + l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc] + + for (a = n->list->next; a != nil; a = a->next) { + nx = nod(OINDEX, ns, nn); // s[n] ... + nx->etype = 1; // disable bounds check + l = list(l, nod(OAS, nx, a->n)); // s[n] = arg + if (a->next != nil) + l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))); // n = n + 1 + } + + typechecklist(l, Etop); + walkstmtlist(l); + *init = concat(*init, l); + return ns; } diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go index f0006e750..26d436d72 100644 --- a/src/cmd/godoc/doc.go +++ b/src/cmd/godoc/doc.go @@ -47,6 +47,9 @@ The flags are: width of tabs in units of spaces -timestamps=true show timestamps with directory listings + -index + enable identifier and full text search index + (no search box is shown if -index is not set) -maxresults=10000 maximum number of full text search results shown (no full text index is built if maxresults <= 0) diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index b8e9dbc92..f97c764f9 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -64,9 +64,12 @@ var ( // layout control tabwidth = flag.Int("tabwidth", 4, "tab width") showTimestamps = flag.Bool("timestamps", true, "show timestamps with directory listings") - maxResults = flag.Int("maxresults", 10000, "maximum number of full text search results shown") templateDir = flag.String("templates", "", "directory containing alternate template files") + // search index + indexEnabled = flag.Bool("index", false, "enable search index") + maxResults = flag.Int("maxresults", 10000, "maximum number of full text search results shown") + // file system mapping fsMap Mapping // user-defined mapping fsTree RWValue // *Directory tree of packages, updated with each sync @@ -687,17 +690,19 @@ func readTemplates() { func servePage(w http.ResponseWriter, title, subtitle, query string, content []byte) { d := struct { - Title string - Subtitle string - PkgRoots []string - Query string - Version string - Menu []byte - Content []byte + Title string + Subtitle string + PkgRoots []string + SearchBox bool + Query string + Version string + Menu []byte + Content []byte }{ title, subtitle, fsMap.PrefixList(), + *indexEnabled, query, runtime.Version(), nil, @@ -1174,11 +1179,15 @@ func lookup(query string) (result SearchResult) { } // is the result accurate? - if _, ts := fsModified.get(); timestamp < ts { - // The index is older than the latest file system change - // under godoc's observation. Indexing may be in progress - // or start shortly (see indexer()). - result.Alert = "Indexing in progress: result may be inaccurate" + if *indexEnabled { + if _, ts := fsModified.get(); timestamp < ts { + // The index is older than the latest file system change + // under godoc's observation. Indexing may be in progress + // or start shortly (see indexer()). + result.Alert = "Indexing in progress: result may be inaccurate" + } + } else { + result.Alert = "Search index disabled: no results available" } return diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go index e426626b3..967ea8727 100644 --- a/src/cmd/godoc/main.go +++ b/src/cmd/godoc/main.go @@ -176,7 +176,7 @@ func remoteSearch(query string) (res *http.Response, err os.Error) { // remote search for _, addr := range addrs { url := "http://" + addr + search - res, _, err = http.Get(url) + res, err = http.Get(url) if err == nil && res.StatusCode == http.StatusOK { break } @@ -246,8 +246,13 @@ func main() { log.Printf("address = %s", *httpAddr) log.Printf("goroot = %s", *goroot) log.Printf("tabwidth = %d", *tabwidth) - if *maxResults > 0 { - log.Printf("maxresults = %d (full text index enabled)", *maxResults) + switch { + case !*indexEnabled: + log.Print("search index disabled") + case *maxResults > 0: + log.Printf("full text index enabled (maxresults = %d)", *maxResults) + default: + log.Print("identifier search index enabled") } if !fsMap.IsEmpty() { log.Print("user-defined mapping:") @@ -284,7 +289,9 @@ func main() { } // Start indexing goroutine. - go indexer() + if *indexEnabled { + go indexer() + } // Start http server. if err := http.ListenAndServe(*httpAddr, handler); err != nil { diff --git a/src/cmd/gofix/Makefile b/src/cmd/gofix/Makefile index 12f09b4e4..d19de5c4f 100644 --- a/src/cmd/gofix/Makefile +++ b/src/cmd/gofix/Makefile @@ -10,6 +10,7 @@ GOFILES=\ netdial.go\ main.go\ osopen.go\ + httpfinalurl.go\ httpserver.go\ procattr.go\ reflect.go\ diff --git a/src/cmd/gofix/httpfinalurl.go b/src/cmd/gofix/httpfinalurl.go new file mode 100644 index 000000000..53642b22f --- /dev/null +++ b/src/cmd/gofix/httpfinalurl.go @@ -0,0 +1,56 @@ +// 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. + +package main + +import ( + "go/ast" +) + +var httpFinalURLFix = fix{ + "httpfinalurl", + httpfinalurl, + `Adapt http Get calls to not have a finalURL result parameter. + + http://codereview.appspot.com/4535056/ +`, +} + +func init() { + register(httpFinalURLFix) +} + +func httpfinalurl(f *ast.File) bool { + if !imports(f, "http") { + return false + } + + fixed := false + walk(f, func(n interface{}) { + // Fix up calls to http.Get. + // + // If they have blank identifiers, remove them: + // resp, _, err := http.Get(url) + // -> resp, err := http.Get(url) + // + // But if they're using the finalURL parameter, warn: + // resp, finalURL, err := http.Get(url) + as, ok := n.(*ast.AssignStmt) + if !ok || len(as.Lhs) != 3 || len(as.Rhs) != 1 { + return + } + + if !isCall(as.Rhs[0], "http", "Get") { + return + } + + if isBlank(as.Lhs[1]) { + as.Lhs = []ast.Expr{as.Lhs[0], as.Lhs[2]} + fixed = true + } else { + warn(as.Pos(), "call to http.Get records final URL") + } + }) + return fixed +} diff --git a/src/cmd/gofix/httpfinalurl_test.go b/src/cmd/gofix/httpfinalurl_test.go new file mode 100644 index 000000000..9e7d6242d --- /dev/null +++ b/src/cmd/gofix/httpfinalurl_test.go @@ -0,0 +1,37 @@ +// 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. + +package main + +func init() { + addTestCases(httpfinalurlTests) +} + +var httpfinalurlTests = []testCase{ + { + Name: "finalurl.0", + In: `package main + +import ( + "http" +) + +func f() { + resp, _, err := http.Get("http://www.google.com/") + _, _ = resp, err +} +`, + Out: `package main + +import ( + "http" +) + +func f() { + resp, err := http.Get("http://www.google.com/") + _, _ = resp, err +} +`, + }, +} diff --git a/src/cmd/gofmt/test.sh b/src/cmd/gofmt/test.sh index 99ec76932..f60ff9b32 100755 --- a/src/cmd/gofmt/test.sh +++ b/src/cmd/gofmt/test.sh @@ -42,7 +42,8 @@ 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 | bug322.go | bug324.go ) return ;; + bug302.go | bug306.go | bug322.go | bug324.go | bug335.go | \ + bug340.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/gotest/gotest.go b/src/cmd/gotest/gotest.go index a7ba8dd11..8c81baf97 100644 --- a/src/cmd/gotest/gotest.go +++ b/src/cmd/gotest/gotest.go @@ -52,7 +52,7 @@ var ( xFlag bool ) -// elapsed returns time elapsed since gotest started. +// elapsed returns the number of seconds since gotest started. func elapsed() float64 { return float64(time.Nanoseconds()-start) / 1e9 } @@ -182,7 +182,7 @@ func getTestFileNames() { } } -// parseFiles parses the files and remembers the packages we find. +// parseFiles parses the files and remembers the packages we find. func parseFiles() { fileSet := token.NewFileSet() for _, f := range files { @@ -285,6 +285,7 @@ func doRun(argv []string, returnStdout bool) string { } cmd += `"` + v + `"` } + command = "sh" argv = []string{"sh", "-c", cmd} } var err os.Error diff --git a/src/cmd/gotype/gotype.go b/src/cmd/gotype/gotype.go index 568467322..b6a23ae5f 100644 --- a/src/cmd/gotype/gotype.go +++ b/src/cmd/gotype/gotype.go @@ -178,8 +178,10 @@ func processPackage(fset *token.FileSet, files map[string]*ast.File) { report(err) return } - // TODO(gri): typecheck package - _ = pkg + _, err = types.Check(fset, pkg) + if err != nil { + report(err) + } } diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 0cb2b2138..3f3faade0 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -804,6 +804,10 @@ dodata(void) diag("%s: no size", s->name); t = 1; } + if(t >= PtrSize) + t = rnd(t, PtrSize); + else if(t > 2) + t = rnd(t, 4); if(t & 1) ; else if(t & 2) @@ -826,6 +830,10 @@ dodata(void) diag("unexpected symbol type %d", s->type); } t = s->size; + if(t >= PtrSize) + t = rnd(t, PtrSize); + else if(t > 2) + t = rnd(t, 4); if(t & 1) ; else if(t & 2) @@ -899,10 +907,8 @@ address(void) segdata.fileoff = va - segtext.vaddr + segtext.fileoff; if(HEADTYPE == Hwindows) segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN); - if(HEADTYPE == Hplan9x32) { - segdata.vaddr = va = rnd(va, 4096); + if(HEADTYPE == Hplan9x32) segdata.fileoff = segtext.fileoff + segtext.filelen; - } for(s=segdata.sect; s != nil; s=s->next) { s->vaddr = va; va += s->len; diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index 98b068008..ed11f5e5a 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -2562,7 +2562,6 @@ dwarfaddmachoheaders(void) void dwarfaddpeheaders(void) { - dwarfemitdebugsections(); newPEDWARFSection(".debug_abbrev", abbrevsize); newPEDWARFSection(".debug_line", linesize); newPEDWARFSection(".debug_frame", framesize); diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h index 08583cc8f..d1370d28b 100644 --- a/src/cmd/ld/elf.h +++ b/src/cmd/ld/elf.h @@ -978,6 +978,10 @@ ElfShdr* elfshbits(Section*); void elfsetstring(char*, int); void elfaddverneed(Sym*); +EXTERN int elfstrsize; +EXTERN char* elfstrdat; +EXTERN int elftextsh; + /* * Total amount of space to reserve at the start of the file * for Header, PHeaders, SHeaders, and interp. diff --git a/src/cmd/ld/go.c b/src/cmd/ld/go.c index e52c5cb34..a19fe460d 100644 --- a/src/cmd/ld/go.c +++ b/src/cmd/ld/go.c @@ -454,6 +454,7 @@ loaddynimport(char *file, char *pkg, char *p, int n) if(strcmp(name, "_") == 0 && strcmp(def, "_") == 0) { // allow #pragma dynimport _ _ "foo.so" // to force a link of foo.so. + havedynamic = 1; adddynlib(lib); continue; } @@ -468,6 +469,7 @@ loaddynimport(char *file, char *pkg, char *p, int n) s->dynimpname = def; s->dynimpvers = q; s->type = SDYNIMPORT; + havedynamic = 1; } } return; diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index 15219ba11..105d982e4 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -259,6 +259,18 @@ loadlib(void) Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i].file, library[i].objref); objfile(library[i].file, library[i].pkg); } + + // We've loaded all the code now. + // If there are no dynamic libraries needed, gcc disables dynamic linking. + // Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13) + // assumes that a dynamic binary always refers to at least one dynamic library. + // Rather than be a source of test cases for glibc, disable dynamic linking + // the same way that gcc would. + // + // Exception: on OS X, programs such as Shark only work with dynamic + // binaries, so leave it enabled on OS X (Mach-O) binaries. + if(!havedynamic && HEADTYPE != Hdarwin) + debug['d'] = 1; } /* diff --git a/src/cmd/ld/lib.h b/src/cmd/ld/lib.h index 8b603a04a..cd4608085 100644 --- a/src/cmd/ld/lib.h +++ b/src/cmd/ld/lib.h @@ -122,6 +122,7 @@ EXTERN char* outfile; EXTERN int32 nsymbol; EXTERN char* thestring; EXTERN int ndynexp; +EXTERN int havedynamic; EXTERN Segment segtext; EXTERN Segment segdata; @@ -185,6 +186,7 @@ vlong addsize(Sym*, Sym*); vlong adduint8(Sym*, uint8); vlong adduint16(Sym*, uint16); void asmsym(void); +void asmelfsym32(void); void asmelfsym64(void); void asmplan9sym(void); void strnput(char*, int); diff --git a/src/cmd/ld/pe.c b/src/cmd/ld/pe.c index d523ca9c5..1c0c66538 100644 --- a/src/cmd/ld/pe.c +++ b/src/cmd/ld/pe.c @@ -484,13 +484,13 @@ asmbpe(void) d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; + if(!debug['s']) + dwarfaddpeheaders(); + addimports(nextfileoff, d); addexports(nextfileoff); - if(!debug['s']) - dwarfaddpeheaders(); - addsymtable(); fh.NumberOfSections = nsect; diff --git a/src/cmd/prof/gopprof b/src/cmd/prof/gopprof index 8fa00cbe8..8863fc623 100755 --- a/src/cmd/prof/gopprof +++ b/src/cmd/prof/gopprof @@ -2880,17 +2880,18 @@ sub FetchSymbols { my @toask = @pcs; while (@toask > 0) { my $n = @toask; - if ($n > 49) { $n = 49; } + # NOTE(rsc): Limiting the number of PCs requested per round + # used to be necessary, but I think it was a bug in + # debug/pprof/symbol's implementation. Leaving here + # in case I am wrong. + # if ($n > 49) { $n = 49; } my @thisround = @toask[0..$n]; -my $t = @toask; -print STDERR "$n $t\n"; @toask = @toask[($n+1)..(@toask-1)]; my $post_data = join("+", sort((map {"0x" . "$_"} @thisround))); open(POSTFILE, ">$main::tmpfile_sym"); print POSTFILE $post_data; close(POSTFILE); -print STDERR "SYMBL!\n"; my $url = SymbolPageURL(); $url = ResolveRedirectionForCurl($url); my $command_line = "$CURL -sd '\@$main::tmpfile_sym' '$url'"; |